我们重构了模型中使用的枚举以包含新值。现在,当应用程序执行时(使用旧应用程序创建的数据库文件),一些 switch/case 语句的行为非常奇怪。
调试变量 View 显示,例如枚举的值为“OLD”,但调试器会进入“case NEW:”行。
有什么想法吗?干杯!
更新:
以下代码
ObjectSet<Project> set = db.query(Project.class);
System.out.println("Found " + set.size());
for (Project prj : set) {
// this line makes no difference
ProjectStatus otherStatus = ProjectStatus.valueOf(prj.getStatus().name());
// debug
System.out.println(otherStatus.name());
// decide via switch/case
switch (otherStatus) {
case A:
System.out.println("Project status is A (switch/case)");
break;
case B:
System.out.println("Project status is B (switch/case)");
break;
}
// decide via if
if (otherStatus == ProjectStatus.A) {
System.out.println("Project status is A (if ==)");
}
else if (otherStatus == ProjectStatus.B) {
System.out.println("Project status is B (if ==)");
}
}
产生输出
Found 1
B
Project status is B (if ==)
我们尝试了 db4o 6.4 和 7.12
此外,根据枚举重构的类型,如果我们删除枚举值,则会引发以下异常:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at Main.$SWITCH_TABLE$model$ProjectStatus(Main.java:8)
at Main.main(Main.java:37)
最佳答案
所以我可以观察到这种行为:
我们有一个这样的枚举:
public enum SomeState {
One,
Two
}
和一个 switch 语句:
switch(object.getState()){
case One: doSomething("State One");break;
case Two: doSomething("State Two");break;
}
我们存储了一个状态为“Two”的对象,因此它将“切换”到第二种情况。
现在我们重构枚举。我们重命名第二个值并添加一个新值:
public enum SomeState {
One,
NewTwo,
OldTwo
}
以及新的 switch 语句:
switch(object.getState()){
case One: doSomething("State One");break;
case NewTwo: doSomething("State New Two");break;
case OldTwo: doSomething("State Old Two");break;
}
现在该对象将“切换”到“NewTwo”状态,这是完全错误的!
不幸的是,有一个错误:我在此处添加了一个条目 (http://tracker.db4o.com/browse/COR-2268)。根本问题是 db4o 的奇怪枚举处理。它实际上存储枚举对象本身。当从数据库加载对象时,它会恢复枚举状态,甚至是静态变量中的内容!如果同时进行了重构,那么整个事情就会变得一团糟。基本上我们使用多个具有相同序数和困惑名称的枚举。
目前我建议避免使用枚举(在 Java 上。在 .Net 中,db4o 枚举处理有效)=(。
编辑:迁移建议:您可以这样做:将“重构”枚举作为完整的新值添加到枚举中。然后加载包含该枚举的所有对象并将值更改为新值。之后,您删除旧的枚举值。
关于java - 重构枚举后 db4o 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8405706/