平原网站建设电话,智博常州网站建设,长春一般建一个网站需要多少钱,做土司的网站数组与泛型有很大的不同#xff1a;
1. 数组是协变的#xff08;covariant#xff09; 意思是#xff1a;如果Sub是Super的子类型#xff0c;则数组类型Sub[] 是数组类型Super[] 的子类型。
2. 泛型是不变的#xff08;invariant#xff09; 对于任何两种不同的类型Ty…数组与泛型有很大的不同
1. 数组是协变的covariant 意思是如果Sub是Super的子类型则数组类型Sub[] 是数组类型Super[] 的子类型。
2. 泛型是不变的invariant 对于任何两种不同的类型Type1 和Type2ListType1 既不是ListType2 的子类型也不是父类型。
现在有两段代码
Object[] objectArray new Long[1];
objectArray[0] I dont fit in;
ListObject ol new ArrayListLong(); // Incompatible types
ol.add(I dont fit in);
无论哪种方式都会报错因为不能把一个String 类型放到一个Long 类型容器中但是用一个数组的话在运行时才会报错对于列表可以在编译时就能发现错误。所以使用列表就有优势因为运行时报错的代价太高
3. 数组是具体化的在运行时才知道和强化他们的类型
就比如上面的代码将String保存到Long数组中就会得到ArrayStoreException异常
4. 泛型在编译时就强化它的类型信息并在运行时擦除它的元素类型信息
由于上面这些区别数组和泛型不能很好地混用所以new ListE[]new ListStringnew E[]这些语法都是错误的在编译时会产生一个泛型数组创建错误。
非法的原因是它不安全以下面这段代码为例
ListString[] stringLists new ListString[1]; // (1)
ListInteger intList List.of(42); // (2)
Object[] objects stringLists; // (3)
objects[0] intList; // (4)
String s stringLists[0].get(0); // (5)
假设第1行创建一个泛型数组是合法的第2行创建并初始化包含单个元素的ListInteger第3行将ListString 数组存储到Object数组变量中这是合法的因为数组是协变的第4行将ListInteger 存储在Object数组的唯一元素中这是因为泛型是通过擦除来实现的ListString[] 实例是List[]所以这个赋值不会产生ArrayStoreException 异常
现在问题就来了我们将一个ListInteger 实例存储到一个声明为ListString 实例的数组中为了防止这种情况出现第一行必须报错。
EListE 和ListString 等在技术上被称为不可具体化的类型指其运行时表示法包含的信息比它的编译时表示法包含的信息更少。唯一可具体化的参数化类型是无限制的通配符类型如List?等创建无限制通配符类型的数组是合法的但并不常用。 当泛型数组创建错误时最佳解决方案是使用集合类型ListE 。例如编写一个带有集合的Chooser类和一个方法方法返回集合中随机选择的一个元素。
public class Chooser {private final Object[] choiceArray;public Chooser(Collection choices) {choiceArray choices.toArray();}public Object choose() {Random rnd ThreadLocalRandom.current();return choiceArray[rnd.nextInt(choiceArray.length)];}public static void main(String[] args) {ListString list new ArrayList();list.add(1);list.add(2);list.add(3);Chooser chooser new Chooser(list);Object choose chooser.choose();System.out.println(choose);}
}
如果想将choose方法的返回值从Object转换成每次调用该方法时想要的类型
public class ChooserT {private final T[] choiceArray;public Chooser(CollectionT choices) {choiceArray choices.toArray();}// choose 方法不变
} 上面的类会报错 如果加一条强制类型转换的话
choiceArray (T[]) choices.toArray();
仍有报警信息 要消除上面的警告需要用列表代替数组
public class ChooserT {private final ListT choiceList;public Chooser(CollectionT choices) {choiceList new ArrayList(choices);}public T choose() {Random rnd ThreadLocalRandom.current();return choiceList.get(rnd.nextInt(choiceList.size()));}
}
总结一下数组和泛型有着截然不同的类型规则1. 数组是协变且可以具体化的2. 泛型是不可变的且可以被擦除的