为什么它在 Java 7 下编译而不是在 Java 8 下编译?

Why does this compile under Java 7 but not under Java 8?

这似乎可以很好地编译 Java 7,以及任何版本的 Scala 库:

public static void main(String[] args) {
    scala.collection.immutable.Set<String> set = new scala.collection.immutable.HashSet<String>();
    Iterator<String> iterator = set.iterator();
}

它也可以很好地编译 Java 8 和 Scala 2.11.5+。但是对于 Java 8 和 Scala 2.11.4,Eclipse 抱怨:

The method iterator() is ambiguous for the type Set<String>

我不明白这个。在某些情况下,您可能会对 select 的重载方法产生歧义,但如果您不传递任何参数,则肯定不会?

真正奇怪的是,如果我这样重铸它:

public static void main(String[] args) {
    Iterator<String> iterator = new scala.collection.immutable.HashSet<String>().iterator();
}

然后投诉就消失了。在我看来,这与上面的版本完全相同。那为什么现在可以正常编译了?

这可能不是严格意义上的 Java 8/Scala 库问题。它可能与 Eclipse 有关。您使用的是哪个版本的 Eclipse?这听起来有点像 Eclipse 4.4 中的这个问题:Java 8 generics thinks single method is ambiguous

如果我们比较 scala.collection.immutable.Set 的 javap 输出,我们得到 2.11.4:

public interface scala.collection.immutable.Set<A> 
    extends 
        scala.collection.immutable.Iterable<A>, 
        scala.collection.Set<A>, 
        scala.collection.generic.GenericSetTemplate<A, 
        scala.collection.immutable.Set>, 
        scala.collection.SetLike<A, scala.collection.immutable.Set<A>>, 
        scala.collection.Parallelizable<A, 
        scala.collection.parallel.immutable.ParSet<A>> {
    public abstract scala.collection.generic.GenericCompanion<scala.collection.immutable.Set> companion();
    public abstract <B> scala.collection.immutable.Set<B> toSet();
    public abstract scala.collection.immutable.Set<A> seq();
    public abstract scala.collection.parallel.Combiner<A, scala.collection.parallel.immutable.ParSet<A>> parCombiner();
}

对于 2.11.5:

public interface scala.collection.immutable.Set<A>
    extends 
        scala.collection.immutable.Iterable<A>, 
        scala.collection.Set<A> {
    public abstract scala.collection.generic.GenericCompanion<scala.collection.immutable.Set> companion();
    public abstract <B> scala.collection.immutable.Set<B> toSet();
    public abstract scala.collection.immutable.Set<A> seq();
    public abstract scala.collection.parallel.Combiner<A, scala.collection.parallel.immutable.ParSet<A>> parCombiner();
}

版本 2.11.4 不正确,违反了 Java 虚拟机规范,section 4.7.9.1:

A class signature encodes type information about a (possibly generic) class declaration. It describes any type parameters of the class, and lists its (possibly parameterized) direct superclass and direct superinterfaces, if any. A type parameter is described by its name, followed by any class bound and interface bounds.


这在 this scalac issue 中有清楚的解释,已在... 2.11.5

中修复