Scala 2.9.1 编译器会丢弃类型参数信息吗?

发布于 2024-12-08 19:53:28 字数 1379 浏览 0 评论 0原文

我正在编写一些 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 编译器会发出字节码,其中 numbersSet

这是一个错误吗?这是故意改变的不幸的(对我来说)副作用吗? (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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏雨凉 2024-12-15 19:53:28

好吧,因为我在评论中的盲目尝试被证明是幸运的,与答案相同。

它与

def foo(numbers: java.util.Set[java.lang.Long])

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

def foo(numbers: java.util.Set[java.lang.Long])

java.lang.Long is not the same as the Long of scala. Notably, Set[java.lang.Long] can contain null, a Set[Long] should not (unless the type system was circumvented with some sort of unchecked cast). This is in spite of the Set being implemented as containing references in both case; in the second case, they are guaranteed to be non null.

Identifying Set[Long] and Set[java.lang.Long] opens a loophole in the type system. That being said, I don't know whether the change was intended.

活雷疯 2024-12-15 19:53:28

简短的回答,这很复杂。 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文