为什么我不能在Java:中做到这一点
public class TestClass {
public <T extends TestClass> T test(){
return this; // error here
}
}
据我所知,this
将始终是某个扩展TestClass
的类的实例,那么为什么编译器不允许使用上面的代码呢?即使我将扩展TestClass
,那么this
的类型无论如何都将适合extends TestClass
。我得到以下错误:
错误:(4,16(java:不兼容的类型:无法转换TestClass至T
假设你有SubTestClass extends TestClass
,然后你写:
TestClass instance = new TestClass();
SubTestClass result = instance.test();
这对于test()
类的签名是合法的,尽管这是无稽之谈(1(。编译器将推断出T
是类SubTestClass
。然后很明显,TestClass
实例不是instanceof SubTestClass
。因此,在合法使用test()
方法的情况下,返回this
可能会产生类型不匹配,这就是编译器告诉您的。
使用test()
签名,不可能返回除null
以外的任何值,因为null
是唯一可以分配给未知类型变量的值。
让我解释一下最后一个声明(在评论中询问(:test()
方法的实现必须返回一些与T
类型匹配的值,而具体类型(从调用情况推断为SubTestClass
(不能推断给该方法——在参数或实例字段中没有任何内容可以读取在这种情况下返回SubTestClass
的要求。在另一种调用情况下,可能需要返回AnotherSubTestClass
,并且无法区分第一种和第二种情况。
如果返回this
(使用(T)
强制转换使其通过编译器(,它将在第一种或第二种情况下失败,或者在这两种情况下都失败。因此,如果没有很高的失败风险,你就无法做到这一点。
唯一可以成功分配给SubTestClass
和AnotherSubTestClass
变量的值是null
值。因此,这是您可以安全地从具有此类签名的方法返回的唯一值。
(1( 如果有一个泛型方法,泛型类型不能从参数中推导出来,而只能从预期的结果类型中推断出来,那就很难工作了——该方法应该如何知道调用者的期望?
您误解了什么:
据我所知,
this
将始终是扩展TestClass 的某个类的实例
这不是真的,this
可以是TestClass
本身的一个实例。这就是编译器崩溃的原因。为了修复它,您应该将this
强制转换为T
:
return (T) this;
编辑01:
顺便说一句,如果你想做这样的事情,我也建议你添加这两个选项中的一个来防止RuntimeError:
- 将
TestClass
设置为抽象类 - 请确保
this
不是TestClass
的实例,您可以使用以下内容来执行此操作:this.getClass().equals(TestClass.class)
希望这能有所帮助。
"this"表示类"TestClass",因为TestClass是T的superClass,所以superClass不能转换为subClass,但您可以尝试强制类型转换,或者将返回类型设置为"TestClass"。
public <T extends TestClass> T test() {
return (T)this;
}
编辑01:强制强制转换是错误的,它可能会导致运行时错误。