在Scala工作表中使用自定义枚举时,我收到一个错误:java.lang.ExceptionInInitializeError
更新-2014/9/17 事实证明,如果将在Scala工作表中使用自定义枚举时,我收到一个错误:java.lang.ExceptionInInitializeError,scala,enums,scala-ide,Scala,Enums,Scala Ide,更新-2014/9/17 事实证明,如果将println(Value.Player2)作为第一个命令,则先前更新(从2013年2月19日起)中的解决方案也无法运行;i、 e.序号仍然分配不正确 从那以后,我创造了一个新的世界。实现等待分配序号,直到所有JVM类/对象初始化完成。它还有助于用额外的数据扩展/修饰每个枚举成员,同时对于(反)序列化仍然非常有效 我还创建了一个详细介绍Scala中使用的所有不同枚举模式的示例(包括我在上面提到的要点中的解决方案) 我正在使用的是新安装的(预安装了Sca
println(Value.Player2)
作为第一个命令,则先前更新(从2013年2月19日起)中的解决方案也无法运行;i、 e.序号仍然分配不正确
从那以后,我创造了一个新的世界。实现等待分配序号,直到所有JVM类/对象初始化完成。它还有助于用额外的数据扩展/修饰每个枚举成员,同时对于(反)序列化仍然非常有效
我还创建了一个详细介绍Scala中使用的所有不同枚举模式的示例(包括我在上面提到的要点中的解决方案)
我正在使用的是新安装的(预安装了ScalaIDE的Eclipse)。我使用的是Windows7-64位。我在使用Scala工作表时取得了多种成功。在不到一个小时的时间里,我的机器已经死机三次(完全复位或一次死机)。因此,这可能是Scala工作表中的一个bug。我还不确定,也没有时间追查这个问题。然而,这个枚举问题正在阻止我进行测试 我在Scala工作表中使用以下代码:
package test
import com.stack_overflow.Enum
object WsTempA {
object Value extends Enum {
sealed abstract class Val extends EnumVal
case object Empty extends Val; Empty()
case object Player1 extends Val; Player1()
case object Player2 extends Val; Player2()
}
println(Value.values)
println(Value.Empty)
}
以上方法很好。但是,如果注释掉第一个println,第二行将抛出一个异常:java.lang.ExceptionInInitializerError。我只是一个Scala新手,不明白为什么会发生这种情况。任何帮助都将不胜感激
下面是Scala工作表右侧的堆栈跟踪(左侧已剥离,以便在此处显示):
java.lang.ExceptionInInitializeError
在test.WsTempA$Value$Val处(test.WsTempA.scala:7)
test.WsTempA$Value$Empty$(test.WsTempA.scala:8)
test.WsTempA$Value$Empty$。(test.WsTempA.scala)
在test.WsTempA$$anonfun$main$1.apply$mcV$sp(test.WsTempA.scala:14)
位于org.scalaide.worksheet.runtime.library.WorksheetSupport$$anonfun$$exe
可爱$1.应用$mcV$sp(工作表支持。scala:76)
在org.scalaide.worksheet.runtime.library.WorksheetSupport$重定向(W
工作表支持。scala:65)
在org.scalaide.worksheet.runtime.library.WorksheetSupport$.$execute(Wor
ksheetSupport.scala:75)
在test.WsTempA$.main处(test.WsTempA.scala:11)
在test.WsTempA.main(test.WsTempA.scala)处
原因:java.lang.NullPointerException
test.WsTempA$Value$(test.WsTempA.scala:8)
test.WsTempA$Value$(test.WsTempA.scala)
... 9更多
com.stack_overflow.Enum类来自。为了简单起见,我在这里粘贴了我的版本(以防在复制/粘贴操作中遗漏了一些关键内容):
package com.stack\u溢出
//抄袭https://stackoverflow.com/a/8620085/501113
抽象类枚举{
输入Val(Val)
valuesByName_u+=(toString->theVal)
}
}
}
任何形式的指导都将不胜感激
更新-2013/2/19 在使用Rex Kerr进行了几次循环后,下面是代码的更新版本:
package test
import com.stack_overflow.Enum
object WsTempA {
object Value extends Enum {
sealed abstract class Val extends EnumVal
case object Empty extends Val {Empty.init} // <---changed from ...Val; Empty()
case object Player1 extends Val {Player1.init} // <---changed from ...Val; Player1()
case object Player2 extends Val {Player2.init} // <---changed from ...Val; Player2()
private val init: List[Value.Val] = List(Empty, Player1, Player2) // <---added
}
println(Value.values)
println(Value.Empty)
println(Value.values)
println(Value.Player1)
println(Value.values)
println(Value.Player2)
println(Value.values)
包测试
导入com.stack_overflow.Enum
对象WsTempA{
对象值扩展枚举{
密封抽象类Val扩展了EnumVal
case object Empty扩展Val{Empty.init}/这里有两个问题:一个是由于初始化问题导致代码无法工作,另一个是IDE问题。我将只讨论代码失败
问题是在实际访问Empty
之前需要运行Empty()
,但是访问内部大小写对象不会在外部对象上运行初始值设定项,因为它们只是假装是内部对象的成员。(在值
中没有包含Empty
的变量)
通过运行apply()
方法作为Empty
的初始值设定项的一部分,可以绕过此问题:
object Value extends Enum {
sealed abstract class Val extends EnumVal
case object Empty extends Val { apply() }
case object Player1 extends Val { apply() }
case object Player2 extends Val { apply() }
}
现在您的初始化错误应该消失了。(因为您必须这样做,我建议apply()
实际上是一个错误的名称选择;也许set
或类似的名称会更好(更短)
如果将println
粘贴到main
方法中,下面是字节码在打印值时的样子。值
:
public void main(java.lang.String[]);
Code:
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: getstatic #24; //Field WsTempA$Value$.MODULE$:LWsTempA$Value$;
6: invokevirtual #30; //Method Enum.values:()Lscala/collection/immutable/List;
9: invokevirtual #34; //Method scala/Predef$.println:(Ljava/lang/Object;)V
12: return
注意第3行,在这里您得到了值
本身的一个静态字段(这意味着JVM确保该字段已初始化)
public void main(java.lang.String[]);
Code:
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: getstatic #24; //Field WsTempA$Value$Empty$.MODULE$:LWsTempA$Value$Empty$;
6: invokevirtual #28; //Method scala/Predef$.println:(Ljava/lang/Object;)V
9: return
现在,第3行不是指值,而是指内部对象,这意味着首先调用内部对象的初始值设定项,然后调用外部对象的初始值设定项,然后它看到内部对象的初始值设定项应该完成(但实际上没有完成)…并对其调用一个方法,然后…boom
如果将apply
放在Empty
初始值设定项中,则会保存该初始值设定项,因为值
初始值设定项即使被无序调用,也不再调用Empty
上的方法。因此它奇迹般地工作了。(请确保不引入任何其他方法调用!)您能发布完整的堆栈跟踪吗?:)(如果您无法从UI获取,请在workspace/.metadata/.log中查看)@briTransmisth Tyvm请求。我在上面添加了堆栈跟踪。但是,它在Scala工作表中被截断(缺少9行)。如果您需要我深入查看您提到的日志,我会这样做。我现在已经深入查看了日志,但没有出现此错误。还有一个异常似乎完全不相关。如果您仍然希望我深入查看,请告诉我。无需调用Empty.init
--只需init
即可。此外,我注意到总的来说,his对于Enum来说是一个非常不合适的解决方案,因为您必须将每个项列出两次,并且有大约35个bo字符
object Value extends Enum {
sealed abstract class Val extends EnumVal
case object Empty extends Val { apply() }
case object Player1 extends Val { apply() }
case object Player2 extends Val { apply() }
}
public void main(java.lang.String[]);
Code:
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: getstatic #24; //Field WsTempA$Value$.MODULE$:LWsTempA$Value$;
6: invokevirtual #30; //Method Enum.values:()Lscala/collection/immutable/List;
9: invokevirtual #34; //Method scala/Predef$.println:(Ljava/lang/Object;)V
12: return
public void main(java.lang.String[]);
Code:
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: getstatic #24; //Field WsTempA$Value$Empty$.MODULE$:LWsTempA$Value$Empty$;
6: invokevirtual #28; //Method scala/Predef$.println:(Ljava/lang/Object;)V
9: return