简体   繁体   English

用泛型实例化抽象类的对象

[英]instantiate object of abstract class with generic type

I am creating a function with a generic type and that generic type is an abstract type which I need to instantiate.我正在创建一个具有泛型类型的函数,该泛型类型是我需要实例化的抽象类型。 This code will explain it more clearly:这段代码会更清楚地解释它:

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


}

Basically I want to enforce "T extends AbstractRow but is not Abstract itself".基本上我想强制执行“T 扩展 AbstractRow 但不是抽象本身”。

I realize you can't instantiate abstract classes, so I'd like a suggestion on a workaround or some other method that would allow me to mimic the behavior of creating an object of a generic type.我意识到你不能实例化抽象类,所以我想要一个关于解决方法或其他一些方法的建议,这些方法可以让我模仿创建泛型类型对象的行为。

As far as I know, there's two ways to do this:据我所知,有两种方法可以做到这一点:

  1. Add a Class<T> type field to your abstract generic class, and set it through the constructor (or another method).Class<T> type字段添加到抽象泛型类,并通过构造函数(或其他方法)设置它。 You can then invoke type.newInstance() to create the object.然后您可以调用type.newInstance()来创建对象。
  2. Create a factory interface Factory<T> with a T create() method and set that as a field on your abstract class through the constructor (or another method).使用T create()方法创建工厂接口Factory<T>并通过构造函数(或其他方法)将其设置为抽象类上的字段。 Upon creating a concrete instance of your generic class, you also have to pass a concrete implementation of said factory.在创建泛型类的具体实例时,您还必须传递所述工厂的具体实现。
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();
}

Usage:用法:

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

concrete.foo();

Your main issue isn't that you're working with an abstract class - in which case the suggestions posted in the comments would be useful.您的主要问题不是您正在使用抽象类 - 在这种情况下,评论中发布的建议会很有用。 The bigger problem is that you're trying to instantiate a generic type directly (read: new T() ) - which, simply put, you can't do in Java because of type erasure .更大的问题是您试图直接实例化一个泛型类型(阅读: new T() ) - 简单地说,由于类型擦除,您无法在 Java 中做到这一点。

That said, there's always a workaround:也就是说,总有一种解决方法:

/**@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
}

Usage:用法:

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"
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM