0

我编写了一个函数来处理一些 ArrayList,并希望将列表传递给外部调用者。但是我发现调用函数后列表没有改变。

这是一些测试代码(因为它是一个演示,但说明了我的问题):

@Test
public void testList() {
    List<Integer> l1 = new ArrayList<Integer>(5);
    List<Integer> l2 = new ArrayList<Integer>(5);
    l1.add(11); l1.add(12); l1.add(13); l1.add(14); l1.add(15);
    l2.add(21); l2.add(22); l2.add(23); l2.add(24); l2.add(25);
    System.out.println("outer l1: " + l1);
    System.out.println("outer l2: " + l2);

    subList(l1, l2);  //call the function

    System.out.println("after l1: " + l1);
    System.out.println("after l2: " + l2);
}

protected static void subList(List<Integer> l1, List<Integer> l2) {
    l1.remove(0);  l1.remove(0);
    l2 = l2.subList(0, 4);
    System.out.println("inner l1: " + l1);
    System.out.println("inner l2: " + l2);
}

结果是:

outer l1: [11, 12, 13, 14, 15]
outer l2: [21, 22, 23, 24, 25]
inner l1: [13, 14, 15]             (in function, changed)
inner l2: [21, 22, 23, 24]         (in function, changed too)
after l1: [13, 14, 15]             (changed)
after l2: [21, 22, 23, 24, 25]     (unchanged?!)

似乎 List2 没有被函数subList(List l1, List l2)改变,而 List1 改变了。

List参数是CopyValue传递的吗??那么,在函数中,当l2的引用发生变化时,JVM复制了一个新的链表,原来的外链表是保持旧值吗?

如何编写“副作用”程序来修改 ArrayList ?

4

6 回答 6

4

在 Java 中,引用总是按值传递。因此,在被调用方法中分配新值l2不会更改调用方法中的引用。

您需要以下代码才能使其工作:

List<Integer> subList = new ArrayList<Integer>(l2.subList(0, 4));
l2.clear();
l2.addAll(subList);
于 2012-09-18T12:07:05.450 回答
1

subList方法创建一个新的列表对象,旧的将保持不变。您可以调用clear旧列表并使用addAll将新列表中的数据复制回其中...

于 2012-09-18T12:03:46.520 回答
1

问题出在这一行:

l2 = l2.subList(0, 4);

这将分配l2给一个新对象,并且由于 Java 仅按值传递(而不是引用),因此您只能在场景中修改原始对象。

于 2012-09-18T12:04:42.800 回答
1

subList是原始列​​表中数据的视图(请参阅文档)。它与原始列表具有相同的引用,但任何结构更改(例如删除项目)都不会反映在原始列表中。

您应该对原始列表进行更改。

于 2012-09-18T12:05:35.877 回答
1

l2.subList(0, 4);它创建了一个新的 list 实例,您使用 l2 保存该实例,但在主类 l2 中创建的实例保持不变。

subList(List<Integer> l1, List<Integer> l2)l2 引用主类中创建的实例,并l2 = l2.subList(0, 4);用新创建的实例重写 l2 引用值。所以在主类中创建的实例保持不变。

于 2012-09-18T12:07:45.033 回答
0

- subList就像原始列表中的数据呈现。

-对 的任何更改sublist都不会反映在原始列表中。

-最好使用 aCopy-Constructor来执行此操作...

例如:

List<Integer> subList = new ArrayList<Integer>(l2.subList(0, 4));

于 2012-09-18T12:11:47.467 回答