【发布时间】:2021-01-12 16:11:29
【问题描述】:
在长期使用 C、C++ 和 C# 之后,我最近开始使用 Java。我无法理解 Java 枚举应该如何工作。 经过一些研究,我创建了以下内容:
public class RedRoad implements Serializable, Parcelable
{
// ... other parts removed for clarity
public enum State
{
NOT_STARTED(0),
PART_DONE(1),
COMPLETED(2);
private int value;
private State(int value) {
this.value = value;
}
public void setValue(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
}
我使用 getValue() 将这些 State 值作为整数存储在 sqlite 数据库中,使用 setValue() 检索它们,然后通过广播发送生成的“Road”对象。然后我这样做:
switch (road.state) {
case COMPLETED:
pline.getOutlinePaint().setColor(Color.GREEN); break;
case PART_DONE:
pline.getOutlinePaint().setColor(Color.argb(0xFF,0xFF,0xA5,0x00)); break;
case NOT_STARTED:
default: pline.getOutlinePaint().setColor(Color.RED);
}
但前两种情况永远不会被调用,即使我已经检查过 road.state.getValue() 有时是 1 ,而不是零。 此外,如果我将切换代码更改为:
switch (road.state.getValue()) {
case 2:
pline.getOutlinePaint().setColor(Color.GREEN); break;
case 1:
Log.d("*** road state ", String.valueOf(road.state.getValue()));
Log.e("*** road state ", String.valueOf(road.state));
pline.getOutlinePaint().setColor(Color.argb(0xFF,0xFF,0xA5,0x00));
break;
case 0:
default:
pline.getOutlinePaint().setColor(Color.RED);
}
然后根据要求设置颜色。我在日志中得到了一个非凡的输出:
D/*** road state: 1
E/*** road state: NOT_STARTED
这怎么可能? NOT_STARTED 被定义为零!
[编辑] 后来发现,除了上述之外(我可以找到解决方法),从异步任务发送到主要活动后,值不正确('Road'类是可打包的)。如果我在发送之前记录 state.getValue() ,然后在接收之后再次记录,任何非零值都已更改为零。
【问题讨论】:
-
我注意到你的枚举中有二传手。枚举值应该是不可变的;你应该删除那些。
-
@AndyTurner 取决于我想它们的用途。我见过枚举用作存储值的单例对象。这并不是完全错误,但“每个 JVM 一个实例”的事情确实需要谨慎
-
@JeroenSteenbeeke 这些值在规范中称为Enum Constants。它们旨在成为常量。 More here.
-
@AndyTurner 该规范还允许非最终成员,因此暗示了不变性但不是必需的。我同意在几乎所有情况下,拥有可变枚举都是一个坏主意,这正是您第二个链接中的原因。但我们都知道,我们开发人员有时会提出非正统的代码(我给出的单例示例来自 Effective Java 的第 2 版)。也就是说:您说得对,需要删除问题中的设置器。
-
@Andy Turner,好的,但是在数据库中存储和检索这些值的正确方法是什么?