从泛化为 <T 扩展 TestClass 的泛型方法返回此值>



为什么我不能在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)强制转换使其通过编译器(,它将在第一种或第二种情况下失败,或者在这两种情况下都失败。因此,如果没有很高的失败风险,你就无法做到这一点。

唯一可以成功分配给SubTestClassAnotherSubTestClass变量的值是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:强制强制转换是错误的,它可能会导致运行时错误。

最新更新