我有一个简单的应用程序:
object Test extends App {
implicit def t2mapper[X, X0 <: X, X1 <: X](t: (X0, X1)) = new {
def map[R](f: X => R) = (f(t._1), f(t._2))
}
println("Hello!")
val (foo, bar) = (1, 2) map (_ * 2)
println((foo, bar))
}
(t2mapper
来自这个答案。)
代码编译得很好:
$ scalac -version
Scala compiler version 2.9.1 -- Copyright 2002-2011, LAMP/EPFL
$ scalac -unchecked Test.scala
$
但是在运行时,它会抛出一个IllegalAccessError
(在打印之前): Hello!
$ java -版本 java版本“1.6.0_24” OpenJDK 运行时环境 (IcedTea6 1.11.1) (6b24-1.11.1-4ubuntu3) OpenJDK Server VM(build 20.0-b12,混合模式) $ 斯卡拉测试 java.lang.IllegalAccessError:试图从类 Test$delayedInit$body 访问字段 Test$.reflParams$Cache1 在 Test$delayedInit$body.(Test.scala:6) 在 Test$.(Test.scala:1) 在 Test$.(Test.scala) 在 Test.main(Test.scala) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:616) 在 scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:78) 在 scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:24) 在 scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:88) 在 scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:78) 在 scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101) 在 scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:33) 在 scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:40) 在 scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:56) 在 scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:80) 在 scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:89) 在 scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
请注意,最后两行替换为
println((1, 2) map (_ * 2))
或者
val (foo, bar) = (2, 4)
println((foo, bar))
或者
val intermediate = (1, 2) map (_ * 2)
val (foo, bar) = intermediate
println((foo, bar))
(2,4)
它按预期打印。但是当包裹在一个块中时
{
val intermediate = (1, 2) map (_ * 2)
val (foo, bar) = intermediate
println((foo, bar))
}
或者
private val blah = {
val intermediate = (1, 2) map (_ * 2)
val (foo, bar) = intermediate
println((foo, bar))
}
它抛出异常。
为什么第一种和最后一种方法会导致 JVM 在运行时抛出错误?