泛型-无法使用T扩展Base来返回T的Base

时间:2019-03-15 22:09:25

标签: java generics extends

public class Testing<T extends Tuple> {

   public T method(){
     return new Tuple(); //Syntax error
   }
}

这是我得到的错误(语法错误):

Incompatible Types:
Required: T
Found: com.company.package1.Tuple

即使我一开始就写了T extends Tuple,但为什么会出现此错误?

谢谢

6 个答案:

答案 0 :(得分:2)

说明

通过引入通用参数T,您可以为班级用户提供为您设置类型的可能性。

泛型的作用类似于方法的参数,但类似于类的参数

extends Tuple是对用户的约束。因此,允许您的用户使用IntTuple。您的方法说它返回T,但实际上只返回{​​{1}}。当用户将通用参数设置为Tuple时,该方法还需要返回IntTuple,而不是IntTuple


示例

考虑以下更易读的示例:

Tuple

用户可以像这样使用服务器场:

public class Farm<A extends Animal> {
    public A produce() {
        // ...
    }
}

这里的重要部分是Farm<Pig> pigFarm = new Farm<>(); Pig pig = produce(); 现在必须必须分发produce。而且,如果另一个用户拥有Pig,则该服务器场必须发出Farm<Cow>

但是,您当前的实现是:

Cow

但是public A produce() { return new Animal(); } 并不是Animal,也不是Pig。因此它无法工作。 (理论上)只有在用户出于某种原因而使用Cow时,它才会起作用。


解决方案

您极有可能打算做完全不同的事情。因此,既然您已了解问题,请重新考虑您的设计。

也许您甚至根本不想使用泛型,而只返回Farm<Animal>,删除Animal。 也许您确实想返回T,但从其他地方获取实际的T实例。用这种方法创建一个新的T实例将非常困难,因为您不知道用户实际设置的确切类型T是什么。 T的构造函数可能不同于Cow


注意

其他答案建议强制转换为Pig,但这可能无法达到您的预期目的。这是使该代码以某种方式编译的方式。然后它将支持T,但不支持子类。在示例中,这反映了Tuple。对于所有其他输入,它将以Farm<Animal>失败。由于ClassCastException无法转换为Animal等。

答案 1 :(得分:0)

由于从具有Tuple作为返回类型的方法中返回T,所以会出现编译错误。在运行时,此T可能不是Tuple,而是对其进行扩展的某种类型。您可以将其转换为T

return (T) new Tuple();

type erasure之后,由于return (Tuple) new Tuple();被绑定到Tuple,它变为T。这就是为什么它将编译没有任何错误的原因。

但是它将被视为未经检查的演员,并向您发出警告。可能会在执行时导致ClassCastException,而不是Tuple的某个子类。{p>

答案 2 :(得分:0)

您必须强制转换为T,因为方法method()必须返回类型为T的对象

 class Testing<T extends Tuple> {

    public T method(){
        return (T) new Tuple()
    }
}

答案 3 :(得分:0)

您应按以下步骤更改代码以解决此错误:

public class Testing<T extends Tuple> {
     @SuppressWarnings({"unchecked"})
     public T method(){
          return (T) new Tuple();
     }

答案 4 :(得分:0)

@andreas在第一条评论中是正确的。您应该问下摆以使他的评论成为答案并接受。

将父级强制转换为子类将不起作用。

为了使事情更清楚一点,请看以下示例:

public class Tuple {
}

public class NamedTuple extends Tuple {
    public String getName() {
        return "NamedTuple";
    }
}

public class Testing<T extends Tuple> {
    public T method(){
        return (T) new Tuple(); // asking for trouble
    }
}

public static void main(String[] args) {
    final NamedTuple namedTuple = new Testing<NamedTuple>().method();

    // what exactly can be expected here, given that method() creates a Tuple?
    namedTuple.getName();
}

致电namedTuple.getName()会发生什么? Testing.method()创建了Tuple的实例,但是Tuple没有getName()类期望的NamedTuple方法。

幸运的是,它永远不会出现,因为method()会因ClassCastException而失败。

答案 5 :(得分:0)

仅仅因为T扩展了Tuple并不意味着Tuple的类型为T

相关问题