2012-04-13 75 views
6

以下代碼使用Java中方法重寫的概念。Java中的協變返回類型

package pkg; 

import java.util.ArrayList; 
import java.util.List; 

abstract class SuperClass 
{ 
    abstract public List<String>getList(); 
} 

final class SubClass extends SuperClass 
{ 
    private List<String>list=null; 

    @Override 
    public ArrayList<String> getList() 
    { 
     list=new ArrayList<String>(); 
     list.add("A"); 
     list.add("B"); 
     return (ArrayList<String>) list; 
    } 
} 

final public class Main 
{ 
    public static void main(String[] args) 
    { 
     SuperClass s=new SubClass(); 
     List<String>list=s.getList(); 

     for(String str:list) 
     { 
      System.out.println(str); 
     } 
    } 
} 

按照慣例,方法重寫在超類和子類中都使用相同的簽名(帶返回類型)。在上面的代碼中,SuperClass中的getList()方法的返回類型爲List,在其子類中返回類型爲ArrayList。方法覆蓋如何在這裏工作?

順便說,很明顯,ArrayListList接口的實現,但是編譯器如何對待這裏的返回類型,而重寫getList()方法?

我應該相信像這樣的... 重寫的方法的返回類型允許爲重寫的方法的返回類型的子類型。

+0

似乎沒有很好的理由宣佈'SubClass.list'作爲'List'(而不是'ArrayList')。 – 2012-04-13 02:48:16

+0

@ MichaelBrewer-Davis - 當你直接使用'SubClass'而不是像SuperClass'那樣處理它時,它可以使事情變得更好。 – 2012-04-13 03:09:19

+0

@Brendan - 我在談論(私有)成員變量過於籠統,而不是方法過於具體。方法中的協變是陽光和蝴蝶。 – 2012-04-13 15:13:39

回答

19

是的。

在早期的java中並非如此,但它在Java 5.0中發生了變化。

在同一個類中,不能有兩個方法的簽名只有返回類型不同。直到J2SE 5.0發佈之前,類也不能覆蓋它從超類繼承的方法的返回類型。在這篇技巧中,您將學習J2SE 5.0中的一個新特性,它允許協變返回類型。這意味着子類中的方法可能會返回一個對象,該對象的類型是該方法返回的類型的子類,並且超類中具有相同的簽名。該功能消除了對過多類型檢查和投射的需求。

此信息的來源不再可用於interwebs。

+0

鏈接已死。 – Ghos3t 2017-07-05 15:22:32

3

是的,這是正確的。由於ArrayList是一個List,所以當原始方法返回一個List時,你可以返回一個ArrayList。

4

在面向對象編程中,方法的協變返回類型是當在子類中重寫方法時可以用「窄」類型替換的方法。這是一個相當常見的範例,值得注意的語言是C++。 協變返回類型已經(部分地)允許在自JDK5.0釋放Java語言,所以下面的例子中不會對先前版本編譯:

// Classes used as return types: 

class A { 
} 

class B extends A { 
} 

// "Class B is more narrow than class A" 
// Classes demonstrating method overriding: 

class C { 
    A getFoo() { 
     return new A(); 
    } 
} 

class D extends C { 
    B getFoo() { 
     return new B(); 
    } 
} 

更具體地,協變(寬較窄)或逆變(從窄到寬)返回類型是指重寫方法的返回類型更改爲與原始重寫方法的返回類型相關(但不同於)的類型的情況。

兩個協變返回類型之間的關係通常是允許一個類型與另一個類型的替換,遵循Liskov替換原則。

這通常意味着重寫方法的返回類型將是重寫方法的返回類型的子類型。上面的例子具體說明了這種情況。如果不允許替換,返回類型是不變的,並導致編譯錯誤。

參考:https://en.wikipedia.org/wiki/Covariant_return_type

+0

https://en.wikipedia.org/wiki/Covariant_return_type – 2014-06-24 20:46:46