我正在阅读jls,我面临以下任期:
return-type-substitutable
来自jls的片段
返回类型为R1的方法声明d1 return-type-substitutable为另一个返回类型为R2的方法d2 如果以下任何一种情况属实:
如果R1无效,则R2无效。
如果R1是基本类型,则R2与R1相同。
如果R1是引用类型,则以下之一为真:
- 适应d2(§8.4.4)类型参数的R1是。的子类型 R2。
- 可以通过未经检查的转换将R1转换为R2的子类型 (§5.1.9)。
- d1与d2(§8.4.2)没有相同的签名,R1 = | R2 |。
前两点很明显。
你可以澄清吗?- R1,适用于d2(§8.4.4)的类型参数,是R2的子类型。
- 可以通过未经检查的转换(第5.1.9节)将R1转换为R2的子类型。
- d1与d2(§8.4.2)没有相同的签名,R1 = | R2 |。
感谢
P.S。 为Luiggi Mendoza
interface Foo {
List<String> foo(String arg1, String arg2);
}
class Bar implements Foo {
@Override
public ArrayList<String> foo(String arg1, String arg2) {
//implementation...
return null;
}
public String foo(String arg1, String arg2, String arg3) {
//implementation...
return null;
}
}
它正在起作用。
如果返回类型为R1的方法声明d1覆盖或隐藏 声明另一个方法d2,返回类型为R2,则d1必须为 d2的return-type-substitutable(第8.4.5节),或编译时错误 发生
If R1 is a reference type then **one of the following** is true:
...
--d1 does not have the same signature as d2 (§8.4.2), and R1 = |R2|.
...
代码:
interface Foo {
List<String> foo(String arg1, String arg2);
}
class Bar implements Foo {
@Override
public List<String> anotherName(String arg1, String arg2,Object obj) {
return null;
}
这是编译错误。
R1 == R2(List<String > == List<String>
)
D1!= D2
我在哪里违反了规则?
答案 0 :(得分:2)
我们有这个界面
interface Foo {
List<String> foo(String arg1, String arg2);
}
实施它的课程
class Bar implements Foo {
@Override
public List<String> foo(String arg1, String arg2) {
//implementation...
}
}
我们有:
Bar#foo
为d1
List<String>
在d1中将类型返回为R1。Foo#foo
为d2
List<String>
在d2中将类型返回为R2。R1,适用于d2(§8.4.4)的类型参数,是R2的子类型。
这意味着R1
可以是R2
的子类型,这意味着R1应该通过IS-A测试。所以,我们可以做到以下几点:
class Bar implements Foo {
@Override
public ArrayList<String> foo(String arg1, String arg2) {
//implementation...
}
}
可以通过未经检查的转化(§5.1.9)将R1转换为R2的子类型。
这与泛型更相关。这意味着R1
应该通过IS-A测试,即使它发出了未经检查的覆盖警告。所以,我们可以做到以下几点:
class Bar implements Foo {
@Override
public ArrayList foo(String arg1, String arg2) {
//implementation...
}
}
d1与d2(§8.4.2)没有相同的签名,而R1 = | R2 |
这意味着重载:
class Bar implements Foo {
@Override
public ArrayList<String> foo(String arg1, String arg2) {
//implementation...
}
public ArrayList<String> foo(String arg1, String arg2, String arg3) {
//implementation...
}
}
答案 1 :(得分:0)
如果返回类型为R1的方法声明d1覆盖或隐藏了另一个返回类型为R2的方法d2的声明,那么对于d2,d1必须是return-type-substitutable(第8.4.5节),或者是编译时错误出现为d2(§8.4.2),R1 = | R2 |。
让我们分一杯羹:
首先,我们需要一个方法声明d2
和一个返回类型R2
:
class SomeClass {
public List<String> d2() {
return null;
}
}
现在,我们定义一个扩展SomeClass
的类,定义d1
并返回R1
。
class AnotherClass extends SomeClass {
//@Override annotation means it is overriding a method in parent class
//d2 here is d1
//Object here is R1
@Override
public List<String> d2() {
}
}
这怎么编译?因为d1
是d2
的返回类型可替代,这意味着R1
可以将R2
替换为返回类型。这也称为covariant return type,并在Java Tutorials. Returning a Value from a Method中介绍。这是由另一条规则支持的:
返回类型为R1的方法声明d1是另一个方法d2的return-type-substitutable,如果满足以下任何条件,则返回类型为R2:如果R1是引用类型,则以下之一为真:d1不与d2(§8.4.2)具有相同的签名,R1 = | R2 |。
这意味着所有这些方法都有效覆盖SomeClass#d2
:
class AnotherClass extends SomeClass {
//ArrayList implements List
@Override
public ArrayList<String> d2() {
return null;
}
}
class AnotherClass extends SomeClass {
//raw List can be casted to `List<String>` by unchecked conversion
//means you don't need a explicit cast to convert `List` to `List<String>`
//due to type erasure
@Override
public List d2() {
return null;
}
}
class AnotherClass extends SomeClass {
//combination of both examples above
@Override
public ArrayList d2() {
return null;
}
}
但这些都是无效的实现:
class AnotherClass extends SomeClass {
//the signature is not the same
@Override
public List<String> d1() {
return null;
}
}
class AnotherClass extends SomeClass {
//Set is not a subtype of List
@Override
public Set<String> d2() {
return null;
}
}
class AnotherClass extends SomeClass {
//Collection is not a subtype of List
@Override
public Collection<String> d2() {
return null;
}
}