2016-07-05 124 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。 –