我对Java泛型如何处理继承/多态性感到困惑.
假设以下层次结构 -
动物(父母)
狗 - 猫(儿童)
所以假设我有一个方法doSomething(List<Animal> animals)
.根据所有继承和多态的规则,我会假设a List<Dog>
是 a List<Animal>
而a List<Cat>
是 a List<Animal>
- 所以任何一个都可以传递给这个方法.不是这样.如果我想实现这种行为,我必须明确告诉该方法接受一个Animal的任何子类的列表doSomething(List<? extends Animal> animals)
.
我知道这是Java的行为.我的问题是为什么?为什么多态通常是隐含的,但是当涉及泛型时必须指定它?
来自Joshua Bloch的Effective Java,
协变只是意味着如果X是Y的子类型,那么X []也将是Y []的子类型.数组是协变的因为字符串是Object So的子类型
String[] is subtype of Object[]
不变量仅仅意味着X不是Y的子类型,
List<X> will not be subType of List<Y>.
Run Code Online (Sandbox Code Playgroud)我的问题是为什么决定在Java中使数组协变?还有其他SO帖子,例如为什么阵列不变,但列出协变?,但他们似乎专注于Scala,我无法遵循.
我认为标题应该解释一下,但以防万一......
我想知道以下Java代码片段可能产生与转换相关的风险和潜在问题:
List<? extends MyObject> wildcardList = someAPI.getList();
List<MyObject> typedList = (List<MyObject>) wildcardList;
Run Code Online (Sandbox Code Playgroud)
我的想法是wildcardList中的所有对象都应该是MyObject的实例(确切的类型或子类),因此每当从typedList检索对象时,就不应该有ClassCastException.它是否正确?如果是这样,为什么编译器会生成警告?
以下陈述:
URLClassLoader ucl = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class<URLClassLoader> uclc = ucl.getClass();
Run Code Online (Sandbox Code Playgroud)
失败并出错:
Type mismatch: cannot convert from Class<capture#2-of ? extends URLClassLoader> to Class<URLClassLoader>
Run Code Online (Sandbox Code Playgroud)
我为什么需要演员?
我发现了几个帖子解释了为什么你不能反过来(将T分配给a),但那种(有点)是显而易见的.
注意:我在eclipse Luna下编码,所以我不知道它是否是Luna Quirk,或者是否有一些我在仿制药中真的不理解的东西.