gpt4 book ai didi

java - 为什么在用非泛型方法覆盖泛型方法时,子签名和未经检查的规则在返回类型上以这种方式工作?

转载 作者:搜寻专家 更新时间:2023-10-31 20:17:17 25 4
gpt4 key购买 nike

public class Base {

<T> List<? extends Number> f1() {return null;}
List<? extends Number> f2() {return null;}
<T extends Number> List<T> f3() {return null; }
}

class Derived extends Base {

List<String> f1() {return null;} // compiles fine !!!
List<String> f3() {return null; } // compiles fine !!!

// compile ERR: return type is incompatible with Base.f2()
List<String> f2() {return null;}
}

为什么在派生类中重写方法 f1() 和 f3() 的定义没有编译错误,就像在派生类中重写 f2() 方法的定义(给出编译错误 “返回类型与 Base 不兼容。 f2()”)?

JLS 中的子签名覆盖规则允许覆盖方法(在派生类中)是非泛型的,而被覆盖的方法(在基类中)是泛型的。

未经检查的覆盖规则允许在子类中创建返回类型 List<String>而不是 List<T>在基类中。

但我无法解释下面行为的差异,我不明白为什么派生类中的 f1() 和 f3() 覆盖定义编译成功(在 Eclipse、SE8 上),忽略有界类型参数施加的限制为 f3() 和有界通配符为 f1()!

附言我的猜测 - 在 Derived 编译器的 f1() 和 f3() 中将这两种方法视为仅返回“原始”列表 - 编译器首先进行删除(目前仅在 Derived 中!?),然后将 Derived 中的这些删除方法与未删除的方法进行比较(到目前为止)Base 中的方法。现在未经检查的覆盖规则是可以的(并且不需要检查边界 - 这根本不可能),编译器决定这是正确的覆盖并且编译更进一步......并且在 Base.f1() 和 Base 中编译泛型结束的某个地方.f3() 也被删除了:)))

This SO answer也为这个主题添加了想法。

最佳答案

您的 f1f3 覆盖不是通用的,尽管原始声明是通用的。编译允许覆盖的返回类型与原始返回类型不同,因为它们具有相同的类型删除 (List)。我认为来自JLS 8.4.5 ,尽管坦率地说,我发现规范的这一部分有点令人困惑。

如果您再次将覆盖更改为通用:

<T> List<String> f1() {return null;}
<T extends Number> List<String> f3() {return null; }

...然后都无法编译:

error: <T#1>f1() in Derived cannot override <T#2>f1() in Base
<T> List<String> f1() {return null;}
^
return type List<String> is not compatible with List<? extends Number>
where T#1,T#2 are type-variables:
T#1 extends Object declared in method <T#1>f1()
T#2 extends Object declared in method <T#2>f1()

error: <T#1>f3() in Derived cannot override <T#2>f3() in Base
<T extends Number> List<String> f3() {return null; }
^
return type List<String> is not compatible with List<T#1>
where T#1,T#2 are type-variables:
T#1 extends Number declared in method <T#1>f3()
T#2 extends Number declared in method <T#2>f3()

请注意,即使在您的原始代码中,javac 也会发出有关不安全转换的警告,如果您使用 -Xlint:unchecked,它会提供详细信息:

return type requires unchecked conversion from List<String> to List<? extends Number>
return type requires unchecked conversion from List<String> to List<T>

关于java - 为什么在用非泛型方法覆盖泛型方法时,子签名和未经检查的规则在返回类型上以这种方式工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46998262/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com