带有newInstance的java泛型类型参数

时间:2015-02-13 14:47:40

标签: java generics

我不确定为什么Java要求我将makeInstance方法的返回强制转换为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 {

    }

}

3 个答案:

答案 0 :(得分:2)

Java希望您投射结果的原因是T方法返回的makeInstance不能保证与T方法的freshen相同。原因是getClass()没有返回Class<T>。相反,它会返回Class<? extends X>,其中X是静态类型instance的删除,即Object。编译器的推理链停止的地方:它不能从该调用推断返回类型为T,要求你进行强制转换。

转换实例的另一种方法是强制转换类,如下所示:

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

答案 1 :(得分:1)

问题的根本原因是&#34;键入erasure&#34;:当Java编译器编译freshen()方法的主体时,它基本上用其上限替换T类型,即:Base

所以这就是编译器正在做的理由: - instance类型为Base(正如我所说,T已替换为Base) - 对.getClass()类型的变量调用Base,因此此调用的返回值为Class<? extends Base&gt; - 因此,从编译器的角度来看,传递给makeInstance()的参数类型为Class<? extends Base>。因此,T内的makeInstance()也是Base =&gt;该方法返回Base

答案 2 :(得分:0)

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

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 {

    }

}

希望这有帮助。