Java 实例化类型参数的对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/299998/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Instantiating object of type parameter
提问by Mercurious
I have got a template class as follows:
我有一个模板类如下:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
How do I create a new instance of T in my class?
如何在我的班级中创建 T 的新实例?
采纳答案by erickson
After type erasure, all that is known about T
is that it is some subclass of Object
. You need to specify some factory to create instances of T
.
在类型擦除之后,我们T
只知道它是Object
. 您需要指定一些工厂来创建T
.
One approach could use a Supplier<T>
:
一种方法可以使用Supplier<T>
:
class MyClass<T> {
private final Supplier<? extends T> ctor;
private T field;
MyClass(Supplier<? extends T> ctor) {
this.ctor = Objects.requireNonNull(ctor);
}
public void myMethod() {
field = ctor.get();
}
}
Usage might look like this:
用法可能如下所示:
MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);
Alternatively, you can provide a Class<T>
object, and then use reflection.
或者,您可以提供一个Class<T>
对象,然后使用反射。
class MyClass<T> {
private final Constructor<? extends T> ctor;
private T field;
MyClass(Class<? extends T> impl) throws NoSuchMethodException {
this.ctor = impl.getConstructor();
}
public void myMethod() throws Exception {
field = ctor.newInstance();
}
}
回答by krosenvold
If you're willing to subclass you can avoid erasure as well, check out http://www.artima.com/weblogs/viewpost.jsp?thread=208860
如果您愿意子类化,也可以避免擦除,请查看 http://www.artima.com/weblogs/viewpost.jsp?thread=208860
回答by Dan Hodge
This may be more heavyweight than what you're looking for, but it will also work. Note that if you take this approach, it would make more sense to inject the factory into MyClass when it is constructed instead of passing it into your method each time it is called.
这可能比您正在寻找的更重量级,但它也可以工作。请注意,如果您采用这种方法,那么在构造 MyClass 时将工厂注入到 MyClass 中,而不是在每次调用时将其传递到您的方法中会更有意义。
interface MyFactory<T>
{
T newObject();
}
class MyClass<T>
{
T field;
public void myMethod(MyFactory<T> factory)
{
field = factory.newObject()
}
}
回答by Dan Hodge
Another non-reflective approach is to use a hybrid Builder / Abstract Factory pattern.
另一种非反射方法是使用混合构建器/抽象工厂模式。
In Effective Java, Joshua Bloch goes over the Builder pattern in detail, and advocates a generic Builder interface:
在 Effective Java 中,Joshua Bloch 详细介绍了 Builder 模式,并提倡通用的 Builder 接口:
public interface Builder<T> {
public T build();
}
Concrete builders can implement this interface, and outside classes can use the concrete builder to configure the Builder as required. The builder can be passed to MyClass as a Builder<T>
.
具体构建器可以实现这个接口,外部类可以根据需要使用具体构建器来配置构建器。构建器可以作为Builder<T>
.
Using this pattern, you can get new instances of T
, even if T
has constructor parameters or requires additional configuration. Of course, you'll need some way to pass the Builder into MyClass. If you can't pass anything into MyClass, then Builder and Abstract Factory are out.
使用此模式,您可以获得 的新实例T
,即使T
有构造函数参数或需要额外配置。当然,您需要某种方式将 Builder 传递给 MyClass。如果你不能将任何东西传递给 MyClass,那么 Builder 和 Abstract Factory 就被淘汰了。
回答by Kevendra
Class classOfT
类 classOfT
try {
t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
} catch (Exception e) {
e.printStackTrace();
}