我想我错过了一些基本的东西。对先前提出的问题的任何解释或指示将非常有用。
import java.util.Arrays;
import java.util.List;
public class St {
public static void bla(Object[] gaga) {
gaga[0] = new Date(); // throws ArrayStoreException
System.out.println(gaga[0]);
}
public static void bla(List<Object> gaga) {
System.out.println(gaga.get(0));
}
public static void main(String[] args) {
String[] nana = { "bla" };
bla(nana); // Works fine
List<String> bla1 = Arrays.asList(args);
bla(bla1); // Wont compile
System.out.println(new String[0] instanceof Object[]); // prints true
System.out.println(nana.getClass().getSuperclass().getSimpleName()); // prints Object
}
}
因此,似乎List<String>
不是List<Object>
的子类,而String[]
是Object[]
的子类。
这是一个有效的假设吗?如果是这样,为什么?如果没有,为什么?
由于
答案 0 :(得分:10)
Java arrays are covariant,即他们允许Object[] foo = new String[2];
。但这并不意味着它们是子类。 String[]
是Object
的子类(虽然instanceof
返回true,String[].class.getSuperclass()
返回Object
)
答案 1 :(得分:5)
是的,您的假设是有效的。正如@Bozho所说,数组是协变的,而泛型集合(如泛型List)则不是协变的。
数组中的协方差存在风险:
String[] strings = new String[] { "a", "b" }
Object[] objects = strings;
objects[0] = new Date(); // <-- Runtime error here
String s = strings[0];
s.substring(5, 3); // ????!! s is not a String
第三行触发运行时异常。如果它没有触发此异常,那么您可以获得String
变量s
,该变量引用的值不是String
(也不是其子类型):a {{1 }}
答案 2 :(得分:3)
(new String[0] instanceof Object[]) // => true
答案 3 :(得分:3)
你是对的。数组类型在Java中是协变的,但是Foo<Sub>
不是Foo<Super>
。
答案 4 :(得分:2)
String []是Object []
的子类
正确,请参阅4.10.3 Subtyping among Array Types:
如果S和T都是参考类型,则S []> 1 T [] iff S> 1 T。
自String >1 Object
以来String[] >1 Object[]
也就是说,String[]
是Object[]
的直接子类型
对象&gt; 1对象[]
因此Object > String[]
; String[]
是({1}}
泛型不存在这种关系,因此Object
不正确。
现在,请考虑以下简单示例:
List<String> > List<Object>
它无法编译,因为import java.util.*;
class G {
interface I {
void f();
}
class C implements I {
public void f() {}
}
void allF(List<I> li) {
for (I i : li) { i.f(); }
}
void x(List<C> lc) {
allF(lc);
}
}
正在使用x
来调用allF
<{1>} <{1}}。为了能够使用List<C>
,签名必须略有改变:
List<I>
现在它编译。非正式地,List<C>
是某种类型的void allF(List<? extends I> li) {
,可以扩展/实现I.因此li
可分配给 {{1} }。你可以用这样的清单做什么是有限的。基本上,您可以读取/访问它但不能List
它。