标签:int ring class 构造函数 origin 总结 类型 row pointer
在看ArrayList源码时,发现了这样一行代码
c.toArray might (incorrectly) not return Object[] (see 6260652)
意思是c.toArray()不一定会返回 Object[] ,请查看编号为6260652的Java Bug
这里附上Java Bug 网址: Java Bug Database,可以根据关键词或bug id 查询详细信息
看一组实例吧...
package com.kristin.java; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * @author hang li * @since 2018/4/20 */ public class DailyTest { public static void test1() { System.out.println("this is test1..."); List<String> list = new ArrayList<>(); list.add("aa"); list.add("bb"); Object[] arr = list.toArray(); System.out.println(arr.getClass().getCanonicalName()); arr[0] = new Object(); DailyTest.printArr(arr); } public static void test2() { System.out.println("this is test2..."); List<String> list = Arrays.asList("aa", "bb"); Object[] arr = list.toArray(); System.out.println(arr.getClass().getCanonicalName()); arr[0] = new Object(); DailyTest.printArr(arr); } public static void test3() { System.out.println("this is test3..."); Object[] arr = new String[]{"aa", "bb"}; arr[0] = 1; DailyTest.printArr(arr); } public static void printArr(Object[] arr) { for (Object o : arr) { System.out.print(o + " "); } System.out.println(); } public static void main(String[] args) { /* 分别依次调用以下三个函数*/ /* * test1 Output: * this is test1... * java.lang.Object[] * java.lang.Object@2503dbd3 bb */ DailyTest.test1(); /* * test2 Output: * this is test2... * java.lang.String[] * Exception in thread "main" java.lang.ArrayStoreException: java.lang.Object */ DailyTest.test2(); /* * test3 Output: * this is test3... * Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer */ DailyTest.test3(); } }
test1(),test2()都是调用toArray(),为什么一个更改arr[0]没问题,另一个报错呢?
首先看ArrayList.java中toArray()源码:由于ArrayList中elementData类型为Object[],所以调用copyOf()返回值类型为Object[]
public Object[] toArray() { return Arrays.copyOf(elementData, size); } public static <T> T[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); }
再看一下Arrays.asList()源码及相关代码: asList()将String[]作为参数传入,然后调用了ArrayList的代参构造函数,此时a的真实类型依然是String[],然后调用clone(),a的类型依然是String[],所以最终调用了toArray()后,返回的是String[],这也就是为什么再讲数组第一个赋为new Object()时,因为类型不同所以不能进行转换,这与test3()的例子相似
public static <T> List<T> asList(T... a) { return new ArrayList<>(a); } ArrayList(E[] array) { a = Objects.requireNonNull(array); } public static <T> T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); return obj; } public Object[] toArray() { return a.clone(); }
总结:
由于Arrays.asList()返回的不一定是Object[],所以会出现向数组中添加Object对象报异常的问题,问题是在2005年提出的,现在已经解决了,所以尽量使用toArray(T[] a)避免Exception的发生
public <T> T[] toArray(T[] a) { if (a.length < size) // Make a new array of a‘s runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; }
Bug详情可以参考: OpenJDK
本文参考:
https://www.cnblogs.com/zhizhizhiyuan/p/3662371.html
https://www.zhihu.com/question/66518325/answer/243761796
标签:int ring class 构造函数 origin 总结 类型 row pointer
原文地址:https://www.cnblogs.com/Hangtutu/p/9066967.html