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
,但为什么会出现此错误?
谢谢
答案 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
。