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

一、背景

有些同学提出“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。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明明如月学长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值