在Java中创建泛型类型的实例?
时间:2020-03-05 18:56:42 来源:igfitidea点击:
是否可以在Java中创建泛型类型的实例?我正在根据我所看到的答案进行思考,因为答案是"不"(由于类型擦除),但是如果有人能看到我所缺少的内容,我将很感兴趣:
class SomeContainer<E> { E createContents() { return what??? } }
编辑:事实证明,超级类型令牌可以用于解决我的问题,但是它需要很多基于反射的代码,如下面的一些答案所示。
我将对此开放一会儿,看看是否有人提出与Ian Robertson的Artima Article截然不同的东西。
解决方案
回答
如我们所说,由于类型擦除,我们无法真正做到这一点。我们可以使用反射来完成它,但是它需要大量代码和大量错误处理。
回答
你是对的。你不能做new E()
。但我们可以将其更改为
private static class SomeContainer<E> { E createContents(Class<E> clazz) { return clazz.newInstance(); } }
真痛苦但这行得通。以工厂模式包装它会使它更具容忍性。
回答
这是我想出的一个选项,可能会有所帮助:
public static class Container<E> { private Class<E> clazz; public Container(Class<E> clazz) { this.clazz = clazz; } public E createContents() throws Exception { return clazz.newInstance(); } }
编辑:或者,我们可以使用此构造函数(但它需要E的实例):
@SuppressWarnings("unchecked") public Container(E instance) { this.clazz = (Class<E>) instance.getClass(); }
回答
Dunno(如果有帮助),但是当我们继承(包括匿名)泛型类型时,可以通过反射获得类型信息。例如。,
public abstract class Foo<E> { public E instance; public Foo() throws Exception { instance = ((Class)((ParameterizedType)this.getClass(). getGenericSuperclass()).getActualTypeArguments()[0]).newInstance(); ... } }
因此,当我们对Foo进行子类化时,会得到Bar的一个实例,例如,
// notice that this in anonymous subclass of Foo assert( new Foo<Bar>() {}.instance instanceof Bar );
但这是很多工作,并且仅适用于子类。虽然可以方便。
回答
我们将需要某种类型的某种抽象工厂,以将其责任传递给:
interface Factory<E> { E create(); } class SomeContainer<E> { private final Factory<E> factory; SomeContainer(Factory<E> factory) { this.factory = factory; } E createContents() { return factory.create(); } }
回答
如果你的意思是新E()
那是不可能的。我要补充一点,这并不总是正确的,我们怎么知道E是否具有公共的无参数构造函数?
但是我们总是可以将创建委托给其他知道如何创建实例的其他类,它可以是Class <E>
或者类似这样的自定义代码
interface Factory<E>{ E create(); } class IntegerFactory implements Factory<Integer>{ private static int i = 0; Integer create() { return i++; } }
回答
如果我们不想在实例化过程中两次键入类名,例如:
new SomeContainer<SomeType>(SomeType.class);
我们可以使用工厂方法:
<E> SomeContainer<E> createContainer(Class<E> class);
像:
public class Container<E> { public static <E> Container<E> create(Class<E> c) { return new Container<E>(c); } Class<E> c; public Container(Class<E> c) { super(); this.c = c; } public E createInstance() throws InstantiationException, IllegalAccessException { return c.newInstance(); } }
回答
我们可以使用:
Class.forName(String).getConstructor(arguments types).newInstance(arguments)
但是我们需要提供确切的类名称,包括包。 java.io.FileInputStream
。我用它来创建数学表达式解析器。
回答
package org.foo.com; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; /** * Basically the same answer as noah's. */ public class Home<E> { @SuppressWarnings ("unchecked") public Class<E> getTypeParameterClass() { Type type = getClass().getGenericSuperclass(); ParameterizedType paramType = (ParameterizedType) type; return (Class<E>) paramType.getActualTypeArguments()[0]; } private static class StringHome extends Home<String> { } private static class StringBuilderHome extends Home<StringBuilder> { } private static class StringBufferHome extends Home<StringBuffer> { } /** * This prints "String", "StringBuilder" and "StringBuffer" */ public static void main(String[] args) throws InstantiationException, IllegalAccessException { Object object0 = new StringHome().getTypeParameterClass().newInstance(); Object object1 = new StringBuilderHome().getTypeParameterClass().newInstance(); Object object2 = new StringBufferHome().getTypeParameterClass().newInstance(); System.out.println(object0.getClass().getSimpleName()); System.out.println(object1.getClass().getSimpleName()); System.out.println(object2.getClass().getSimpleName()); } }