Java 如何在实例化T的子类时返回泛型类型T

Java 如何在实例化T的子类时返回泛型类型T,java,generics,inheritance,Java,Generics,Inheritance,我想得到一个参数化类,它能够返回类型为T的对象和T的子对象 代码如下: 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: //

我想得到一个参数化类,它能够返回类型为T的对象和T的子对象

代码如下:

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();
  }

}
我发现以下错误:

testGenerics类型中的方法getA(类)不适用于参数(类


为什么会这样?如何修复它?

这不起作用,因为
B
不是
T
。是的,
B
也扩展了
T
,但它不是
T
。假设您还有一个类
C扩展了一个
,并创建了
testGenerics
的实例。您的
getA()
方法将实例化
B
,但应返回
C
。但是,通过一些调整,以下方法可以很好地工作:

testGenerics<B> tg = new testGenerics<B>();
B b = tg.getA(B.class);

但是,在这里不能真正使用
t
(比如
)。由于
T
是一种参数类型,因此您无法保证
B
是否是或扩展
T

您的问题是类定义
类测试泛型

这意味着
T
是在创建该类的实例时定义的,并且可以绑定到
A
的任何子类,该子类可能不是
B
,而是
C
等。因此传递
B.class
不能保证匹配

要解决此问题,请将
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); 
}
getA(类clazz)抛出实例化异常、IllegaAccessException、IllegalArgumentException、InvocationTargetException、NoSuchMethodException、SecurityException{
返回clazz.getConstructor().newInstance();
}
//这里不需要泛型,因为上面的方法返回一个anyways。
//如果它返回T,您必须将这里的返回类型更改为B,因为getA(B.class)现在将T绑定为B
getA()抛出异常{
返回getA(B级);
}

由于方法级别
T
隐藏了类级别的定义,因此您需要做一些事情:要么使用不同的名称(例如
S
),要么删除类级别的定义(这在任何情况下都没有多大意义)。

@Thomas这并不能解决报告的编译问题。对,看到了。问题有所不同:
T
绑定到
testGenerics
(应该是
testGenerics
btw.)的实例,因此可能不是
B
  public <S extends A> S getA(Class<S> clazz) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
      return clazz.getConstructor().newInstance();
  }
<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); 
}