假设我有类Foo扩展超类。我理解为什么我不能这样做:
List<Foo> fooList = getFooList();
List<Superclass> supList = fooList;
但是,如果supList以某种方式“只读”,那对我来说似乎是合理的。然后,一切都会保持一致,因为objList中出现的所有东西都是Foo,这是一个超类。
我可能会编写一个List实现,它将获取一个基础列表和一个更通用的类型参数,然后将所有内容作为更一般的类型而不是特定类型返回。它会像Collections.unmodifiableList()
的返回一样工作,除了类型会更加通用。
有更简单的方法吗?
我正在考虑这样做的原因是我正在实现一个接口,要求我返回一个(不可修改的)List&lt; Superclass&gt;,但在内部我需要使用Foos,所以我有一个List&lt; Foo&gt;。我不能只是演员。
答案 0 :(得分:5)
扩展Kylar的回答:
如果修改了接口以返回List<? extends Superclass>
,则返回的列表仍然是有效的只读(您可以通过强制转换来解决它,但编译器会发出警告)。并且您可以返回List
的任何子类Superclass
并仍然满足该接口。
实际代码:
public interface MyInterface {
List<? extends Superclass> getList();
}
public class Superclass {}
public class Subclass {}
public class MyClass implements MyInterface {
public List<? extends Superclass> getList() {
return new ArrayList<SubClass>();
}
}
现在,我怎么知道它应该是? extends Superclass
?我记得Josh Bloch's mnemonic:
PECS:制片人扩展,消费者超级。
因此,如果您返回的列表是制作者(即您正在从中删除但未放入内容),则使用? extends
来概括它。
相反,如果它是使用者(即您正在添加内容而不是将其删除),您可以使用? super
对其进行概括。
如果您将其用作生产者和消费者,遗憾的是您无法概括它。
答案 1 :(得分:2)
List<? extends Superclass>
可以使用。然后,您可以返回扩展超类的任何项的列表,如下所示:
public class MoreGeneric {
public static void main(String[] args) {
List<? extends MyClass> someList;
someList = new ArrayList<MyClass2>();
}
abstract public static class MyClass{
abstract void doSomething();
}
public static class MyClass2 extends MyClass{
public void doSomething(){
}
}
}
答案 2 :(得分:1)
我将您推荐给this维基百科文章以供进一步阅读。
简而言之:在Java中,类型参数是不变的(既不是共同变体也不是变体)。你对不变性的观察是正确的,顺便说一下。 wiki article link
P.S .: 如果您对使用在JVM上运行的更灵活类型系统的语言感兴趣,您可能需要查看Scala。
答案 3 :(得分:0)
你可以这样做,只是施展
List<Superclass> supList = (List) fooList;
当你这样做时要小心,因为如果Foo不是Superclass的子类,那么你将得到一个运行时转换异常