且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

ArrayList的toArray()方法为啥不利用泛型返回List的泛型类型的数组探究

更新时间:2022-05-28 23:22:03

一、背景

有些同学提出“ArrayList的public <T> T[] toArray(T[] a) 带参数的方法支持泛型可以返回参数类型的数组,public Object[] toArray()


方法为啥不利用泛型返回List的泛型类型的数组”?这个问题。


那让我们看下源码研究一下吧。另外我将介绍一下通用解决这类问题的方法,方便大家举一反三。



二、研究

无参源码java.util.ArrayList#toArray()


  public Object[] toArray() {

       return Arrays.copyOf(elementData, size);

   }

底层函数java.util.Arrays#copyOf(T[], int)


   @SuppressWarnings("unchecked")

   public static <T> T[] copyOf(T[] original, int newLength) {

       return (T[]) copyOf(original, newLength, original.getClass());

   }

的确这里支持泛型。


但是我们看一下ArrayList真正存储对象的变量: transient Object[] elementData; 它的类型为Object数组。


因此从源码来看,返回值必然是Object数组了。



为啥不给转成E[] 这样呢?


一方面ArrayList真正存储对象的变量: transient Object[] elementData;


另外一方面创建ArrayList的时候,并不一定指定泛型类型的。


因此java.util.ArrayList#toArray()怎么搞?


 @Test

   public void test2() {

       ArrayList arrayList = new ArrayList();

       int random = RandomUtils.nextInt(3, MAX_LENGTH);

       log.debug("随机数-->{}", random);

       for (int i = 0; i < random; i++) {

           arrayList.add(i);

       }

       arrayList.add("String");

       Object[] objects = arrayList.toArray();

       log.debug("结果:{}", JSON.toJSONString(objects));

   }

总不能判断有泛型返回E[] 无泛型返回Object[]吧?


如果一个接口可能返回String,也可能返回Integer,那么返回值类型是不是应该定义为Object?


那么这个问题应该就明了。


三、类似的问题

正如前面说的:


(1)如果一个接口可能返回String,也可能返回Integer,那么返回值类型是不是应该定义为Object?


(2)这点又让我想到了fastjson的json反序列化时调用泛型的函数来转成对象。


com.alibaba.fastjson.JSON#parseObject(java.lang.String)


public static JSONObject parseObject(String text) {

       Object obj = parse(text);

       if (obj instanceof JSONObject) {

           return (JSONObject)obj;

       } else {

           try {

               return (JSONObject)toJSON(obj);

           } catch (RuntimeException var3) {

               throw new JSONException("can not cast to JSONObject.", var3);

           }

       }

   }

然后带类型的com.alibaba.fastjson.JSON#parseObject(java.lang.String, java.lang.Class<T>)


public static <T> T parseObject(String text, Class<T> clazz) {

       return parseObject(text, clazz);

   }

使用时:




一个是无类型参数,一个是有类型参数,有些类似。



四、怎么解决这类问题?

像这种问题还有很多很多,其实最关键的是勇于去扒源码,并结合其注释,再不行去找官方文档。


这三点可以解决绝大多数这类问题。


另外学习的时候多找共性,多类比学习,学的更快一些。


另外学习某个知识点***自己本地多demo,这点可以参考《几个本地搭建练习项目来学习的小技巧分享》。



创作不易,如果觉得本文对你有帮助,欢迎点赞,欢迎关注我,如果有补充欢迎评论交流,我将努力创作更多更好的文章。


另外欢迎加入我的知识星球,知识星球ID:15165241 一起交流学习。


https://t.zsxq.com/Z3bAiea  申请时标注来自CSDN。


 

————————————————

版权声明:本文为CSDN博主「明明如月学长」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/w605283073/article/details/92251503