繁体   English   中英

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

[英]How to return generic type T when instantiating a subclass of T

我想获取一个可以返回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();
  }

}

我是这样想的:

我声明的是泛型T,它扩展了A。因此,我可以从Class clazz创建一个扩展了A的T类型的实例。

但是,当我决定从B.class获取A时(哪个扩展了A):

getA(B.class)

我收到以下错误:

类型为testGenerics <T>的方法getA(Class <T>)不适用于参数(Class <B>)

为什么是这样? 我该如何解决?

您的问题是类定义class testGenerics<T extends A>

这意味着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); 
}

由于方法级别T在类级别隐藏了定义,因此您需要为此做些事情:使用其他名称(例如S )或在类级别删除定义(无论如何在这里都没有多大意义)。

这是行不通的,因为B不是T 是的, B也扩展了T ,但不是T 假设您还有一个类C extends A并创建了一个testGenerics<C>的实例。 您的getA()方法将实例化B但应返回C 但是,以下内容在进行一些调整后仍然可以正常工作:

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

如何解决此问题取决于您实际想要做什么。 例如,这允许您实例化A任何子类:

  public <S extends A> S getA(Class<S> clazz) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
      return clazz.getConstructor().newInstance();
  }

但是,您实际上不能在这里使用T (例如<S extends T> )。 由于T是参数类型,因此不能保证BT还是扩展T

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM