SuperScenePack3





一、背景

有些同学提出“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 一起交流学习。

评论