2016-07-05 159 views
8

我遇到過一些我在Java中發現奇怪的東西,並且無法找到關於它的很多信息。請看下面的代碼:泛型和抽象方法

public class TestClass { 

    private static abstract class AbstractClass { 
     abstract List<? extends Object> getList(); 
     abstract Map<Long, List<? extends Object>> getMap(); 
    } 

    private static final class ConcreteClass extends AbstractClass { 
     @Override 
     List<String> getList() { 
      return null; 
     } 

     @Override 
     Map<Long, List<String>> getMap() { 
      return null; 
     } 
    } 
} 

編譯器顯示了getMap()方法的錯誤:

getMap() in ConcreteClass cannot override getMap() in AbstractClass 
    return type Map<Long, List<String>> is not compatible with Map<Long, List<? extends Object>> 

但同樣的錯誤是不存在的getList()方法,但我希望兩個都上班或兩者都失敗。在這兩種情況下,首要的方法是刪除List<String>以代替List<? extends Object>。有人可以解釋這個嗎?

回答

10

這是因爲存在從List<String>List<? extends Object>而不是從Map<Long, List<String>>Map<Long, List<? extends Object>>的隱式轉換。

除非使用通配符類型,否則所有泛型類型都是不變的。由於「外部」Map類型的泛型類型參數中沒有通配符,因此無法捕獲任何不匹配的泛型類型。

如果您的地圖類型爲Map<Long, ? extends List<? extends Object>>那麼它會像您期望的那樣工作。

而另一部分如果答案是子類可以重寫或實現具有不同返回類型的超類型方法,但只有當子類型的方法的返回類型可隱式轉換爲超類型方法的返回類型。 (在Java 1.4及更低版本中,即使這樣也行不通:如果類型不完全匹配,將會導致編譯時錯誤。)

+0

很好的答案,謝謝! (我會接受時間限制後) – lucasvw

+3

的好處,我想補充'?擴展Object'可以被替換爲'?'而沒有任何影響 – Andrew

+2

@Andrew:當然,但是相同的原則適用於通配符上的任何下界,而不僅僅是Object。 –