java 带有 newInstance 的泛型类型参数

java generic type parameter with newInstance

我不确定为什么 Java 要求我将 makeInstance 方法的 return 转换为 T?我究竟做错了什么?有没有更好的方法来完成这个?

public class Scratch {

    public <T extends Base> T freshen(T instance) {
        //why do I need to cast this to T
        return makeInstance(instance.getClass());
    }

    public <T extends Base> T makeInstance(Class<T> type) {
        try {
            return type.newInstance();
        } catch (InstantiationException ex) {
            Logger.getLogger(Scratch.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(Scratch.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public static final class Base {

    }

}

Java 想要你转换结果的原因是 T return 从 makeInstance 方法编辑的不能保证与 [=11= 相同] 的 freshen 方法。原因是getClass()没有returnClass<T>。相反,它 returns Class<? extends X>,其中 Xinstance 静态类型的擦除,即 Object。这就是编译器的推理链停止的地方:它无法从该调用中推断出 return 类型将是 T,需要您进行转换。

转换实例的替代方法是转换 class,如下所示:

return makeInstance((Class<T>)instance.getClass());

您可以使用以下方法解决此问题。

public class Scratch<T extends Base> {

    public T freshen(T instance) {
        // No need to cast this to T
        return makeInstance(instance.getClass());
    }

    public T makeInstance(Class<T> type) {
        try {
            return type.newInstance();
        } catch (InstantiationException ex) {
            Logger.getLogger(Scratch.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(Scratch.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public static final class Base {

    }

}

希望对您有所帮助。

问题的根本原因是 "type erasure":当 Java 编译器编译 freshen() 方法的主体时,它实际上用其上层替换了 T 类型绑定,即:Base.

所以这是编译器正在做的推理: - instanceBase 类型(如我所说,T 已替换为 Base) - .getClass() 在类型为 Base 的变量上调用,因此此调用的 return 值为 Class<? extends Base> - 因此,从编译器的角度来看,传递给 makeInstance() 的参数属于 Class<? extends Base> 类型。因此 makeInstance() 里面的 T 也是 Base => 方法 returns Base