如何在实例化T

时间:2018-03-21 14:28:22

标签: 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:
    //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创建一个类型为T的实例,扩展为A.

然而,当我决定从B.class(扩展A)获得A时:

getA(B.class)

我收到以下错误:

  

类型testGenerics&lt;中的方法getA(Class&lt; T&gt;) T>不适用于参数(Class&lt; B&gt;)

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

2 个答案:

答案 0 :(得分:1)

您的问题是课程定义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隐藏了类级别的定义,您需要对此做一些事情:使用不同的名称(例如{{1}})或删除类级别的定义(它无论如何都没有多大意义。

答案 1 :(得分:0)

这不起作用,因为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是参数类型,因此无法保证B是{延伸T还是data dataset_1; input CASENO X; datalines; 1 100 2 200 3 300 ; data dataset_2; input CASENO Y; datalines; 2 200000 3 300000 ;