如何调用泛型类型的正确工厂方法?

时间:2017-11-12 19:37:35

标签: java generics factory-method

我正在尝试编写一个泛型类,它可以通过调用该类型的类的静态工厂方法来创建其泛型类型的实例:

class Test<T extends Parent> {

    public static void main(String[] args) {
        new Test<Child>();
    }

    private Test() {
        System.out.println(Child.newInstance());
        System.out.println(T.newInstance());
    }
}

abstract class Parent {
    static <T extends Parent> T newInstance() {
        return null;
    }
}

class Child extends Parent {
    static Child newInstance() {
        return new Child();
    }
}

我希望Child.newInstance()T.newInstance()会调用相同的方法,因为T类型设置为Child。但是T.newInstance()调用其父类的方法并返回null,而直接调用Child.newInstance()则返回一个新的Child对象。 有人可以解释一下,我在Java Generics逻辑中的误解是什么,以及是否有其他干净的方法来创建泛型类型的实例?

编辑:我不是要覆盖静态方法,我只是想隐藏它。

2 个答案:

答案 0 :(得分:0)

由于类型擦除,我们不知道类型参数是什么。因此,在运行时,我们不知道它是Test<Parent>Test<Child>Test<Chicken>等。

如果要使用type参数,则需要传入相关的Class对象并对其使用反射,如下所示:

public class Test<T extends Parent> {

    public static void main(String[] args) {
        new Test<Child>(Child.class);
    }

    private Test(Class<T> clazz) {
        System.out.println(Child.newInstance());
        try {
            System.out.println(clazz.getDeclaredMethod("newInstance").invoke(null));
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }
}

答案 1 :(得分:0)

由于java的类型擦除,在运行时,每个通用对象都被其上限替换。所以在你的代码中:

class Test<T extends Parent> {

private Test() {
    System.out.println(Child.newInstance());
    System.out.println(T.newInstance());
}

}

由于Parent是上限,test()最终会编译成以下内容,无论您在类外指定什么泛型参数:

private Test() {
    System.out.println(Child.newInstance());
    System.out.println(Parent.newInstance());
}