簡體   English   中英

JLS。 返回式可替代性。 這是什么意思?

[英]jls. return-type-substitutable. What does it mean?

我正在閱讀jls,但遇到了以下術語:

return-type-substitutable

來自jls的片段

如果滿足以下任何條件,則返回類型為R1的方法聲明d1可替換為返回類型為R2的另一個方法d2:

如果R1為空,則R2為空。

如果R1是原始類型,則R2與R1相同。

如果R1是引用類型,則下列條件之一為真:

--R1是R2的子類型,適用於d2(第8.4.4節)的類型參數。

--R1可以通過未經檢查的轉換(第5.1.9節)轉換為R2的子類型。

--d1與d2(第8.4.2節)的簽名不同,並且R1 = | R2 |。

前兩點很明顯。

你能澄清一下嗎

--R1是R2的子類型,適用於d2(第8.4.4節)的類型參數。

--R1可以通過未經檢查的轉換(第5.1.9節)轉換為R2的子類型。

--d1與d2(第8.4.2節)的簽名不同,並且R1 = | R2 |。

謝謝

Luiggi Mendoza的PS

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理解以下短語:

如果具有返回類型R1的方法聲明d1覆蓋或隱藏了具有返回類型R2的另一個方法d2的聲明,則d1必須是d2的返回類型可替換的(第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

我在哪里違反規則?

讓我們有這個界面

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 as d2
  • List<String>返回d2中的R2類型。

適應d2類型參數(第8.4.4節 )的R1是R2的子類型。

這意味着R1可以是R2的子類型,這意味着R1應該通過IS-A測試。 因此,我們可以執行以下操作:

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

可以通過未經檢查的轉換將R1轉換為R2的子類型(第5.1.9節 )。

這與泛型更相關。 這意味着即使R1引發未檢查的覆蓋警告, 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...
    }
}

如果具有返回類型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;
    }
}

現在,我們定義一個擴展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作為返回類型。 這也稱為協變返回類型 ,在Java教程中有介紹。 從方法返回值 另一條規則支持:

如果滿足以下任一條件,則返回類型為R1的方法聲明d1可替換為具有返回類型R2的另一個方法d2:如果R1為引用類型,則以下條件之一為true: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;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM