I noticed a difference in the output of the following program when run with Java 8 and Java 9.
import java.lang.reflect.Method;
public class OrderingTest {
public static void main(String[] args) {
ServiceImpl service = new ServiceImpl();
for (Method method : service.getClass().getMethods()) {
for (Class<?> anInterface : method.getDeclaringClass().getInterfaces()) {
try {
Method intfMethod = anInterface.getMethod(method.getName(), method.getParameterTypes());
System.out.println("intfMethod = " + intfMethod);
} catch (NoSuchMethodException e) { }
}
}
}
}
class ServiceImpl implements ServiceX {
@Override
public Foo getType() { return null; }
}
interface ServiceX extends ServiceA<Foo>, ServiceB { }
abstract class Goo { }
class Foo extends Goo { }
interface ServiceA<S> {
S getType();
}
interface ServiceB {
@java.lang.Deprecated
Goo getType();
}
You can run both versions of java here: https://www.jdoodle.com/online-java-compiler/
Java 8 outputs:
intfMethod = public abstract java.lang.Object ServiceA.getType()
intfMethod = public abstract java.lang.Object ServiceA.getType()
intfMethod = public abstract java.lang.Object ServiceA.getType()
Java 9 outputs:
intfMethod = public abstract Goo ServiceB.getType()
intfMethod = public abstract Goo ServiceB.getType()
intfMethod = public abstract Goo ServiceB.getType()
But when I reorder the super-interfaces to:
interface ServiceX extends ServiceB, ServiceA<Foo> { }
Then both versions of java output:
intfMethod = public abstract Goo ServiceB.getType()
intfMethod = public abstract Goo ServiceB.getType()
intfMethod = public abstract Goo ServiceB.getType()
I was wondering what is causing it? Is there a new java feature I am not aware of?
Java 8 documentation https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8
Java 9 documentation https://docs.oracle.com/javase/specs/jls/se9/html/jls-8.html#jls-8.4.8
Java 8 applications use packages as a top-level component whereas Java 9 applications use modules as a top-level component. Each Java 9 module has only one module with one module descriptor whereas Java 8 package doesn't build multiple modules into a single module.
Reactive Streams: Overview of reactive programming; Understanding the Java Flow API; Implementing publishers and subscribers; Implementing processors; Practical applications. New Language Features: Private methods in interfaces; Type interference; Miscellaneous improvements; Multi-version JARs.
The difference seems to be in the implementation of getMethod
API in use which is visible by the stated documentation starting Java-9 :
Within each such subset only the most specific methods are selected. Let method M be a method from a set of methods with same VM signature (return type, name, parameter types). M is most specific if there is no such method N != M from the same set, such that N is more specific than M. N is more specific than M if:
a. N is declared by a class and M is declared by an interface; or
b. N and M are both declared by classes or both by interfaces and N's declaring type is the same as or a subtype of M's declaring type (clearly, if M's and N's declaring types are the same type, then M and N are the same method).
While Java-8 follows up internally with interfaceCandidates.getFirst()
(i.e. the order change matters here), the upgraded version seems to be working on the specific algorithm using res.getMostSpecific()
before returning the method asked for.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With