有可能在Java中创建泛型类型的实例吗?我在想,根据我所看到的,答案是否定的(由于类型擦除),但如果有人能看到我遗漏的东西,我会很感兴趣:
class SomeContainer<E>
{
E createContents()
{
return what???
}
}
编辑:事实证明,超级类型令牌可以用来解决我的问题,但它需要大量基于反射的代码,如下面的一些答案所示。
我将把这个问题放一段时间,看看是否有人提出了与Ian Robertson的Artima文章截然不同的东西。
对诺亚的回答进行了改进。
改变的原因
a]如果使用多于一个泛型类型,则更安全,以防您更改顺序。
b]类泛型类型签名会不时变化,这样你就不会对运行时中无法解释的异常感到惊讶。
健壮的代码
public abstract class Clazz<P extends Params, M extends Model> {
protected M model;
protected void createModel() {
Type[] typeArguments = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
for (Type type : typeArguments) {
if ((type instanceof Class) && (Model.class.isAssignableFrom((Class) type))) {
try {
model = ((Class<M>) type).newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
或者使用一个眼线笔
一行代码
model = ((Class<M>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1]).newInstance();
希望这还不算太晚!!
Java是类型安全的,这意味着只有对象才能创建实例。
在我的例子中,我不能将参数传递给createContents方法。我的解决方案是使用与下面的答案不同的扩展。
private static class SomeContainer<E extends Object> {
E e;
E createContents() throws Exception{
return (E) e.getClass().getDeclaredConstructor().newInstance();
}
}
这是我不能传递参数的例子。
public class SomeContainer<E extends Object> {
E object;
void resetObject throws Exception{
object = (E) object.getClass().getDeclaredConstructor().newInstance();
}
}
如果使用非对象类型扩展泛型类,则使用反射会产生运行时错误。将泛型类型扩展为对象,将此错误转换为编译时错误。
在Java 8中,你可以使用Supplier函数接口很容易地实现这一点:
class SomeContainer<E> {
private Supplier<E> supplier;
SomeContainer(Supplier<E> supplier) {
this.supplier = supplier;
}
E createContents() {
return supplier.get();
}
}
你可以这样构造这个类:
SomeContainer<String> stringContainer = new SomeContainer<>(String::new);
这一行上的String::new语法是一个构造函数引用。
如果你的构造函数接受参数,你可以使用lambda表达式:
SomeContainer<BigInteger> bigIntegerContainer
= new SomeContainer<>(() -> new BigInteger(1));