Scala 2.9.1 编译器会丢弃类型参数信息吗?
我正在编写一些 Java 代码,这些代码依赖于一些 Scala 代码(我也编写过)。如果 Scala 使用 2.8.0 编译,则尝试提供参数化类型的参数似乎可以工作,但如果我使用 2.9.1,则失败。
(简化的)Scala 代码大致如下所示:
package test
import collection.JavaConversions._
class SomeClass {
def foo(numbers: java.util.Set[Long]) {
numbers.foreach(println(_))
}
}
它可以在 2.8.0 和 2.9.1 编译器中顺利编译。 Java 代码看起来像这样:
package test;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class App {
public static void main(String[] args) {
new SomeClass().foo(new HashSet<Long>(Arrays.asList(1L, 2L, 3L)));
}
}
如果我使用 2.8.0 编译器编译 Scala,那么 Java 将顺利编译(使用 Java 的 1.6.0_26 编译器)。但是,如果我使用 2.9.1 编译 Scala,则 Java 编译器会失败并显示以下错误:
test\App.java:16: foo(java.util.Set<java.lang.Object>) in test.SomeClass cannot be applied to (java.util.HashSet<java.lang.Long>)
sc.foo(new HashSet<Long>(Arrays.asList(1L, 2L, 3L)));
^
1 error
因此,看来虽然 Scala 2.8.0 在字节码中保留了 numbers
类型为 Set
,2.9.1 编译器会发出字节码,其中 numbers
是 Set
这是一个错误吗?这是故意改变的不幸的(对我来说)副作用吗? (Scala 变更日志提到“... JavaConversions 实现更顺畅的互操作”)。如果是这样,我能做些什么来让它在 2.9.1 上工作吗?
I'm writing some Java code that depends on some Scala code (that I have also written). Trying to supply an argument with a parameterized type seems to work if the Scala is compiled with 2.8.0 but fail if I use 2.9.1.
The (simplified) Scala code looks roughly like this:
package test
import collection.JavaConversions._
class SomeClass {
def foo(numbers: java.util.Set[Long]) {
numbers.foreach(println(_))
}
}
This compiles happily with both the 2.8.0 and 2.9.1 compilers. The Java code looks something like this:
package test;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class App {
public static void main(String[] args) {
new SomeClass().foo(new HashSet<Long>(Arrays.asList(1L, 2L, 3L)));
}
}
If I compile the Scala with the 2.8.0 compiler, then the Java will compile happily (with Java's 1.6.0_26 compiler). However, if I compile the Scala with 2.9.1, then the Java compiler fails with the error:
test\App.java:16: foo(java.util.Set<java.lang.Object>) in test.SomeClass cannot be applied to (java.util.HashSet<java.lang.Long>)
sc.foo(new HashSet<Long>(Arrays.asList(1L, 2L, 3L)));
^
1 error
So it seems that while Scala 2.8.0 retains in the bytecode the information that numbers
is of type Set<Long>
, the 2.9.1 compiler emits bytecode where numbers
is a Set<Object>
.
Is this a bug? Is it an unfortunate (for me) side-effect of a deliberate change? (The Scala changelog mentions "various fixes in ... JavaConversions
for smoother interoperation"). If so, is there anything I can do to get this to work with 2.9.1?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,因为我在评论中的盲目尝试被证明是幸运的,与答案相同。
它与
java.lang.Long
一起工作,与scala的Long
不一样。值得注意的是,Set[java.lang.Long]
可以包含null
,而Set[Long]
不应该包含(除非类型系统被绕过)某种未经检查的演员阵容)。尽管Set
在这两种情况下都被实现为包含引用;在第二种情况下,它们保证不为空。识别
Set[Long]
和Set[java.lang.Long]
会在类型系统中打开一个漏洞。话虽这么说,我不知道这个改变是否是有意为之。Ok, as my shot in the dark in comment proved lucky, same as an answer.
It works with
java.lang.Long
is not the same as theLong
of scala. Notably,Set[java.lang.Long]
can containnull
, aSet[Long]
should not (unless the type system was circumvented with some sort of unchecked cast). This is in spite of theSet
being implemented as containing references in both case; in the second case, they are guaranteed to be non null.Identifying
Set[Long]
andSet[java.lang.Long]
opens a loophole in the type system. That being said, I don't know whether the change was intended.简短的回答,这很复杂。 Scala 类型系统中的
Any
是一个伟大的统一体,但当您身处 Java 领域时,这完全是虚构的。2.9 之前采取的简化视图是考虑不周并且破坏了东西的。
要了解问题的棘手性质,请阅读邮件列表中 Paul Phillips 的帐户:
http://www.scala-lang.org/node/8888
http://www.scala-lang.org/node/8980
Short answer, it's complicated.
Any
in the Scala type system is a great unifier, but a complete fiction by the time you're in Java-land.The simplified view taken prior to 2.9 was ill-conceived and broke things.
To get a feel for the rock-and-a-hard-place nature of the problem, read Paul Phillips' accounts from the mailing lists:
http://www.scala-lang.org/node/9157
http://www.scala-lang.org/node/8888
http://www.scala-lang.org/node/8980