在Java中创建泛型类型的实例?
Posted
技术标签:
【中文标题】在Java中创建泛型类型的实例?【英文标题】:Create instance of generic type in Java? 【发布时间】:2010-09-09 15:56:40 【问题描述】:是否可以在 Java 中创建泛型类型的实例?根据我所见,我认为答案是no
(由于类型擦除),但如果有人能看到我遗漏的东西,我会很感兴趣:
class SomeContainer<E>
E createContents()
return what???
编辑:事实证明,Super Type Tokens 可以用来解决我的问题,但它需要大量基于反射的代码,正如下面的一些答案所示。
我将暂时搁置这个问题,看看是否有人提出与 Ian Robertson 的Artima Article 截然不同的东西。
【问题讨论】:
刚刚在 android 设备上测试了性能。 10000 次操作和:8-9 ms 采用 new SomeClass(),9-11 ms 采用 Factory正如您所说,由于类型擦除,您无法真正做到这一点。您可以使用反射来完成它,但它需要大量代码和大量错误处理。
【讨论】:
你会如何使用反射呢?我看到的唯一方法是 Class.getTypeParameters(),但它只返回声明的类型,而不是运行时类型。 你在说这个吗? artima.com/weblogs/viewpost.jsp?thread=208860【参考方案2】:你是对的。你不能做new E()
。但是你可以把它改成
private static class SomeContainer<E>
E createContents(Class<E> clazz)
return clazz.newInstance();
这很痛苦。但它有效。将其包装在工厂模式中使其更容易忍受。
【讨论】:
是的,我看到了那个解决方案,但它只有在您已经拥有对您想要实例化的类型的 Class 对象的引用时才有效。 是的,我知道。如果你可以做 E.class 那就太好了,但这只是因为擦除而给你 Object.class :) 这是解决这个问题的正确方法。这通常不是你想要的,但它就是你得到的。 那你怎么调用createContents()方法呢? 这不再是唯一的方法,现在有一种更好的方法,不需要使用 Guava 和 TypeToken 传入Class<?>
引用,see this answer for the code and links!【参考方案3】:
这是我想出的一个选项,它可能会有所帮助:
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();
【讨论】:
是的,即使没有泛型也一样——使用泛型,这个容器的实例化变得有点多余(你必须指定“E”是两次)。 嗯,当你使用 Java 和泛型时会发生这种情况......它们并不漂亮,而且存在严重的限制......【参考方案4】:我不知道这是否有帮助,但是当您子类化(包括匿名)泛型类型时,类型信息可通过反射获得。例如,
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 );
但这需要做很多工作,而且只适用于子类。不过可以很方便。
【讨论】:
是的,这很好,特别是如果泛型类是抽象的,你可以在具体的子类中这样做:) 如果类Foo
不是抽象的,此方法也可以工作。但为什么它只适用于 Foo 的匿名子类?假设我们将Foo
具体化(我们省略了abstract
),为什么new Foo<Bar>();
会导致错误,而new Foo<Bar>();
不会? (例外:“类不能转换为 ParameterizedType”)
@TimKuipers class Foo<E>
中的 <E>
未绑定到任何特定类型。只要E
没有静态 绑定,您就会看到异常行为,例如:new Foo<Bar>()
、new Foo<T>() ...
或class Fizz <E> extends Foo<E>
。第一种情况不是静态绑定的,它在编译时被擦除。第二种情况用另一个类型变量 (T) 代替 E
,但仍然未绑定。在最后一种情况下,很明显E
仍然是未绑定的。
静态绑定类型参数的一个例子是class Fizz extends Foo<Bar>
——在这种情况下,Fizz
的用户会得到一个Foo<Bar>
并且只能是Foo<Bar>
。因此,在这种情况下,编译器很乐意将该信息编码到 Fizz
的类元数据中,并将其作为 ParameterizedType
提供给反射代码。当你创建一个像new Foo<Bar>() ...
这样的匿名内部类时,它会做同样的事情,除了Fizz
之外,编译器会生成一个“匿名”类名,在编译外部类之前你不会知道。
需要注意的是,如果类型参数也是 ParameterizedType,这将不起作用。例如,Foo<Bar<Baz>>
。您将创建一个无法显式创建的 ParameterizedTypeImpl
实例。因此,检查getActualTypeArguments()[0]
是否返回ParameterizedType
是个好主意。如果是,那么您想获取原始类型,然后创建一个实例。【参考方案5】:
您需要某种抽象工厂来将责任推卸给:
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();
【讨论】:
..Factory.create() 是什么样子的? @OhadRFactory<>
是一个接口,所以没有正文。关键是您需要一个间接层来将责任转嫁给那些“知道”构造实例所需的代码的方法。使用普通代码而不是元语言 Class
或 Constructor
这样做要好得多,因为反射会带来整个世界的伤害。
现在您可以使用如下方法引用表达式创建工厂实例:SomeContainer<SomeElement> cont = new SomeContainer<>(SomeElement::new);
【参考方案6】:
如果你的意思是
new E()
那么这是不可能的。我还要补充一点,它并不总是正确的——你怎么知道 E 是否有公共的无参数构造函数?
但是您始终可以将创建委托给其他知道如何创建实例的类 - 它可以是 Class<E>
或类似这样的自定义代码
interface Factory<E>
E create();
class IntegerFactory implements Factory<Integer>
private static int i = 0;
Integer create()
return i++;
【讨论】:
【参考方案7】:如果您不想在实例化过程中键入两次类名,例如:
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();
【讨论】:
【参考方案8】:你可以使用:
Class.forName(String).getConstructor(arguments types).newInstance(arguments)
但是您需要提供确切的类名,包括包,例如。 java.io.FileInputStream
。我用它来创建一个数学表达式解析器。
【讨论】:
你如何在运行时获得泛型类型的确切类名? 您必须使用该类的实例来保存它。可行,虽然不太方便。如果您的泛型有 E 类型(或 T 或其他类型)的成员,则获取它的二进制名称只是foo.getClass().getName()
。那个实例来自哪里?我目前正在将一个传递给我正在处理的项目中的构造函数。【参考方案9】:
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());
【讨论】:
如果您在泛型中使用泛型类型,则此代码的好方法可能会导致 ClassCastException。然后您检索实际类型参数您应该检查它是否也是 ParamterizedType,如果是,则返回他的 RawType(或比这更好的东西)。另一个问题是,当我们扩展更多的时候,这段代码也会抛出 ClassCastExeption。 原因:java.lang.ClassCastException:sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl 无法转换为 java.lang.Class @DamianLeszczyński-Vash 也会失败,例如class GenericHome<T> extends Home<T>
【参考方案10】:
return (E)((Class)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
【讨论】:
这在我的原始问题示例中不起作用。SomeContainer
的超类就是 Object
。因此,this.getClass().getGenericSuperclass()
返回 Class
(类 java.lang.Object),而不是 ParameterizedType
。这实际上已经被同行回答***.com/questions/75175/… 指出了。
完全错误:线程“main”中的异常 java.lang.ClassCastException:java.lang.Class 无法转换为 java.lang.reflect.ParameterizedType【参考方案11】:
您可以使用以下 sn-p 实现此目的:
import java.lang.reflect.ParameterizedType;
public class SomeContainer<E>
E createContents() throws InstantiationException, IllegalAccessException
ParameterizedType genericSuperclass = (ParameterizedType)
getClass().getGenericSuperclass();
@SuppressWarnings("unchecked")
Class<E> clazz = (Class<E>)
genericSuperclass.getActualTypeArguments()[0];
return clazz.newInstance();
public static void main( String[] args ) throws Throwable
SomeContainer< Long > scl = new SomeContainer<>();
Long l = scl.createContents();
System.out.println( l );
【讨论】:
完全错误:线程“main”中的异常 java.lang.ClassCastException:java.lang.Class 无法转换为 java.lang.reflect.ParameterizedType【参考方案12】:来自Java Tutorial - Restrictions on Generics:
Cannot Create Instances of Type Parameters
您不能创建类型参数的实例。例如,以下代码会导致编译时错误:
public static <E> void append(List<E> list)
E elem = new E(); // compile-time error
list.add(elem);
作为一种解决方法,您可以通过反射创建一个类型参数的对象:
public static <E> void append(List<E> list, Class<E> cls) throws Exception
E elem = cls.getDeclaredConstructor().newInstance(); // OK
list.add(elem);
您可以按如下方式调用 append 方法:
List<String> ls = new ArrayList<>();
append(ls, String.class);
【讨论】:
cls.newInstance()
已贬值以支持cls.getDeclaredConstructor().newInstance()
。
@antikbd 感谢您的提示!我已经相应地更新了示例。【参考方案13】:
我以为我能做到,但很失望:它不起作用,但我认为它仍然值得分享。
也许有人可以纠正:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface SomeContainer<E>
E createContents();
public class Main
@SuppressWarnings("unchecked")
public static <E> SomeContainer<E> createSomeContainer()
return (SomeContainer<E>) Proxy.newProxyInstance(Main.class.getClassLoader(),
new Class[] SomeContainer.class , new InvocationHandler()
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
Class<?> returnType = method.getReturnType();
return returnType.newInstance();
);
public static void main(String[] args)
SomeContainer<String> container = createSomeContainer();
[*] System.out.println("String created: [" +container.createContents()+"]");
它产生:
Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
at Main.main(Main.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
第 26 行是带有[*]
的行。
唯一可行的解决方案是@JustinRudd 提出的解决方案
【讨论】:
【参考方案14】:如果你需要一个泛型类中类型参数的新实例,那么让你的构造函数要求它的类...
public final class Foo<T>
private Class<T> typeArgumentClass;
public Foo(Class<T> typeArgumentClass)
this.typeArgumentClass = typeArgumentClass;
public void doSomethingThatRequiresNewT() throws Exception
T myNewT = typeArgumentClass.newInstance();
...
用法:
Foo<Bar> barFoo = new Foo<Bar>(Bar.class);
Foo<Etc> etcFoo = new Foo<Etc>(Etc.class);
优点:
比 Robertson 的超级类型令牌 (STT) 方法简单得多(问题更少)。 比 STT 方法(早餐会吃掉您的手机)效率更高。缺点:
无法将 Class 传递给默认构造函数(这就是 Foo 为 final 的原因)。如果您确实需要一个默认构造函数,您可以随时添加一个 setter 方法,但您必须记得稍后再给她一个调用。 Robertson 的反对意见... 比害群之马还多的酒吧(尽管再次指定类型参数类不会完全杀死你)。与 Robertson 的说法相反,这并不违反 DRY 原则,因为编译器将确保类型正确性。 不完全是Foo<L>
proof。对于初学者...如果类型参数类没有默认构造函数,newInstance()
将抛出一个 wobbler。无论如何,这确实适用于所有已知的解决方案。
缺乏对 STT 方法的完全封装。不过没什么大不了的(考虑到 STT 的惊人性能开销)。
【讨论】:
【参考方案15】:你可以用一个类加载器和类名,最后加上一些参数。
final ClassLoader classLoader = ...
final Class<?> aClass = classLoader.loadClass("java.lang.Integer");
final Constructor<?> constructor = aClass.getConstructor(int.class);
final Object o = constructor.newInstance(123);
System.out.println("o = " + o);
【讨论】:
这比只传递类对象更糟糕 您根本不需要显式引用类加载器。【参考方案16】:当您在编译时使用 E 时,您并不真正关心实际的泛型类型“E”(您使用反射或使用泛型类型的基类),因此让子类提供 E 的实例。
abstract class SomeContainer<E>
abstract protected E createContents();
public void doWork()
E obj = createContents();
// Do the work with E
class BlackContainer extends SomeContainer<Black>
protected Black createContents()
return new Black();
【讨论】:
我喜欢这种方法,因为它可读且不会带来任何施法魔法。缺点是您必须在每个派生类中实现 createContents。即使你不需要它。另一种方法是使 createContents 不是抽象的,而是使用空实现(返回 null/throws)......在这种情况下,您只能在需要时实现它。【参考方案17】:有各种库可以使用类似于 Robertson 文章讨论的技术为您解析 E
。这是createContents
的一个实现,它使用TypeTools 来解析由E 表示的原始类:
E createContents() throws Exception
return TypeTools.resolveRawArgument(SomeContainer.class, getClass()).newInstance();
这假定 getClass() 解析为 SomeContainer 的子类,否则将失败,因为如果 E 的实际参数化值未在子类中捕获,则在运行时将被删除。
【讨论】:
【参考方案18】:您现在就可以做到这一点,它不需要一堆反射代码。
import com.google.common.reflect.TypeToken;
public class Q26289147
public static void main(final String[] args) throws IllegalAccessException, InstantiationException
final StrawManParameterizedClass<String> smpc = new StrawManParameterizedClass<String>() ;
final String string = (String) smpc.type.getRawType().newInstance();
System.out.format("string = \"%s\"",string);
static abstract class StrawManParameterizedClass<T>
final TypeToken<T> type = new TypeToken<T>(getClass()) ;
当然,如果您需要调用需要一些反射的构造函数,但这是有据可查的,那么这个技巧就不是了!
这里是JavaDoc for TypeToken。
【讨论】:
此解决方案适用于有限的情况,就像@noah 的反思回答一样。我今天都尝试了它们......最后我将参数类的实例传递给参数化类(以便能够调用 .newInstance() )。 “泛型”的很大缺陷... new Foo@Noah 回答的改进。
改变的原因
a]如果您更改订单时使用超过 1 种泛型类型会更安全。
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();
【讨论】:
【参考方案20】:这是createContents
的一个实现,它使用TypeTools 来解析E
表示的原始类:
E createContents() throws Exception
return TypeTools.resolveRawArgument(SomeContainer.class, getClass()).newInstance();
此方法仅在 SomeContainer
被子类化时才有效,因此 E
的实际值在类型定义中被捕获:
class SomeStringContainer extends SomeContainer<String>
否则 E 的值会在运行时被擦除且不可恢复。
【讨论】:
【参考方案21】:考虑一种更实用的方法:不要无中生有地创建一些 E(这显然是代码异味),而是传递一个知道如何创建 E 的函数,即
E createContents(Callable<E> makeone)
return makeone.call(); // most simple case clearly not that useful
【讨论】:
从技术上讲,您不是在传递一个函数,而是在传递一个 函数对象(也称为 functor)。 或者为了克服捕捉Exception
使用Supplier<E>
代替。【参考方案22】:
不幸的是,Java 不允许您做您想做的事情。见official workaround:
您不能创建类型参数的实例。例如,以下代码会导致编译时错误:
public static <E> void append(List<E> list)
E elem = new E(); // compile-time error
list.add(elem);
作为一种解决方法,您可以通过反射创建一个类型参数的对象:
public static <E> void append(List<E> list, Class<E> cls) throws Exception
E elem = cls.newInstance(); // OK
list.add(elem);
您可以按如下方式调用 append 方法:
List<String> ls = new ArrayList<>();
append(ls, String.class);
【讨论】:
你能告诉我为什么你这样做的时候会反对吗?我不明白为什么官方的解决方法是一个糟糕的解决方案。谢谢。 我猜你会投反对票,因为你的答案与陆克文的基本相同:***.com/a/75254/103412【参考方案23】:在 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
是constructor reference。
如果您的构造函数接受参数,您可以使用 lambda 表达式:
SomeContainer<BigInteger> bigIntegerContainer
= new SomeContainer<>(() -> new BigInteger(1));
【讨论】:
好一个。它避免了反射和必须处理异常。 太好了。不幸的是,对于 Android 用户,这需要 API 级别 24 或更高。 ...这与this even older answer 没有什么不同,表明它背后的技术模式甚至比 Java 对 lambda 表达式和方法引用的支持还要古老,而您甚至可以在升级后将旧代码与它们一起使用编译器… 可以只输入SomeContainer stringContainer = new SomeContainer(String::new);
吗?
@AaronFranke:不,因为那样你会使用raw type。【参考方案24】:
这是一个改进的解决方案,基于@noah、@Lars Bohl 和其他一些人已经提到的ParameterizedType.getActualTypeArguments
。
实施中的第一个小改进。工厂不应该返回实例,而是一个类型。一旦您使用Class.newInstance()
返回实例,您就会减少使用范围。因为只有无参数的构造函数可以像这样被调用。更好的方法是返回一个类型,并允许客户端选择他想要调用的构造函数:
public class TypeReference<T>
public Class<T> type()
try
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
if (pt.getActualTypeArguments() == null || pt.getActualTypeArguments().length == 0)
throw new IllegalStateException("Could not define type");
if (pt.getActualTypeArguments().length != 1)
throw new IllegalStateException("More than one type has been found");
Type type = pt.getActualTypeArguments()[0];
String typeAsString = type.getTypeName();
return (Class<T>) Class.forName(typeAsString);
catch (Exception e)
throw new IllegalStateException("Could not identify type", e);
这是一个用法示例。 @Lars Bohl 仅展示了一种通过扩展获得具体化的通用方法。 @noah 只能通过使用 创建一个实例。以下是演示这两种情况的测试:
import java.lang.reflect.Constructor;
public class TypeReferenceTest
private static final String NAME = "Peter";
private static class Person
final String name;
Person(String name)
this.name = name;
@Test
public void erased()
TypeReference<Person> p = new TypeReference<>();
Assert.assertNotNull(p);
try
p.type();
Assert.fail();
catch (Exception e)
Assert.assertEquals("Could not identify type", e.getMessage());
@Test
public void reified() throws Exception
TypeReference<Person> p = new TypeReference<Person>();
Assert.assertNotNull(p);
Assert.assertEquals(Person.class.getName(), p.type().getName());
Constructor ctor = p.type().getDeclaredConstructor(NAME.getClass());
Assert.assertNotNull(ctor);
Person person = (Person) ctor.newInstance(NAME);
Assert.assertEquals(NAME, person.name);
static class TypeReferencePerson extends TypeReference<Person>
@Test
public void reifiedExtenension() throws Exception
TypeReference<Person> p = new TypeReferencePerson();
Assert.assertNotNull(p);
Assert.assertEquals(Person.class.getName(), p.type().getName());
Constructor ctor = p.type().getDeclaredConstructor(NAME.getClass());
Assert.assertNotNull(ctor);
Person person = (Person) ctor.newInstance(NAME);
Assert.assertEquals(NAME, person.name);
注意:您可以强制TypeReference
的客户端在创建实例时始终使用,方法是使此类抽象:
public abstract class TypeReference<T>
。我没有这样做,只是为了显示已擦除的测试用例。
【讨论】:
【参考方案25】:希望现在帮上忙还为时不晚!!!
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();
如果您使用无对象类型扩展泛型类,则使用反射会创建运行时错误。要将您的泛型类型扩展为对象,请将此错误转换为编译时错误。
【讨论】:
【参考方案26】:你能做的是-
首先声明那个泛型类的变量
2.然后创建它的构造函数并实例化该对象
然后在你想用的地方用它
例子-
1
private Class<E> entity;
2
public xyzservice(Class<E> entity)
this.entity = entity;
public E getEntity(Class<E> entity) throws InstantiationException, IllegalAccessException
return entity.newInstance();
3.
E e = getEntity(实体);
【讨论】:
返回 entity.newInstance();触发警告:“Class使用TypeToken<T>
类:
public class MyClass<T>
public T doSomething()
return (T) new TypeToken<T>().getRawType().newInstance();
【讨论】:
如果你使用 Guava 而不是 GSON,那就有点不同了:(T) new TypeToken<T>(getClass()).getRawType().newInstance();
【参考方案28】:
请注意,kotlin 中的泛型类型可能没有默认构造函数。
implementation("org.objenesis","objenesis", "3.2")
val fooType = Foo::class.java
var instance: T = try
fooType.newInstance()
catch (e: InstantiationException)
// Use Objenesis because the fooType class has not a default constructor
val objenesis: Objenesis = ObjenesisStd()
objenesis.newInstance(fooType)
Withou default constructor
Objenesis
【讨论】:
【参考方案29】:Ira 的解决方案启发了我,并对其稍作修改。
abstract class SomeContainer<E>
protected E createContents()
throw new NotImplementedException();
public void doWork()
E obj = createContents();
// Do the work with E
class BlackContainer extends SomeContainer<Black>
// this method is optional to implement in case you need it
protected Black createContents()
return new Black();
如果您需要 E
实例,您可以在派生类中实现 createContents
方法(或者在您不需要时不实现它。
【讨论】:
以上是关于在Java中创建泛型类型的实例?的主要内容,如果未能解决你的问题,请参考以下文章