java.util.Arrays.asList(T ...)如何工作?

时间:2021-10-30 19:32:48

It seems to be a silly question at the first sight, but I found that the mechanism isn't trivial. The implementation from JDK 8 (copied from here) is just a few lines:

这看起来似乎是一个愚蠢的问题,但我发现这个机制并非无足轻重。 JDK 8的实现(从这里复制)只是几行:

@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}

The point is that there are only 3 constructors in ArrayList:

关键是ArrayList中只有3个构造函数:

  • one doesn't take any parameter
  • 一个不带任何参数

  • one takes an int (the initial capacity)
  • 一个拿一个int(初始容量)

  • one takes a Collection (the elements) as shown below (copied from here):
  • 一个采取如下所示的集合(元素)(从这里复制):

public class ArrayList<E> extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{

    // ...

    transient Object[] elementData; // non-private to simplify nested class access

    private int size;

    // ...

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);

    }

    // ...

}

Since the only possibility is that the 3rd constructor is called, it seems that the parameter a (the generic vararg) is somehow "casted" to a Collection. But as far as I know, varargs are nothing more than arrays with a shorter syntax, and are not convertible to Collections (so that's why this made me puzzled)...

由于唯一的可能性是调用第3个构造函数,似乎参数a(通用vararg)以某种方式“转换”到Collection。但据我所知,varargs只不过是语法较短的数组,并且不能转换为Collections(这就是为什么这让我感到困惑)...

Does anybody know how the magic works?

有谁知道魔法是如何运作的?

Thank you!

3 个解决方案

#1


12  

You're looking at the wrong ArrayList class. The one used in Arrays.asList(..) is java.util.Arrays.ArrayList and has a constructor that accepts an array.

您正在查看错误的ArrayList类。 Arrays.asList(..)中使用的是java.util.Arrays.ArrayList,并且有一个接受数组的构造函数。

#2


5  

The ArrayList type that's described here is not java.util.ArrayList; it's a private type defined inside that file (see line 3799). That one does have an array constructor, and it's the one referenced by Arrays.asList.

这里描述的ArrayList类型不是java.util.ArrayList;它是在该文件中定义的私有类型(参见第3799行)。那个确实有一个数组构造函数,它是Arrays.asList引用的那个。

Hope this helps!

希望这可以帮助!

#3


4  

Arrays.asList(...) returns a new ArrayList. Here's the tricky part. The new ArrayList is not the one in the java.util package, it is actually a static inner class in Arrays class. Check this code.

Arrays.asList(...)返回一个新的ArrayList。这是棘手的部分。新的ArrayList不是java.util包中的那个,它实际上是Arrays类中的静态内部类。检查此代码。

Arrays.java

public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a);
}
// the static inner class is shown below.
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;

ArrayList(E[] array) {
        if (array==null)
            throw new NullPointerException();
    a = array;
}  

... }

#1


12  

You're looking at the wrong ArrayList class. The one used in Arrays.asList(..) is java.util.Arrays.ArrayList and has a constructor that accepts an array.

您正在查看错误的ArrayList类。 Arrays.asList(..)中使用的是java.util.Arrays.ArrayList,并且有一个接受数组的构造函数。

#2


5  

The ArrayList type that's described here is not java.util.ArrayList; it's a private type defined inside that file (see line 3799). That one does have an array constructor, and it's the one referenced by Arrays.asList.

这里描述的ArrayList类型不是java.util.ArrayList;它是在该文件中定义的私有类型(参见第3799行)。那个确实有一个数组构造函数,它是Arrays.asList引用的那个。

Hope this helps!

希望这可以帮助!

#3


4  

Arrays.asList(...) returns a new ArrayList. Here's the tricky part. The new ArrayList is not the one in the java.util package, it is actually a static inner class in Arrays class. Check this code.

Arrays.asList(...)返回一个新的ArrayList。这是棘手的部分。新的ArrayList不是java.util包中的那个,它实际上是Arrays类中的静态内部类。检查此代码。

Arrays.java

public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a);
}
// the static inner class is shown below.
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;

ArrayList(E[] array) {
        if (array==null)
            throw new NullPointerException();
    a = array;
}  

... }