[英]How to return generic type T when instantiating a subclass of T
I want to get a Parametrized class which is able to return an object of type T AND children of T 我想获取一个可以返回T类型的对象和T的子代的参数化类
This is the code: 这是代码:
import java.lang.reflect.InvocationTargetException;
class A {};
class B extends A {};
public class testGenerics<T extends A> {
T a;
T getA() {
return getA(B.class); // Compilation problem:
//The method getA(Class<T>) in the type testGenerics<T> is not applicable for the arguments (Class<B>)
}
T getA(Class<T> clazz) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
return clazz.getConstructor().newInstance();
}
}
This is how I think: 我是这样想的:
I am declaring generic type T, that extends A. Therefore, I can create from Class clazz an instance of type T extending A. 我声明的是泛型T,它扩展了A。因此,我可以从Class clazz创建一个扩展了A的T类型的实例。
However, when I decide to get A from B.class (Which extends A): 但是,当我决定从B.class获取A时(哪个扩展了A):
getA(B.class)
I get following error: 我收到以下错误:
The method getA(Class< T >) in the type testGenerics< T > is not applicable for the arguments (Class< B >)
类型为testGenerics <T>的方法getA(Class <T>)不适用于参数(Class <B>)
Why is this? 为什么是这样? How can I fix it?
我该如何解决?
Your problem is the class definition class testGenerics<T extends A>
. 您的问题是类定义
class testGenerics<T extends A>
。
That means that T
is defined when creating an instance of that class and could be bound to any subclass of A
- which might not be B
but C
etc. Thus passing B.class
isn't guaranteed to match. 这意味着
T
是在创建该类的实例时定义的,并且可以绑定到A
任何子类-可能不是B
而是C
等。因此,不能保证传递B.class
匹配。
To fix that put the defintion of T
at the method level: 要解决此问题,请将
T
的定义置于方法级别:
<T extends A> A getA(Class<T> clazz) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
return clazz.getConstructor().newInstance();
}
//No generics needed here, since the method above returns A anyways.
//If it'd return T you'd have to change the return type here to B since getA(B.class) binds T to be B now
A getA() throws Exception {
return getA(B.class);
}
Since the method level T
hides the definition at the class level you need to do something about that: either use a different name (eg S
) or remove the definition at the class level (it doesn't make much sense there anyways). 由于方法级别
T
在类级别隐藏了定义,因此您需要为此做些事情:使用其他名称(例如S
)或在类级别删除定义(无论如何在这里都没有多大意义)。
This does not work because B
is not T
. 这是行不通的,因为
B
不是T
Yes, B
also extends T
, but it is not T
. 是的,
B
也扩展了T
,但不是T
Imagine you have also a class C extends A
and create an instance of testGenerics<C>
. 假设您还有一个类
C extends A
并创建了一个testGenerics<C>
的实例。 Your getA()
method would instantiate B
but should return C
. 您的
getA()
方法将实例化B
但应返回C
The following, however, works fine with a few tweaks: 但是,以下内容在进行一些调整后仍然可以正常工作:
testGenerics<B> tg = new testGenerics<B>();
B b = tg.getA(B.class);
How to fix this depends on what you actually want to do. 如何解决此问题取决于您实际想要做什么。 This, for instance allows you to instantiate any subclass of
A
: 例如,这允许您实例化
A
任何子类:
public <S extends A> S getA(Class<S> clazz) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
return clazz.getConstructor().newInstance();
}
However you can't really use T
here (like <S extends T>
). 但是,您实际上不能在这里使用
T
(例如<S extends T>
)。 Since T
is a parameter type, you have no guarantees on whether B
is or extends T
. 由于
T
是参数类型,因此不能保证B
是T
还是扩展T
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.