Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
267 views
in Technique[技术] by (71.8m points)

reflection - Java superinterfaces runtime difference Java 8 vs Java 9

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

question from:https://stackoverflow.com/questions/65937177/java-superinterfaces-runtime-difference-java-8-vs-java-9

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...