通用继承和调用GetMethod().getReturnType()

Rya*_*ord 6 java generics reflection

在我当前的项目中,我有类似以下的类.在某些时候,getReturnTypeForGetId()A和方法之类的方法被调用B.使用A返回Integer按预期调用方法,但B返回Serializable.

我在这里错过了什么?我是否被一些令人发指的擦除事件所困扰,或者我只是错过了某种通用的上下文冲突?

编辑:添加一个过度使用的getId()方法来B解决问题,但我仍然想了解我遇到了什么.

import java.io.Serializable;

public class WeirdTester {
    static interface Identifiable<T extends Serializable> {
        T getId();
        void setId(final T id);
    }

    static abstract class BaseEntity<T extends Serializable> implements Identifiable<T> {
        private T id;
        public T getId() { return id; }
        public void setId(final T id) { this.id = id; }
    }

    static class A implements Identifiable<Integer> {
        private Integer id;
        public Integer getId() { return id; }
        public void setId(final Integer id) { this.id = id; }
    }

    static class B extends BaseEntity<Integer> {}

    @SuppressWarnings("unchecked")
    private static <T extends Serializable, Q extends Identifiable<T>> Class<T> getReturnTypeForGetId(
            final Class<Q> clazz) throws Exception {
        return (Class<T>) clazz.getMethod("getId", (Class[])null).getReturnType();
    }

    public static void main(final String[] args) throws Exception {
        System.out.println(getReturnTypeForGetId(A.class));
        // CONSOLE: "class java.lang.Integer"
        System.out.println(getReturnTypeForGetId(B.class));
        // CONSOLE: "interface java.io.Serializable"
    }
}
Run Code Online (Sandbox Code Playgroud)

Tom*_*ine 2

编译后的类中有多个getId方法A。您将获得协变返回类型的桥接方法(未反映在虚拟机中的语言的“虚构”)。的规范Class.getMethod表示它将返回具有最具体返回类型的方法(假设存在)。它为 执行此操作A,但因为B该方法没有被重写,因此 javac 避免了合成不必要的桥接方法。

事实上,对于这个示例,所有信息仍然存在于类文件中。(之前我说过它没有被删除。这不是真的,但删除并不意味着它不存在!)然而,提取通用信息有点棘手(它将位于Identifiable.class.getGenericReturnType()Identifiable.class.getTypeParameters()BaseEntity.class.getGenericInterfaces和(我思考!))。BaseEntity.class.getTypeParameters()B.getGenericSuperclass

用于javap准确查看类文件中的内容。