【问题标题】:Simple use of Scala collections from Java not compiling with 2.11简单使用 Java 中的 Scala 集合,而不是用 2.11 编译
【发布时间】:2014-08-24 00:13:00
【问题描述】:

所以我得到了这个超级令人兴奋的 Java 类:

import scala.collection.immutable.Stream;

public class EmptyStreamFactory {
  public static Stream<String> createEmptyStringStream() {
    return Stream.<String>empty();
  }
}

使用类路径上的 2.10.4 scala-library.jar 编译就好了(或 2.9.2,值得一提)。现在我用 2.11 试试:

EmptyStreamFactory.java:5: error: incompatible types
    return Stream.<String>empty();
                               ^
  required: Stream<String>
  found:    GenTraversable
1 error

这有什么意义呢?乍一看,可能与远程相关的唯一区别是 Stream.Empty 在 2.11 中不再扩展 Serializable,但我不明白这会如何导致这个问题。 List 等也会发生同样的事情。

有一个简单的解决方法 - 您可以转换为适当的类型 - 但我想了解这里发生了什么。

(我使用的是 Oracle 的 JDK,版本 1.7.0_67。)

【问题讨论】:

  • Stream.Empty 仍然扩展 Serializable,因为它扩展了 StreamEmpty 上删除的 Serializable 是多余的,所以这不是问题的根源。

标签: java scala scala-2.11


【解决方案1】:

桥接方法的静态转发器本身并未标记为桥接方法,并且无论出于何种原因,java 更喜欢返回 GenTraversable 的那个,因为它有两个可供选择。

classOf[scala.collection.immutable.Stream[_]].getMethods filterNot 
  (_.isBridge) filter (_.getName == "empty") foreach println
public static scala.collection.immutable.Stream scala.collection.immutable.Stream.empty()
public static scala.collection.GenTraversable scala.collection.immutable.Stream.empty()

你不能在java语言中重载返回类型,所以任何人都可以猜测编译器遇到它时会做什么。我不知道它是否被指定,虽然它可能是。

一般你can't call collections methods from java,这已经被判断为不会修复。

编辑:关于“仍然不明白 2.11 中发生了什么变化来实现这一点”,这是最初的一批候选人:

% git log --no-merges --oneline --grep=forwarder v2.10.4..v2.11.2
532ef331eb (pull/3868/head) Restore reporter forwarders in CompilationUnit
b724201383 Rip out reporting indirection from CompilationUnit
98216be3f3 Move reporting logic into Reporting trait
653c404d7f (pull/3493/head) SI-3452 GenBCode version of the static-forwarder signature fix
640e279500 SI-3452 A better fix for static forwarder generic sigs
f8d80ea26a SI-3452 Correct Java generic signatures for mixins, static forwarders
51ec62a8c3 (pull/3480/head) SI-6948 Make the Abstract* classes public.
731ed385de SI-8134 SI-5954 Fix companions in package object under separate comp.
3cc99d7b4a (pull/3103/head) Collections library tidying and deprecation.  Separate parts are listed below.
5d29697365 Flesh out the Delambdafy phase.
6e2cadb8bd (pull/2951/head) SI-7847 Static forwarders for case apply/unapply
9733f56c87 (pull/1173/head) Fixes SI-4996.

您不会通过查看库代码来找到它,这是肯定的。这是编译器的变化。

【讨论】:

  • 这不是在谈论 Scala 吗?来自链接:I played with it until it got too tedious.
  • 哈哈,看起来像马丁,我同意只要“它”是一个类型参数。
  • 谢谢。仍然不明白 2.11 中发生了什么变化来实现这一点,但是哦,好吧。您能提出一个具体的解决方法吗?
  • 抱歉,我唯一的建议是“不要指望这会起作用。”
  • 实际上,IIRC 从昨晚开始,它会尝试使用两个具有相同擦除的抽象成员的最后一件事是采用最具体的返回类型。 OK,15.12.2.5 到此结束。
【解决方案2】:

我今天学到的是,Java 很乐意忽略无关的类型 arg(JLS 15.12.2.1,本节末尾的细则)。

这条规则源于兼容性问题和原则 可替代性。

显然,有些规则源于原则性推理,有些则源于实际问题,偶尔的规则具有双重血统。

apm@mara:~/tmp$ javap -classpath ~/scala-2.11.2/lib/scala-library.jar scala.collection.immutable.Stream | grep empty
  public static <A extends java/lang/Object> scala.collection.immutable.Stream<A> empty();
  public static scala.collection.GenTraversable empty();
apm@mara:~/tmp$ javap -classpath ~/scala-2.10.4/lib/scala-library.jar scala.collection.immutable.Stream | grep empty
  public static <A extends java/lang/Object> scala.collection.immutable.Stream<A> empty();
  public static <A extends java/lang/Object> scala.collection.immutable.Stream<A> empty();

看来桥接方法的转发器已修复。

这样编译:

import scala.collection.immutable.Stream;
import scala.collection.immutable.Stream$;

public class EmptyStreamFactory {
    public static Stream<String> createEmptyStringStream() {
        return Stream$.MODULE$.<String>empty();
    }
}

我需要三天的周末来重新阅读 Java 中的重载规范。

也许因为 Stream 是抽象的,所以最具体的返回类型规则开始生效。

【讨论】:

  • 感谢您提供额外的线索,但我仍然不明白发生了什么。
  • @TravisBrown 第二个签名来自scala-lang.org/api/2.10.4/…,但不是为生成上限 GenTraversable 而生成的。现在是,Java 重载选择了它。出于某种原因,它在 Stream 上选择它而不是在 Stream$ 上。
  • 在 Stream$ 上,GenTraversable 返回方法是一种桥接方法。在 Stream 上,它不是。
  • @extempore 谢谢,我昨晚注意到了,但没有注册。这就像大脑必须以不同的模式运作exitingErasure(thunk)
猜你喜欢
  • 1970-01-01
  • 2014-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多