C枚举的Java代表
编译器编写的C。
typedef enum {
SOME_OP,
ANOTHER_OP,
//Etc.
} Operations;
我
uint8_t* opsAndArgs;
Java a intecode
{SOME_OP, 42, ANOTHER_OP, 99, 03, DIFFERENT_OP, RANDOM_OP, 14, etc.}
正在移植到 C程序中的功能通过OPSANDARGS和打开操作员进行迭代,适当地消费参数:
int i = 0;
while (i < opsAndArgs.length) {
switch (opsAndArgs[i] {
case SOME_OP:
handleSomeOp(opsAndArgs[i+1]);
i = i + 2; break;
case ANOTHER_OP:
handleAnotherOp(opsAndArgs[i+1], opsAndArgs[i+2]);
i = i + 3; break;
case DIFFERENT_OP:
handleDifferentOp();
i = i + 1; break;
Etc.
}
}
有没有办法在Java中做同样的事情?即,创建一个枚举,我可以将其混合成具有数字值的数组,并且仍然可以在将剩余值视为参数的同时打开枚举定义的运算符?
似乎原始程序正在利用C枚举的某些功能,使它们与UINT8_T值可混合。
I am porting to Java a bytecode compiler written in C. In the C implementation, the set of operations is represented in an enum:
typedef enum {
SOME_OP,
ANOTHER_OP,
//Etc.
} Operations;
Operations are then mixed with numeric arguments in an array defined as:
uint8_t* opsAndArgs;
For example, opsAndArgs might hold:
{SOME_OP, 42, ANOTHER_OP, 99, 03, DIFFERENT_OP, RANDOM_OP, 14, etc.}
Finally, a function in the C program iterates through opsAndArgs and switches on operators, consuming arguments as appropriate:
int i = 0;
while (i < opsAndArgs.length) {
switch (opsAndArgs[i] {
case SOME_OP:
handleSomeOp(opsAndArgs[i+1]);
i = i + 2; break;
case ANOTHER_OP:
handleAnotherOp(opsAndArgs[i+1], opsAndArgs[i+2]);
i = i + 3; break;
case DIFFERENT_OP:
handleDifferentOp();
i = i + 1; break;
Etc.
}
}
Is there a way I can do the same thing in Java? I.e., create an Enum that I can mix into an array with numeric values, and still have the ability to switch on Enum-defined operators while treating the remaining values as arguments?
It seems like the original program is taking advantage of some feature of C enums such that they are mix-able with uint8_t values.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
与C中不同,Java中的枚举是一个对象。这意味着将它们与数字混合的唯一方法是与
list&lt; object&gt;
或object []
。每个枚举确实都有一个
ordinal()
值,即int。这些不是编译时常数,因此您不能在开关语句中使用它们*。我认为您有一些选项:
list&lt; object&gt;
/object []
解决方案。如果仅执行打开操作,则可以使用instance Of
和switch> switch
ordinal()
作为常数,因为如果您更改枚举的顺序,序数值也会更改。我认为您要问自己的主要问题是:您是否需要枚举?还是常数班足够好?因为这绝对是解决方案的更容易。
* 然而?我没有完全最新的速度,以切换模式匹配的最新更改...
**在Java 16中最终确定语法。在较旧版本中,使用
opsandargs [i] Instanceof操作
在组合中在if中具有新变量:操作操作=(操作)opsandargs [i];
Unlike in C, an enum in Java is an object. That means that the only way to mix the them with numbers is with a
List<Object>
orObject[]
.Every enum does have an
ordinal()
value that is an int. These are not compile-time constants though, so you can't use them in switch statements*.I think that you have some options:
List<Object>
/Object[]
solution. If you only perform switching on the operations, you can do this with a combination ofinstanceof
andswitch
ordinal()
as constants because if you change the order of enum constants the ordinal values change as well.I think the main question you have to ask yourself is: do you need an enum? Or is the constants class good enough? Because that's definitely the easier of the solutions.
* Yet? I'm not fully up-to-speed with the latest changes to switch pattern matching...
** That's syntax finalized in Java 16. In older versions, use
opsAndArgs[i] instanceof Operation
in combination with a new variable inside the if:Operation operation = (Operation) opsAndArgs[i];
从我的角度来看:
保持C字节代码解释器的结构,否则生活变得太复杂了!
opsandargs
必须是字节数组。我们在这里谈论Java字节代码。某些值必须解释为字节,有些值为短裤,并且程序计数器需要以字节大小的步骤前进。使用
静态最终字节
for opcodes。From my point of view:
Keep the structure of the C byte code interpreter, else life gets too complicated!
opsAndArgs
has to be a byte array. We are talking about Java byte code here. Some values have to be interpreted as bytes, some as shorts, ... and the program counter needs to advance in byte-sized steps.Use
static final byte
for opcodes.这是Java的一个工作解决方案。显然,有些事情不清楚(例如,我不知道您的
Handlexxxxop
方法做了什么),因此进行了自由。否则,这在Java 17中可以正常工作。我们创建一个称为
value
的通用接口,以便我们可以为我们的list&lt; value&gt;
具有可接受值的域。然后,我们将其密封,因此只有我们允许的类型才能被视为value
。这两种类型是参数
和操作
。我们还拥有一个方法aslist
,可以处理您在问题中描述的数组。现在,您可以将操作和参数作为参数传递。如果您想传递some_op
,则可以将其传递为operation.some_op
“ some_op” 。该方法当前可以处理两种方式,但是我选择以String
的方式传递每个操作。参数也一样。如果您想传递42
,则可以将其作为新参数(42)
将其传递给,或者可以将其作为int 通过
42
。该方法当前可以处理两种方式,但是我选择以int
的方式传递每个参数。操作
是enum
,它保留了您定义的所有操作。如果要添加更多操作,只需将它们添加到此枚举中,进行编译,然后更新任何现在失败编译的交换语句。参数
是记录
保存参数。拥有明确的类型有助于我们在在一起时将参数与操作分开。主要方法基本上以相同的方式收集值,然后使用我们的
list&lt; value&gt;值
作为参数。calculateresult
基本上是开关语句,而您在原始问题中有循环。这是大多数自由的地方。而且您的开关案例没有指定参数遇到的情况,因此我构建了我的解决方案,以默默地忽略switch
语句中的参数。Here's a working solution in Java. Obviously, there are some things that were unclear (for example, I don't know what your
handleXXXXOp
methods do), so liberties were taken. Otherwise, this works just fine in Java 17.We create a common interface called
Value
, so that we can have a domain of acceptable values for ourList<Value>
. Then, we make it sealed, so that only the types we allow can be considered aValue
. Those 2 types areArgument
andOperation
. We also have a methodasList
that handles taking in the array that you described in your question. Now, you can pass in your operations and arguments as parameters. If you wanted to pass inSOME_OP
, you can either pass it in asOperation.SOME_OP
or as aString
via"SOME_OP"
. The method can handle both ways currently, but I am choosing to pass in each operation as aString
. Same for the arguments. If you wanted to pass in42
, you could either pass it in asnew Argument(42)
, or you could pass it in naked as anint
via42
. The method can handle both ways currently, but I am choosing to pass in each argument as anint
.Operation
is anenum
that holds all of the operations you defined. If you want to add more operations, simply add them to this enum, compile, then update any of the switch statements that now fail compilation.Argument
is arecord
that holds arguments. Having it be an explicit type helps us separate the arguments from the operations when they are together.The main method gathers up the values in basically the same way you did, then calls the method
calculateResult
, with ourList<Value> values
as the parameter.calculateResult
is basically the switch statement and while loop that you had in your original question. This is where most of the liberties were taken. And your switch case didn't specify what happens when it comes across an argument, so I built my solution to silently ignore arguments in theswitch
statement.