The accepted answer to the stack exchange discussion you mentioned (https://stackoverflow.com/a/5365419/16595881) solves your issue.
To comment on the comments on this question, Oracle did not define a Java SE compiler as the 'correct' compiler for Java SE, but rather Oracle defined the specifications that a Java SE compiler must adhere to. In order for a Java SE compiler to be 'correct' (i.e. in order for something to be a Java SE compiler), it must implement those specifications. Just because Oracle defined both the specifications and a (questionable) implementation of those specifications, it is not guaranteed that the implementation is 'correct', although it likely is. In this case, your javac
compiler correctly implements the Java SE language specifications, but Eclipse's compiler does not (it might now, being 5 years later).
Also, javac
is a command-line tool on your PATH that points to an executable binary that can be arbitrary. This means instead of being a compiler, the binary executed by calling javac
might simply print "I am not a Java SE compiler" or instead might produce nasal demons. The point is that the javac
binary is not necessarily Oracle's implementation of the Java SE compiler specifications. For example, it could be an implementation by Sun (which was bought by Oracle in 2009) or by OpenJDK, to name a few. Anyway...
In the second definition of MyTest#add
, T
extends Interface2
, but that does not limit T
from also extending Interface1
, because classes can implement multiple interfaces. So, it is possible to construct a class that implements both interfaces then pass one of its instances as the argument into MyTest#add
, in which case both definitions of the method would be valid candidates, with neither being more appropriate then the other. Consider the following code example, where we replace the interfaces with abstract classes:
public class MyTest {
public static void main(String[] args) {
MyTest test = new MyTest();
test.add(test.new Abstract1() {
@Override
void method1() {
test.method();
}
});
}
public void add(Abstract1 a1) {
}
public <T extends Abstract2> void add(T a2) {
}
private void method() {
}
public abstract class Abstract1 {
abstract void method1();
}
public abstract class Abstract2 {
abstract boolean isMethod2();
abstract void setMethod2(boolean required);
}
}
The only difference here is the use of abstract classes instead of interfaces. If you were to call MyTest#add
, there would be no ambiguity since no object could be an instance of both Abstract1
and Abstract2
, since no class can extend multiple classes. For this reason, the Java SE language specifications allows this to be compiled.