在Java中实现跳转表
如何将这个简单计算器程序中的switch/case语句转换成跳转表在Java中实现跳转表,java,jump-table,Java,Jump Table,如何将这个简单计算器程序中的switch/case语句转换成跳转表 import java.lang.*; import java.util.*; public class Calculator { private int solution; private static int x, y, ops; private char operators; public Calculator() { solution = 0; }
import java.lang.*;
import java.util.*;
public class Calculator
{
private int solution;
private static int x, y, ops;
private char operators;
public Calculator()
{
solution = 0;
}
public int addition(int x, int y)
{
return x + y;
}
public int subtraction(int x, int y)
{
return x - y;
}
public int multiplication(int x, int y)
{
return x * y;
}
public int division(int x, int y)
{
solution = x / y;
return solution;
}
public void calc(int ops){
Scanner operands = new Scanner(System.in);
System.out.println("operand 1: ");
x = operands.nextInt();
System.out.println("operand 2: ");
y = operands.nextInt();
System.out.println("Solution: ");
switch(ops)
{
case(1):
System.out.println(addition(x, y));
break;
case(2):
System.out.println(subtraction(x, y));
break;
case(3):
System.out.println(multiplication(x, y));
break;
case(4):
System.out.println(division(x, y));
break;
}
}
public static void main (String[] args)
{
System.out.println("What operation? ('+', '-', '*', '/')");
System.out.println(" Enter 1 for Addition");
System.out.println(" Enter 2 for Subtraction");
System.out.println(" Enter 3 for Multiplication");
System.out.println(" Enter 4 for Division");
Scanner operation = new Scanner(System.in);
ops = operation.nextInt();
Calculator calc = new Calculator();
calc.calc(ops);
}
}
老实说,我不知道跳转表到底是什么(在网上找不到任何解释),所以我不知道它与switch/case语句有何不同
旁注:这段代码只处理整数,所以如果你除以5/3,它会给你1。如何轻松地将其更改为浮点/双精度。好吧,我不知道什么是跳转表,但如果您想控制另一种类型的数字,可以更改参数,例如您的方法:
public int addition(int x, int y)
{
return x + y;
}
如果你想加倍-->
但我强烈建议您每隔一个类从Number扩展一次就使用类型Number
例:
如前所述,跳转表是指向函数的偏移量/指针数组。与C/C++不同,Java实际上没有函数指针() 但是你可以假装,用面向对象的方法来做。用一个方法(f)定义一个基类(Funky)。派生多个子对象,每个子对象对应一个函数操作(+、-、*、/,等等),并为每个子对象创建一个对象(毕竟它只是一个接口),然后将该子对象存储到类型数组中(Funky) 在表中查找该操作,并对参数调用该方法 例如: 定义一个基类(或者一个接口,它会让你更快乐?)。请注意,如果扩展类,可以使用基类方法作为默认方法(生成错误消息或引发异常) 哦,您将需要实例,并将它们加载到一个数组(jumptable)中
有些技术对某些语言来说是惯用的,跳转表更像是一种系统,而不是Java,而不是真正的Java惯用语 这是一个老生常谈的问题,但我认为它对于说明你可以做些什么仍然有价值。基本上,创建一个接口,其唯一目的是为操作数组提供类型,然后使用方法引用填充操作数组。之后,您可以使用索引选择正确的操作。我对OP的代码做了最小的修改,这样比较就最容易了:
import java.util.Scanner;
public class Calculator
{
//
// Create an interface to use as Type for
// operations array.
//
private interface BinaryOperation {
int performOperation(int a, int b);
}
//
// Array has one unused element to make coding easier
// and use operation as a direct index.
// You can replace with 4 element array easily.
//
BinaryOperation[] operations = new BinaryOperation[5];
private int solution;
private static int x, y, ops;
private char operators;
public Calculator()
{
solution = 0;
//
// Initialize jump table using method references.
//
operations[1] = this::addition;
operations[2] = this::subtraction;
operations[3] = this::multiplication;
operations[4] = this::division;
}
public int addition(int x, int y)
{
return x + y;
}
public int subtraction(int x, int y)
{
return x - y;
}
public int multiplication(int x, int y)
{
return x * y;
}
public int division(int x, int y)
{
solution = x / y;
return solution;
}
public void calc(int ops){
Scanner operands = new Scanner(System.in);
System.out.println("operand 1: ");
x = operands.nextInt();
System.out.println("operand 2: ");
y = operands.nextInt();
System.out.println("Solution: ");
//
// Call binary operation through jump table
//
System.out.println(operations[ops].performOperation(x, y));
}
public static void main (String[] args)
{
System.out.println("What operation? ('+', '-', '*', '/')");
System.out.println(" Enter 1 for Addition");
System.out.println(" Enter 2 for Subtraction");
System.out.println(" Enter 3 for Multiplication");
System.out.println(" Enter 4 for Division");
Scanner operation = new Scanner(System.in);
ops = operation.nextInt();
Calculator calc = new Calculator();
calc.calc(ops);
}
}
如果您使用的是支持lambdas的Java版本,那么更符合作为“跳转表”实现要求的解决方案将使用实际的跳转表,该跳转表将运算符代码映射到实现每个操作数的lambda表达式 这是一种令人愉快的方式,不仅可以消除笨拙的switch语句,而且可以生成更易于维护和扩展的代码。以后可以很容易地添加新的操作数,而无需对计算器实现进行任何更改。只需实现新操作符及其命名方法,并将其添加到跳转表中。您的计算器将自动支持新的操作数
import com.google.common.collect.ImmutableMap;
import java.lang.*;
import java.util.*;
public class Calculator
{
private static final Map<Integer,BinaryOperator<Integer>> evaluators = ImmutableMap.<Integer, BinaryOperator<Integer>>builder()
.put(1, (Integer x, Integer y) -> new IntAddition().evaluateFor(x,y))
.put(2, (Integer x, Integer y) -> new IntSubtraction().evaluateFor(x,y))
.put(3, (Integer x, Integer y) -> new IntMultiplication().evaluateFor(x,y))
.put(4, (Integer x, Integer y) -> new IntDivision().evaluateFor(x,y))
.build();
private static final Map<Integer,Nameable> names = ImmutableMap.<Integer, Nameable>builder()
.put(1, () -> new IntAddition().getName())
.put(2, () -> new IntSubtraction().getName())
.put(3, () -> new IntMultiplication().getName())
.put(4, () -> new IntDivision().getName())
.build();
private int solution;
private static int x, y, ops;
public Calculator()
{
solution = 0;
}
public void calc(int opcode)
{
Scanner operands = new Scanner(System.in);
System.out.println("Enter operand 1: ");
x = operands.nextInt();
System.out.println("Enter operand 2: ");
y = operands.nextInt();
System.out.print("Solution: ");
System.out.println(evaluators.get(opcode).evaluateFor(x, y));
}
public static void main(String[] args)
{
System.out.println("What operation?");
for (Integer opcode : evaluators.keySet())
{
System.out.println(String.format(" Enter %d for %s", opcode, names.get(opcode).getName()));
}
Scanner operation = new Scanner(System.in);
ops = operation.nextInt();
Calculator calc = new Calculator();
calc.calc(ops);
}
interface Nameable
{
String getName();
}
interface BinaryOperator<T>
{
T evaluateFor(T x, T y);
}
static class IntAddition implements BinaryOperator<Integer>, Nameable
{
IntAddition() { }
public Integer evaluateFor(Integer x, Integer y)
{
return x + y;
}
public String getName()
{
return "Addition";
}
}
static class IntSubtraction implements BinaryOperator<Integer>, Nameable
{
IntSubtraction() { }
public Integer evaluateFor(Integer x, Integer y)
{
return x - y;
}
public String getName()
{
return "Subtraction";
}
}
static class IntMultiplication implements BinaryOperator<Integer>, Nameable
{
IntMultiplication() { }
public Integer evaluateFor(Integer x, Integer y)
{
return x * y;
}
public String getName()
{
return "Multiplication";
}
}
static class IntDivision implements BinaryOperator<Integer>, Nameable
{
IntDivision() { }
public Integer evaluateFor(Integer x, Integer y)
{
return x / y;
}
public String getName()
{
return "Division";
}
}
}
import com.google.common.collect.ImmutableMap;
导入java.lang.*;
导入java.util.*;
公共类计算器
{
私有静态最终映射计算器=ImmutableMap.builder()
.put(1,(整数x,整数y)->new IntAddition().evaluateFor(x,y))
.put(2,(整数x,整数y)->新的整数减法().evaluateFor(x,y))
.put(3,(整数x,整数y)->新的整数乘法().evaluateFor(x,y))
.put(4,(整数x,整数y)->new IntDivision().evaluateFor(x,y))
.build();
私有静态最终映射名称=ImmutableMap.builder()
.put(1,()->new IntAddition().getName())
.put(2,()->new int减法().getName())
.put(3,()->new intmultiply().getName())
.put(4,()->new IntDivision().getName())
.build();
私有int解决方案;
专用静态整数x,y,ops;
公共计算器()
{
溶液=0;
}
公共无效计算(内部操作码)
{
扫描仪操作数=新扫描仪(System.in);
System.out.println(“输入操作数1:”);
x=操作数。nextInt();
System.out.println(“输入操作数2:”);
y=操作数。nextInt();
系统输出打印(“解决方案:”);
System.out.println(evaluators.get(操作码).evaluateFor(x,y));
}
公共静态void main(字符串[]args)
{
System.out.println(“什么操作?”);
for(整数操作码:evaluators.keySet())
{
System.out.println(String.format(“为%s输入%d”,操作码,名称.get(操作码).getName()));
}
扫描仪操作=新扫描仪(System.in);
ops=operation.nextInt();
计算器计算器=新计算器();
计算(ops);
}
可命名接口
{
字符串getName();
}
接口二进制运算符
{
T评价因子(tx,ty);
}
静态类IntAddition实现了BinaryOperator,可命名
{
插入(){}
公共整数计算器(整数x,整数y)
{
返回x+y;
}
公共字符串getName()
{
返回“加法”;
}
}
静态类IntDetraction实现二进制运算符,可命名
{
整数减法(){}
公共整数计算器(整数x,整数y)
{
返回x-y;
}
公共字符串getName()
{
返回“减法”;
}
}
静态类IntMultiplication实现二进制运算符,可命名
{
IntMultiplication(){}
公共整数计算器(整数x,整数y)
{
返回x*y;
}
公共字符串getName()
{
返回“乘法”;
}
}
静态类IntDivision实现BinaryOperator,可命名
{
IntDivision(){}
公共整数计算器(整数x,整数y)
{
返回x/y;
}
公共字符串getName()
{
返回“除法”;
}
}
}
跳转表:。这都是指向函数的指针,而不是你想要的东西
public class X
//or, public interface X
{
//method
Z fun(Z z1, Z z2)
{
//nothing to see here
}
}
class X1 extends X //or, implements X
{
public Z fun(Z z1, Z z2)
{
//variant1 stuff here
}
}
...
public class Xn extends X //or, implements X
{
public Z fun(Z z1, Z z2)
{
//variantn stuff here
}
}
import java.util.Scanner;
public class Calculator
{
//
// Create an interface to use as Type for
// operations array.
//
private interface BinaryOperation {
int performOperation(int a, int b);
}
//
// Array has one unused element to make coding easier
// and use operation as a direct index.
// You can replace with 4 element array easily.
//
BinaryOperation[] operations = new BinaryOperation[5];
private int solution;
private static int x, y, ops;
private char operators;
public Calculator()
{
solution = 0;
//
// Initialize jump table using method references.
//
operations[1] = this::addition;
operations[2] = this::subtraction;
operations[3] = this::multiplication;
operations[4] = this::division;
}
public int addition(int x, int y)
{
return x + y;
}
public int subtraction(int x, int y)
{
return x - y;
}
public int multiplication(int x, int y)
{
return x * y;
}
public int division(int x, int y)
{
solution = x / y;
return solution;
}
public void calc(int ops){
Scanner operands = new Scanner(System.in);
System.out.println("operand 1: ");
x = operands.nextInt();
System.out.println("operand 2: ");
y = operands.nextInt();
System.out.println("Solution: ");
//
// Call binary operation through jump table
//
System.out.println(operations[ops].performOperation(x, y));
}
public static void main (String[] args)
{
System.out.println("What operation? ('+', '-', '*', '/')");
System.out.println(" Enter 1 for Addition");
System.out.println(" Enter 2 for Subtraction");
System.out.println(" Enter 3 for Multiplication");
System.out.println(" Enter 4 for Division");
Scanner operation = new Scanner(System.in);
ops = operation.nextInt();
Calculator calc = new Calculator();
calc.calc(ops);
}
}
import com.google.common.collect.ImmutableMap;
import java.lang.*;
import java.util.*;
public class Calculator
{
private static final Map<Integer,BinaryOperator<Integer>> evaluators = ImmutableMap.<Integer, BinaryOperator<Integer>>builder()
.put(1, (Integer x, Integer y) -> new IntAddition().evaluateFor(x,y))
.put(2, (Integer x, Integer y) -> new IntSubtraction().evaluateFor(x,y))
.put(3, (Integer x, Integer y) -> new IntMultiplication().evaluateFor(x,y))
.put(4, (Integer x, Integer y) -> new IntDivision().evaluateFor(x,y))
.build();
private static final Map<Integer,Nameable> names = ImmutableMap.<Integer, Nameable>builder()
.put(1, () -> new IntAddition().getName())
.put(2, () -> new IntSubtraction().getName())
.put(3, () -> new IntMultiplication().getName())
.put(4, () -> new IntDivision().getName())
.build();
private int solution;
private static int x, y, ops;
public Calculator()
{
solution = 0;
}
public void calc(int opcode)
{
Scanner operands = new Scanner(System.in);
System.out.println("Enter operand 1: ");
x = operands.nextInt();
System.out.println("Enter operand 2: ");
y = operands.nextInt();
System.out.print("Solution: ");
System.out.println(evaluators.get(opcode).evaluateFor(x, y));
}
public static void main(String[] args)
{
System.out.println("What operation?");
for (Integer opcode : evaluators.keySet())
{
System.out.println(String.format(" Enter %d for %s", opcode, names.get(opcode).getName()));
}
Scanner operation = new Scanner(System.in);
ops = operation.nextInt();
Calculator calc = new Calculator();
calc.calc(ops);
}
interface Nameable
{
String getName();
}
interface BinaryOperator<T>
{
T evaluateFor(T x, T y);
}
static class IntAddition implements BinaryOperator<Integer>, Nameable
{
IntAddition() { }
public Integer evaluateFor(Integer x, Integer y)
{
return x + y;
}
public String getName()
{
return "Addition";
}
}
static class IntSubtraction implements BinaryOperator<Integer>, Nameable
{
IntSubtraction() { }
public Integer evaluateFor(Integer x, Integer y)
{
return x - y;
}
public String getName()
{
return "Subtraction";
}
}
static class IntMultiplication implements BinaryOperator<Integer>, Nameable
{
IntMultiplication() { }
public Integer evaluateFor(Integer x, Integer y)
{
return x * y;
}
public String getName()
{
return "Multiplication";
}
}
static class IntDivision implements BinaryOperator<Integer>, Nameable
{
IntDivision() { }
public Integer evaluateFor(Integer x, Integer y)
{
return x / y;
}
public String getName()
{
return "Division";
}
}
}