在方法中创建通用实例

时间:2016-06-10 11:32:01

标签: java generics methods

我用这样的通用返回类型调用一个方法:

public static <T extends HotelBean> List<T> fill(Class<T> c) throws InstantiationException, IllegalAccessException {
    List<T> list = new ArrayList<>();
    for (int i = 0; i <= 2; i++) {
        T t = c.newInstance();
        list.add(t);
    }
    return list;
}

有没有办法在此方法中创建实例而不将Class作为方法参数? (Class<T> c

2 个答案:

答案 0 :(得分:3)

不,不幸的是,没有。这是首先必须通过Class<T>的主要原因。

Java编译器在称为 type erasure 的过程中从已编译的类和方法中剥离通用信息。编译器完成时,所有T成为Object s或下限类型(这将对应于示例中的HotelBean)。如果无法访问Class<T>,则该方法无法恢复类型参数,这是生成新实例所必需的。

请注意,您的示例必须以这种方式或其他方式传递所需的类型,因为您使用可能是HotelBean的子类的对象填充基类对象的列表。

答案 1 :(得分:1)

而不是传递Class来创建一个实例,这意味着必须处理捕获或抛出异常,而不是传递Supplier<T>

java.util.function.Supplier<T>(Java 8特性)是一个功能接口,它有一个方法get,它返回一个T类型的对象。

使用Supplier<T>看起来像这样:

public static <T extends HotelBean> List<T> fill(Supplier<T> supp) { // No more exceptions!
    List<T> list = new ArrayList<>();
    for (int i = 0; i <= 2; i++) {
        T t = supp.get();
        list.add(t);
    }
    return list;
}

您可以传递不带参数的方法引用并返回类型为T的对象作为供应商,其中包含T的默认构造函数。

class MyClass {
    public MyClass() {...}
}
fill(MyClass::new);

newInstance()的主要区别在于,Supplier<T>返回的对象不一定是 new 对象,因为您不必通过{{ 1}}。您可以传递任何不带参数的方法并返回MyClass::new