Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

This seems to compile fine with Java 7, and any version of the Scala libraries:

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

It also compiles fine with Java 8 and Scala 2.11.5+. But with Java 8 and Scala 2.11.4, Eclipse complains:

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

I don't understand this. You might get ambiguity over which overloaded method to select in some contexts, but surely not if you're not passing any arguments?

The really weird thing is that if I recast it like this:

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

then the complaint goes away. This seems to me to be exactly equivalent to the version above. So why would it now compile fine?

like image 887
chiastic-security Avatar asked May 21 '15 11:05

chiastic-security


People also ask

What is the difference between Java 7 and Java 8?

Java 7 brings JVM support for dynamically-typed languages plus Type Interference for Generic Instance creation. Java 8 brings the most anticipated feature for the programming language called Lambda Expressions, a new language feature which allows users to code local functions as method arguments.

Can I compile Java 8 with Java 11?

The class files created by Java 8 are still executable in Java 11; however, there have been other changes in the Java runtime (library changes, etc.) that might require modification of the code. These modifications may be made in Java 8 and compiled with Java 8 making it compatible with the Java 11 runtime.

Can program developed with Java 7 be run on Java 8?

Binary CompatibilityJava SE 8 is binary-compatible with Java SE 7 except for the incompatibilities listed below. Except for the noted incompatibilities, class files built with the Java SE 7 compiler will run correctly in Java SE 8.

Is JDK 1.8 is same as JDK 8?

http://www.oracle.com/technetwork/java/javase/jdk8-naming-2157130.html Java SE Development Kit 8, also known as JDK 8, has the version number 1.8. In short – 8 is product version number and 1.8 is the developer version number (or internal version number). The product is the same, JDK 8, anyways.


2 Answers

If we compare the javap output of scala.collection.immutable.Set, we get for the 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();
}

and for the 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();
}

The version 2.11.4 is not correct, it is a violation of the Java Virtual Machine Specification, 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 is clearly explained in this scalac issue, which have been fixed in the... 2.11.5

like image 161
gontard Avatar answered Oct 11 '22 02:10

gontard


This may not be a strictly Java 8/Scala library issue. It may be related to Eclipse. Which version of Eclipse are you using? This sounds somewhat like this issue in Eclipse 4.4: Java 8 generics thinks single method is ambiguous

like image 42
Peter Avatar answered Oct 11 '22 03:10

Peter