<t extends =“”superclass =“”>

时间:2016-04-02 08:48:20

标签: generics groovy

class TestClass <T extends SuperClass>{
 public List<T> doSmth(){
    ///....
    List testObjects = []
    testObjects.add(new T(arg))
   return testObjects;
 }
}

class SuperClass{

}
class A extends SuperClass{
 A(Arg arg){
  ....
}
class B extends SuperClass{
 B(Arg arg){
  ....
}

////////test
class Main{
 List <A> a
 List <B> b

 Main(){
  this.a = new TestClass<A>().doSmth()
  this.b = new TestClass<B>().doSmth()
 }
}

发现异常(groovy.lang.GroovyRuntimeException:找不到SuperClass的匹配构造函数)

 testObjects.add(new T(arg))

这是非常正确的,因为SuperClass没有构造函数。但是子类有一个,并且它们都具有相同的签名,arg具有相同的类型。

有人可以帮我找到解决问题的方法吗?

2 个答案:

答案 0 :(得分:3)

不幸的是,无法使用new T创建泛型类型的新实例。所以你需要解决这个问题。

解决此问题的一种方法是在doSmth()中包含一个为您创建实例的闭包参数。

public List<T> doSmth(Closure newT) {
    List testObjects = []
    testObjects.add(newT(arg))
    return testObjects;
}

并提供在调用方法时创建新实例的代码:

Main() {
    this.a = new TestClass<A>().doSmth { new A(it) }
    this.b = new TestClass<B>().doSmth { new B(it) }
}

答案 1 :(得分:2)

您的代码无法正常工作的原因与AB的构造函数不匹配。原因是缺少接受SuperClass中的字符串的构造函数。
new T()没有按预期工作。在您的代码中,它变为new SuperClass(arg)。以下代码演示了它

class TestClass <T extends SuperClass> {
    public void doSmth(){
        println new T().class.simpleName;
    }
}

class SuperClass{}
class A extends SuperClass{}
class B extends SuperClass{}

new TestClass<A>().doSmth()
new TestClass<B>().doSmth()
new TestClass<String>().doSmth() //even this works

输出

SuperClass
SuperClass
SuperClass

TestClass <T>将打印ObjectTestClass <T extends A>将打印A,依此类推。

Groovy在运行时没有泛型类型信息。 Groovy甚至不进行编译类型检查(例如new TestClass<String>())。但它保留了一些信息以使new T()起作用。

  

Java的泛型实现包含一个称为&#34;类型擦除的功能&#34; &#34;扔掉&#34;完成静态类型检查后的泛型类型信息。这使得Java可以轻松地与遗留的&#34;非泛型&#34;库。 Groovy目前做得更进一步,抛弃了泛源信息&#34;在源级&#34;。泛型信息保存在签名中http://web.archive.org/web/20150102195947/http://groovy.codehaus.org/Generics