我们已经重构了我们模型中使用的枚举以包含新值。现在,当应用程序执行时(使用旧应用程序创建的数据库文件),某些switch / case语句表现得非常奇怪。
调试变量视图显示,例如枚举的值为“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)
答案 0 :(得分:2)
所以我可以观察到这种行为:
我们有这样的枚举:
public enum SomeState {
One,
Two
}
和关于此的开关声明:
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枚举处理工作)=(。
编辑:对迁移的建议:您可以这样做:将“重构”枚举作为完整的新值添加到枚举中。然后加载包含该枚举的所有对象,并将值更改为新值。之后,您将删除旧的枚举值。