为通用T创建实例

时间:2015-01-04 18:55:12

标签: java

这里已有太多帖子暗示:

class Foo<T>{
    Class<T> type;
    public Foo(Class<T> type){
        this.type = type;
    }
    // then using newInstance method creating the instance
}

这种方法的问题在于,这不是创建实例的java,这是开发人员被迫将类型传递给Foo类的构造函数。所以,让我们说我需要一个无参数构造函数,Java仍然能够创建实例吗?

例如在C#中我们得到了Activator类型,我们可以这样使用:

Object obj = Activator.CreateInstance<T>();

所以,如果我在Java中使用以下类,并且我无法遵循第一个解决方案,那么什么是类似于C#解决方案的替代方法:

class Foo<T>(){
   public Foo(){
      if T is of Type X Then Do Y
   }
}

3 个答案:

答案 0 :(得分:1)

不,你不能这样做。通用参数只是编译时,它们被完全擦除并在运行时变得不可用。 另请注意,无论您是Activator.CreateInstance<Foo>()(如果可能)还是Activator.CreateInstance(Foo.class),您实际上都将相同的确切信息传递给CreateInstance方法,区别在于纯语法。

答案 1 :(得分:0)

如果真的需要这样做,那么这是可能的。

例如,一些依赖注入框架使用Instance<T>字段来解析和/或在运行时创建依赖项。

您可以通过经典反射调用获取Class<T>个对象:

Class<T> cls = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

检查此答案,了解代码段https://stackoverflow.com/a/3942033/2892277

但是(正如那个答案所提到的),这不是一个好习惯。

答案 2 :(得分:0)

如果开发人员创建了Foo的子类,那么您可以使用TypeTools等内容恢复T。例如:

public class StringFoo extends Foo<String>{}

Class<?> t = TypeResolver.resolveRawArgument(Foo.class, StringFoo.class);
assert t == String.class;

如果用户没有将Foo子类化并仅仅实例化它,则T的值无法在运行时恢复。