【问题标题】:Arrays.asList() doubt?Arrays.asList() 有疑问吗?
【发布时间】:2011-01-25 10:09:10
【问题描述】:

人们说asList 方法将数组转换为列表而不是复制,因此'aList' 中的每个更改都会反映到'a' 中。所以在 'aList' 中添加新值是非法的,因为数组的大小是固定的。

但是,asList() 方法返回 ArrayList<T>。编译器如何区分第 3 行和第 5 行。第 3 行给了我异常 (UnsupportedOperationException)。

        String[] a = {"a","b","c","d"};//1
        List<String> aList =  Arrays.asList(a);//2
        aList.add("e");//3
        List<String> b = new ArrayList<String>();//4
        b.add("a");//5

【问题讨论】:

  • “人们说什么”并不重要。 Javadoc 说什么很重要。

标签: java collections


【解决方案1】:

你从Arrays.asList 收到的这个 List 实现是数组的一个特殊视图——你不能改变它的大小。

Arrays.asList() 的返回类型是java.util.Arrays.ArrayList,经常与java.util.ArrayList 混淆。 Arrays.ArrayList 只是将数组显示为列表

【讨论】:

  • +1 我认为这基本上是问题的症结所在。 OP 看到返回类型是 ArrayList,并且想知道为什么它的行为与 ArrayList 不同。完全有效的问题。
  • Andreas_D,Arrays.asList(...) 的返回类型是java.util.List 而不是java.util.Arrays.ArrayList
【解决方案2】:

Read again,Arrays.asList的类型是:

public static <T> List<T> asList(T... a)

其中明确指出 asList 返回一个实现 interface java.util.List 的对象,但没有说它将返回一个 class java.util.ArrayList 的实例.

接下来,请注意List.add 上的文档说:

布尔加法(E e)

     将指定元素附加到此列表的末尾(可选操作)

从技术上讲,每次您使用类型为 List(而不是 ArrayList)的变量时,您都应始终小心,该方法可能会抛出 UnsupportedOperationException。如果您确定只会收到始终具有正确语义 .add() 的 List 实现,那么当您的假设无效时,您可以省略检查,但可能会出现错误。

【讨论】:

    【解决方案3】:

    马诺杰,

    Arrays.List 的返回类型是 List 接口的一些未知的内部实现,不是 java.util.ArrayList,因此您只能将其分配给 List 类型。

    如果你将它分配给一个 ArrayList 例如它会给你编译时错误 “类型不匹配:无法从 List 转换为 ArrayList”

      ArrayList<String> aList =  Arrays.asList(a);// gives Compile time error
    

    来自Javadoc“Arrays.asList 返回一个由指定数组支持的固定大小的列表。(对返回的列表的更改“写入”到数组。)”这意味着您只提供了一个列表视图IMO 在运行时创建的数组,当然你不能改变数组的大小,所以你也不能改变“Arrays.asList”的大小。

    IMO Arrays.asList 的内部实现具有所有已实现的方法,可以将 Array 的大小更改为 -

    void add(E e)
    {
    //some unknown code
    throw(java.lang.UnsupportedOperationException);
    }
    

    因此,每当您尝试更改 Array 的大小时,它都会抛出 UnsupportedOperationException。

    如果您想使用这样的语法向 ArrayList 添加一些新项目,您可以通过创建 Arraylist 的子类来实现(最好使用 ArrayList 的匿名子类)。您可以将 Arrays.List 的返回类型传递给 ArrayList 的构造函数,(即 public ArrayList(Collection c)) 类似这样 -

    List<String> girlFriends = new java.util.ArrayList<String>(Arrays.asList("Rose", "Leena", "Kim", "Tina"));
    girlFriends.add("Sarah");
    

    现在您可以使用相同的语法轻松地将 Sarah 添加到您的 GF 列表中。

    PS - 请选择这一个或另一个作为您的答案,因为已经解释了一切。您的低录取率非常令人沮丧。

    【讨论】:

      【解决方案4】:

      asList() 不返回java.util.ArrayList,而是返回java.util.Arrays$ArrayList。这个类甚至没有扩展java.util.ArrayList,所以它的行为可能(并且是)完全不同。

      add() 方法继承自 java.util.AbstractList,默认情况下只抛出 UnsupportedOperationException

      【讨论】:

      • 不,asList 返回一个列表。您所描述的对于特定的 Java 实现可能是正确的,但不是您可以依赖的任何东西。
      • @jarnbjo - 对于 Sun Java 和 GNU Classpath 以及可能任何其他实现都是如此,因为这是最简单的方法。由于问题是关于编译器如何判断,我认为一个具体的例子最容易理解。
      【解决方案5】:

      您假设Arrays.asList() 返回ArrayList,但事实并非如此。 Arrays.asList() 返回未指定的 List 实现。该实现只是在每个不受支持的方法上抛出一个UnsupportedOperationException

      【讨论】:

        【解决方案6】:

        这是一个异常,而不是编译器错误。它在程序运行时抛出,而不是在编译时抛出。基本上,Arrays.asList 将返回的实际类在add() 方法内有一个throw UnsupporteOperationException

        更具体地说,Arrays.asList 将返回在 Arrays 类中定义的内部类,该类派生自 AbstractList 并且不实现 add 方法。 AbstractList 中的 add 方法实际上是在抛出异常。

        【讨论】:

          【解决方案7】:

          关键是返回的List实现

          List<String> aList =  Arrays.asList(a);
          

          如果您查看Arrays 中的源代码,您会发现它包含一个内部私有静态类ArrayList。这和java.util.ArrayList不一样。

          【讨论】:

            【解决方案8】:

            asList 返回一个固定大小的列表,因此您无法向其中添加新元素。因为它返回的列表实际上是它创建的数组的“视图”(在您的情况下为“a”),所以您将无法添加元素是有道理的 - 就像您无法将元素添加到数组。请参阅asList 的文档

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-12-30
              • 2017-02-22
              • 2019-05-06
              相关资源
              最近更新 更多