在Java中创建一个泛型类型的实例

9

I have the following Java class

public class MyClass <T extends MyInterface> implements RowMapper<MyInterface>

我正在实现以下方法:

我正在实现以下方法:

@Override
public T mapRow(ResultSet rs, int arg1) throws SQLException {

如何在该类中创建'T'类型的实例?

我尝试定义T类型的类并使用"myInstance.newInstance()",但我无法定义它。将Class作为参数传递到方法并使用"newInstance()"方法可以工作,但我希望能够在不传递参数的情况下实现这一点。


2
任何继承 MyInterface 的类都将代表 T。因此,请创建一个类并将其扩展为 MyInterface。然后创建该新类的实例。 - Ved
你为什么假设 T 有默认构造函数呢? - Louis Wasserman
4个回答

26

Java泛型是通过擦除实现的,这意味着在运行时不会有参数类型信息。你在运行时不会知道T类(没有T.class)。所以你需要将Class对象作为方法参数传递,以便按照你的意愿进行操作。


1
这个问题在SO上已经被问了无数次,但这是唯一一个真正切入重点的答案(尽管可能以直接的“你不能”开始)。非常感谢! - Bruno Brant
@Bruno - 一百万次左右是正确的,人们会认为Java设计者会领会这个提示并将其添加到Java的反射中... - Deian

10

当将对象传递到泛型类/函数中时,您会失去有关类型的所有信息。

唯一的解决方法是将Class对象传递给构造函数/函数:

static class Gen <T>{

    private Class<T> mClass;

    public Gen(Class<T> cls){
        mClass = cls;
    }

    public T get(){
        try{
            return mClass.newInstance();
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
    }
}

static class A{
    public String name = "A!";
}

public static void main(String[] args) {
    Gen<A> g = new Gen<A>(A.class);
    A a = g.get();
    System.out.println(a.name);
}

1

很遗憾,由于类型擦除,您无法做您想要的事情。

您必须明确告诉您的类需要实例化哪种类型,可以通过告诉它Class或者更优雅地给它一个工厂来创建实例。


1

可以提取T在特定子类中绑定的类,尽管这并不是很容易:

http://www.artima.com/weblogs/viewpostP.jsp?thread=208860

我在这篇帖子中有一个稍微更好的代码版本:

http://github.com/ISA-tools/jUtils/blob/master/src/main/java/uk/ac/ebi/utils/reflection/ReflectionUtils.java

http://github.com/ISA-tools/jUtils/blob/master/src/test/java/uk/ac/ebi/utils/reflection/ReflectionUtilsTest.java

这种方法也不是很快,所以如果性能是一个问题,一种更粗略的替代方案可能是在需要的地方传递T和Class<T>的实例。

当然,在获取了这样的类之后,您需要使用反射来实例化它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接