有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java jls。可替换的。这是什么意思?

我正在阅读jls,我面临着以下问题:

return-type-substitutable

来自jls的片段

A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return type R2 iff any of the following is true:

If R1 is void then R2 is void.

If R1 is a primitive type then R2 is identical to R1.

If R1 is a reference type then one of the following is true:

--R1, adapted to the type parameters of d2 (§8.4.4), is a subtype of R2.

--R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9).

--d1 does not have the same signature as d2 (§8.4.2), and R1 = |R2|.

前两点显然是正确的

你能澄清一下吗

--R1, adapted to the type parameters of d2 (§8.4.4), is a subtype of R2.

--R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9).

--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 ArrayList<String> foo(String arg1, String arg2) {
        //implementation...
        return  null;
    }

    public String foo(String arg1, String arg2, String arg3) {
        //implementation...
        return  null;
    }
}

它正在工作

我的问题的原因是——我想了解jls的以下短语:

If a method declaration d1 with return type R1 overrides or hides the declaration of another method d2 with return type R2, then d1 must be return-type-substitutable (§8.4.5) for d2, or a compile-time error occurs

规则:

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

我在哪里违反了规定


共 (2) 个答案

  1. # 1 楼答案

    让我们有这个界面

    interface Foo {
        List<String> foo(String arg1, String arg2);
    }
    

    还有一个实现它的类

    class Bar implements Foo {
        @Override
        public List<String> foo(String arg1, String arg2) {
            //implementation...
        }
    }
    

    我们有:

    • Bar#fooasd1
    • List<String>将d1中的返回类型设置为R1
    • Foo#fooasd2
    • List<String>将d2中的类型返回为R2

    R1, adapted to the type parameters of d2 (§8.4.4), is a subtype of R2.

    这意味着R1可以是R2的一个亚型,这意味着R1应该通过IS-a测试。因此,我们可以做到以下几点:

    class Bar implements Foo {
        @Override
        public ArrayList<String> foo(String arg1, String arg2) {
            //implementation...
        }
    }
    

    R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9).

    这与泛型更相关。这意味着R1应该通过IS-A测试,即使它抛出了未检查覆盖的警告。因此,我们可以做到以下几点:

    class Bar implements Foo {
        @Override
        public ArrayList foo(String arg1, String arg2) {
            //implementation...
        }
    }
    

    d1 does not have the same signature as d2 (§8.4.2), and 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...
        }
    }
    
  2. # 2 楼答案

    If a method declaration d1 with return type R1 overrides or hides the declaration of another method d2 with return type R2, then d1 must be return-type-substitutable (§8.4.5) for d2, or a compile-time error occurs as d2 (§8.4.2), and 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中介绍。这得到了另一条规则的支持:

    A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return type R2 if any of the following is true: 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|.

    这意味着所有这些方法都适用于覆盖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;
        }
    }