有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

私有问题列表上的java迭代

我有一个SomeClass类,里面有一个List<String> someList。我需要让其他类在列表元素上迭代,但不允许它们更改列表或列表元素。测试以下代码:

public class SomeClass {
    static private List<String> someList;

    public static List<String> getSomeList() {
        return someList;
    }
    SomeClass(Array<String> someArray){
        someList=Collections.unmodifiableList(Arrays.asList(someArray));
    }

}
public class DoSomething {
    for (String s : SomeClass.getSomeList()){
    s+="Gotcha";
    }
}

将显示s只会在for循环中更改-一旦完成,getSomeList()将返回良好的旧列表,因此不会保存任何更改。正在尝试调用getSomeList()。add(“someString”)将导致异常:UnsupportedOperationException。 请(向经验丰富的C程序员)解释这种行为背后的逻辑,以及我如何捕获该异常


共 (3) 个答案

  1. # 1 楼答案

    来自javadoc, List stooges=数组。asList(“Larry”、“Moe”、“Curly”),它将返回一个由指定数组支持的固定大小的列表。 因此,对该列表的任何修改都将产生java。lang.UnsupportedOperationException即使代码中没有以下内容 收藏。不可修改列表(Arrays.asList(someArray))

  2. # 2 楼答案

    String的+=操作符实际上创建了一个新的字符串实例,而不是修改原始字符串对象。换句话说,以下两行代码是等效的:

    s += "Gotcha"
    s = new String(s + "Gotcha");
    

    示例

    下面是一个类似于doSomeThing的例子

    public class st {
      public static void main(String[] args) {
        String hello = "hello";
        String helloReference = hello; // making helloReference and hello refer to same object.
        helloReference += " world"; // perform +=
        System.out.format("`hello` = %s, `helloReference` = %s\n",
            hello, helloReference);
      }
    }
    

    它的输出如下所示,这表明由hello引用的对象不受由helloReference执行的+=运算符的影响:

    hello = `hello`, helloReference = `hello world`
    

    在另一个世界中,在+=运算符之前:

        hello            helloReference
          |                     |
       -------------------------------
       |        "hello"              |
       -------------------------------
    

    在+=运算符之后,它将创建一个新实例,并修改helloReference引用的对象:

        hello            helloReference
          |                     |             --------------------
          |                     --------------|   "hello world"  |
       -------------------------------        --------------------
       |        "hello"              |
       -------------------------------
    

    因此,代码可以安全运行,doSomeThing中执行的操作将影响SomeClass引用的对象:

    public class DoSomething {
      for (String s : SomeClass.getSomeList()){
        // this create an new string instance to s
        s+="Gotcha"; 
      }
    }
    
  3. # 3 楼答案

    once it's finished getSomeList() will return the good old list so no changes are saved.

    因为,^{}immutable,所以更改不会反映在最终列表中。。使用^{}^{}代替String作为列表的元素

    Also trying to call getSomeList().add("someString") will result in an exception: UnsupportedOperationException.

    因为,^{}正在返回^{},它是Arrays类中定义的嵌套类,如下所示:

    private static class ArrayList<E> extends AbstractList<E>
             implements RandomAccess, java.io.Serializable
    

    这个类扩展了^{},它反过来又扩展了^{}。嵌套类ArrayList没有重写AbstractList^{}方法。因此,当您在这个List上调用add()时,它会调用AbstractCollection^{}方法,该方法的定义如下:

    public boolean add(E e) {
                 throw new UnsupportedOperationException();
            }
    

    这就是为什么你在打电话给add("something")时会得到^{}