我尝试从我的Main获取foo():
<T extends Main> T foo()
{
return this; // "this" it is a instance of Main
}
并使用它
Main m = new Main();
Main m2 = m.foo();
我遇到了错误:&#34; 不兼容的类型。必填T,找到主&#34;在方法foo()中。
我知道我可以用这个:
<T extends Main> T foo2(T a) {
return a;
}
并使用它:
Main m = new Main();
Main m3 = m.foo2(m);
它工作正常。但我无法理解,为什么我不能使用第一种方法?因为this
绝对是Main的实例扩展。
答案 0 :(得分:8)
如果您在类型<T extends Main> T foo();
中定义Main
,则无法返回this
,因为T
可能是Main
的子类型,Main
当然不是。因此,如果你有MainSubType m = new Main().foo();
编译器希望T
为MainSubType
,但面对它只有Main
类型,所以你必须用艰难的方式解析它,我不能在这里推荐,但这就是你如何去<T extends Main> T foo(){return (T) this}
。如果你这样做,你应该能够编译其余部分。
如果它不适用于foo()中的(T)-cast,则需要提供更多上下文/代码。
答案 1 :(得分:2)
作为user2504380 already pointed out:如果可能的话,你可以默默地&#34; upcast&#34;任何Main
到Main
的任何子类。
但是,你可能根本不需要这个类型参数(至少,我无法想象它可能有意义的情况)。如果你的班级是这样的:
class Main {
Main getIt() {
return this;
}
}
然后你可以创建Main
的子类,并且,由于Java中的covariance,重写方法以返回相应的Main
class SubMain {
// Overriding with a more specific return type:
@Override
SubMain getIt() {
return this;
}
}
这意味着方法的返回类型由您调用方法的引用类型决定:
Main main = new Main();
SubMain subMain = new SubMain();
Main m0 = main.getIt();
Main m1 = subMain.getIt();
// This does not work
//SubMain s0 = main.getIt();
// But this works: The instance IS a SubMain, and returns a SubMain:
SubMain s1 = subMain.getIt();
在涉及自引用泛型类型的更复杂的场景中,您可以使用getThis trick。
答案 2 :(得分:0)
正如其他人已经指出的那样,
<T extends Main>
编译器无法确定T的类型。它可以是Main或Main的任何子类。由于这种不确定性,编译器不允许返回它。如果你使用T之类的
来转换retrun类型(T) this
或者如果存在类型为T的方法参数,则没有不确定性。