【问题标题】:instantiate object of abstract class with generic type用泛型实例化抽象类的对象
【发布时间】:2014-06-08 07:53:24
【问题描述】:

我正在创建一个具有泛型类型的函数,而该泛型类型是我需要实例化的抽象类型。这段代码会解释得更清楚:

public <T extends AbstractRow> foo(){//no I did not actually name the function foo
    ArrayList<T> arr=new ArrayList<T>();
    arr.add(new T(...)); //cant instantiate objects of abstract class


}

基本上我想强制执行“T 扩展 AbstractRow 但不是 Abstract 本身”。

我知道你不能实例化抽象类,所以我想要一个解决方法或其他方法的建议,让我可以模仿创建泛型对象的行为。

【问题讨论】:

  • 除非实现所有抽象方法,否则无法实例化抽象类。
  • 我意识到这一点。我需要一个“解决方法”或一些关于如何使这样的实现工作的想法,我需要实例化一个泛型类型的对象
  • 各位,什么时候可以直接实例化泛型类型呢?
  • @drewmore 如果你有AbstractRow 的非抽象子类,你可以做T t = (T) new SubClassName();
  • @Christian 是的,你可以,但这不是直接实例化泛型类型 - 它是实例化具体类型并将其强制转换为泛型类型

标签: java generics abstract-class


【解决方案1】:

据我所知,有两种方法可以做到这一点:

  1. Class&lt;T&gt; type 字段添加到抽象泛型类中,并通过构造函数(或其他方法)设置它。然后,您可以调用 type.newInstance() 来创建对象。
  2. 使用T create() 方法创建工厂接口Factory&lt;T&gt;,并通过构造函数(或其他方法)将其设置为抽象类的字段。在创建泛型类的具体实例后,您还必须传递所述工厂的具体实现。
import java.util.ArrayList;
import java.util.List;

public class Generic<T> {
    private Factory<T> factory;

    public Generic(Factory<T> factory) {
        this.factory = factory;
    }

    public void foo() {
        List<T> list = new ArrayList<>();

        list.add(factory.create());
    }
}

interface Factory<T> {
    T create();
}

用法:

Generic<Bar> concrete = new Generic<>(new Factory<Bar>() {
    @Override
    public Bar create() {
        return new Bar();
    }
});

concrete.foo();

【讨论】:

    【解决方案2】:

    您的主要问题不是您正在使用抽象类 - 在这种情况下,发布在 cmets 中的建议会很有用。更大的问题是你试图直接实例化一个泛型类型(阅读:new T())——简单地说,由于type erasure,你不能在 Java 中这样做。

    也就是说,总有一种解决方法:

    /**@param clazz the subclass you want to instantiate */
    public <T extends AbstractRow> foo(Class<T> clazz) { 
        ArrayList<T> arr = new ArrayList<T>();
        arr.add(clazz.newInstance); //instantiate new instance of given subclass
    }
    

    用法:

    abstract class Test1  {} 
    class Test2 extends Test1{ }
    
    class Test<T> {
       public static <T extends Test1> T foo(Class<T> clazz) {
         T toReturn = null;
         try{ toReturn = clazz.newInstance(); } catch (Exception e) { };
         return toReturn ;
      }
    
      public static void main(String[] args) {
        Test1 t1 = t.foo(test2.class);
        System.out.println(t1.getClass()); //prints "class pkgname.test2"
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多