Java jls。返回类型可替换。这是什么意思?
我正在阅读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=|
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;
}
}