Java jls。返回类型可替换。这是什么意思?

Java jls。返回类型可替换。这是什么意思?,java,inheritance,methods,return,jls,Java,Inheritance,Methods,Return,Jls,我正在阅读jls,我面临以下术语: return-type-substitutable 来自jls的代码片段 返回类型为R1的方法声明d1为 返回类型可替换为另一个返回类型为R2的方法d2 如果以下任何一项为真: 如果R1无效,则R2无效 如果R1是基元类型,则R2与R1相同 如果R1是引用类型,则以下情况之一为真: --R1适用于d2的类型参数(§8.4.4),是 R2 --R1可以通过未选中的转换转换为R2的子类型 (§5.1.9) --d1与d2没有相同的签名(§8.4.2),R1=|

我正在阅读jls,我面临以下术语:

return-type-substitutable
来自jls的代码片段

返回类型为R1的方法声明d1为 返回类型可替换为另一个返回类型为R2的方法d2 如果以下任何一项为真:

如果R1无效,则R2无效

如果R1是基元类型,则R2与R1相同

如果R1是引用类型,则以下情况之一为真:

--R1适用于d2的类型参数(§8.4.4),是 R2

--R1可以通过未选中的转换转换为R2的子类型 (§5.1.9)

--d1与d2没有相同的签名(§8.4.2),R1=| R2 |

前两点显然是正确的

你能澄清一下吗

--R1适用于d2的类型参数(§8.4.4),是R2的一个子类型

--R1可以通过未经检查的转换(§5.1.9)转换为R2的子类型

--d1与d2没有相同的签名(§8.4.2),R1=| R2 |

谢谢

附言。 为路易吉·门多萨

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;
    }
}
代码:

接口Foo{
列表foo(字符串arg1、字符串arg2);
}
类栏实现了Foo{
@凌驾
公共列表另一个名称(字符串arg1、字符串arg2、对象obj){
返回null;
}
这是编译错误

R1==R2(
List==List

d1!=d2


我在哪里违反了规则?

让我们使用这个界面

interface Foo {
    List<String> foo(String arg1, String arg2);
}
R1可以通过未选中的转换()转换为R2的子类型

这与泛型更为相关。这意味着
R1
应该通过is-A测试,即使它抛出未检查覆盖的警告。因此,我们可以执行以下操作:

class Bar implements Foo {
    @Override
    public ArrayList<String> foo(String arg1, String arg2) {
        //implementation...
    }
}
class Bar implements Foo {
    @Override
    public ArrayList foo(String arg1, String arg2) {
        //implementation...
    }
}
d1与d2()没有相同的签名,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...
    }
}
类栏实现了Foo{
@凌驾
公共ArrayList foo(字符串arg1、字符串arg2){
//实施。。。
}
公共ArrayList foo(字符串arg1、字符串arg2、字符串arg3){
//实施。。。
}
}
如果返回类型为R1的方法声明d1重写或隐藏另一个返回类型为R2的方法d2的声明,则d1必须是d2的可替换返回类型(§8.4.5),否则会出现编译时错误d2(§8.4.2),R1=| R2 |

让我们把它分成几部分:

首先,我们需要一个方法声明
d2
和一个返回类型
R2

class SomeClass {
    public List<String> d2() {
        return null;
    }
}
这是如何编译的?因为
d1
是可替换为
d2
的返回类型,这意味着
R1
可以替换
R2
作为返回类型。这也被称为返回类型,并在中介绍。这由另一个规则支持:

如果以下任何一项为真,则返回类型为R1的方法声明d1为返回类型,可替换为返回类型为R2的另一方法d2:如果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另一个类扩展了SomeClass{
//ArrayList实现列表
@凌驾
公共阵列列表d2(){
返回null;
}
}
另一个类扩展了SomeClass{
//原始列表可以通过未选中的转换转换转换为'List'
//意味着您不需要显式强制转换来将'List'转换为'List'`
//由于类型擦除
@凌驾
公开名单d2(){
返回null;
}
}
另一个类扩展了SomeClass{
//上面两个例子的组合
@凌驾
公共阵列列表d2(){
返回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;
    }
}
class另一个类扩展了SomeClass{
//签名不一样
@凌驾
公开名单d1(){
返回null;
}
}
另一个类扩展了SomeClass{
//集合不是列表的子类型
@凌驾
公共集d2(){
返回null;
}
}
另一个类扩展了SomeClass{
//集合不是列表的子类型
@凌驾
公开募捐d2(){
返回null;
}
}

d1没有与d2相同的签名,这对于jls来说不够精确-我可以完全写出任何签名。这意味着什么**R1=|R2 |**@gstackoverflow这意味着你可以为不同的签名返回相同的类型,这是另一种说法重载。重载-这是指方法名称相同但di的情况不同的参数列表。它与返回类型无关。tge R2周围的大括号如何?@gstackoverflow它指的是类类型。从上次编辑开始,没有要重写的
另一个名称
方法,因此会出现编译器错误。此外,您说
Bar
实现了
Foo
,但没有
公共列表Foo(字符串arg1,字符串arg2)
Bar类中的
方法(或另一种方法,其签名
foo(字符串arg1,字符串arg2)
返回
列表
列表
的子类型).@Luiggi Mendoza我根据我对这条规则的理解编写了规则并编写了代码示例。你能指定我违反规则的地方吗?我已经在我的评论中指出了这些地方。@Luiggi Mendoza你的评论很常见。我接受了。但你的java是可以理解的。想象一下,你是java新手,并尝试遵守规则。Please以以下格式添加到您的问题更新中:引用我的代码中的规则-违反。我说的是2条规则:1.如果返回类型为R1的方法声明d1覆盖或隐藏另一个返回类型为R2的方法d2的声明,则d1必须是d2的返回类型可替换(§8.4.5),否则会出现编译时错误d2(§8.4.2),R1=| R2 |以下短语的问题:d1的签名与d2@gstackoverflow你知道签名是什么吗?它是方法名和参数list@gstackoverflow好的,然后在最后一段代码中,
d1
d2<
class SomeClass {
    public List<String> d2() {
        return null;
    }
}
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() {
    }
}
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;
    }
}