将 LinkedList<short[]>传递给构造函数,它会起作用吗?



我有类SpeexRunner如下,的构造函数采用两个参数一个布尔变量和一个LinkedList<short[]>。如下:-

public class SpeexRunner implements Runnable {
    public boolean stopThread;
    LinkedList<short[]> dataList;
    public SpeexRunner(boolean val_stopThread, LinkedList<short[]> dataRef){
        this.stopThread = val_stopThread;
        dataList = dataRef;
    }
    @Override
    public void run() {
     //add objects in dataList;
     // change / remove dataList Objects
    }
}

我的问题是:- 如果我在 run() 中更改 dataList,这些更改会反映到其他地方声明的原始列表中吗?

如果我在 run() 中更改 dataList,更改是否会反映到其他地方声明的原始列表中?

是的。构造函数接收对列表的引用,而不是列表的副本。如果要复制它,则必须使用 LinkedList 复制构造函数。然后,您将拥有自己的列表副本。但请注意,两个列表中的条目仍然是共享的,因为这些条目是数组 ( short[] ),并且数组是通过引用存储的。

这也许最好通过示例来证明:

import java.util.*;
public class ListExample {
    public static final void main(String[] args) {
        List<short[]> list;
        // Direct use (no copies)
        list = new LinkedList<short[]>();
        list.add(new short[] { 0, 0, 0 });
        System.out.println("list.size() before direct use: " + list.size());
        System.out.println("list.get(0)[0] before direct use: " + list.get(0)[0]);
        new DirectUser(list).doSomething();
        System.out.println("list.size() after direct use: " + list.size());
        System.out.println("list.get(0)[0] after direct use: " + list.get(0)[0]);
        // Output, note how both the list and its contents have been changed:
        // list.size() before direct use: 1
        // list.get(0)[0] before direct use: 0
        // list.size() after direct use: 2
        // list.get(0)[0] after direct use: 1
        // Copying the list, but note that the entries are shared by both lists:
        list = new LinkedList<short[]>();
        list.add(new short[] { 0, 0, 0 });
        System.out.println("list.size() before copy-list use: " + list.size());
        System.out.println("list.get(0)[0] before copy-list use: " + list.get(0)[0]);
        new CopyListUser(list).doSomething();
        System.out.println("list.size() after copy-list use: " + list.size());
        System.out.println("list.get(0)[0] after copy-list use: " + list.get(0)[0]);
        // Output, note how our list didn't change (it doesn't have a new entry), but
        // the entry at index 0 *was* changed:
        // list.size() before copy-list use: 1
        // list.get(0)[0] before copy-list use: 0
        // list.size() after copy-list use: 1
        // list.get(0)[0] after copy-list use: 1
        // "Deep" copying, both the list and its entries:
        list = new LinkedList<short[]>();
        list.add(new short[] { 0, 0, 0 });
        System.out.println("list.size() before deep-copy use: " + list.size());
        System.out.println("list.get(0)[0] before deep-copy use: " + list.get(0)[0]);
        new DeepCopyUser(list).doSomething();
        System.out.println("list.size() after deep-copy use: " + list.size());
        System.out.println("list.get(0)[0] after deep-copy use: " + list.get(0)[0]);
        // Output, note that neither the list nor its entries was affected by the call:
        // list.size() before deep-copy use: 1
        // list.get(0)[0] before deep-copy use: 0
        // list.size() after deep-copy use: 1
        // list.get(0)[0] after deep-copy use: 0

        System.exit(0);
    }
    static class DirectUser {
        List<short[]> items;
        DirectUser(List<short[]> items) {
            // DirectUser doesn't copy the list
            this.items = items;
        }
        void doSomething() {
            this.items.get(0)[0] = 1;
            this.items.add(new short[] { 2, 2, 2 });
        }
    }
    static class CopyListUser {
        List<short[]> items;
        CopyListUser(List<short[]> items) {
            // CopyListUser copies the list, but both lists still share items
            this.items = new LinkedList<short[]>(items);
        }
        void doSomething() {
            this.items.get(0)[0] = 1;
            this.items.add(new short[] { 2, 2, 2 });
        }
    }
    static class DeepCopyUser {
        List<short[]> items;
        DeepCopyUser(List<short[]> items) {
            // DeepCopyUser copies the list AND each entry
            this.items = new LinkedList<short[]>();
            for (short[] entry : items) {
                this.items.add(Arrays.copyOf(entry, entry.length));
            }
        }
        void doSomething() {
            this.items.get(0)[0] = 1;
            this.items.add(new short[] { 2, 2, 2 });
        }
    }
}

DirectUser使用该列表时,在我们的调用代码中,我们看到列表(因为它变得更长)及其内容(第一个条目的第一个插槽从 0 更改为 1)的变化。

CopyListUser使用它时,它会复制列表,因此我们在调用代码中没有看到列表的任何更改(它没有变得更长)。但我们确实看到了对第一个条目的更改(因为两个列表共享同一个数组对象) ——第一个插槽再次从0更改为1

DeepCopyUser使用它时,它会复制列表每个条目的副本,因此事情完全完全断开。我们的调用代码未看到对列表或其项的更改。

如果我在 run() 中更改 dataList,更改是否会反映到其他地方声明的原始列表中?

简短的回答:是的。

稍长的答案:是的,因为参数在 Java 中总是通过引用传递的。

(您可能会

使用禁止或忽略更改的(假设的)LinkedList子类。 在这种情况下,尝试的更改将导致异常或不起作用。 但是,这将是反常的...

是的,它会因为线程具有对列表的引用,而不是列表的副本。请注意,LinkedList 不会同步

如果多个线程同时访问链表,并且至少有一个线程在结构上修改了该列表,则必须在外部同步该列表。

如果将

元素添加到/从列表中删除元素,则更改将从代码的其余部分可见。请注意,如果使用多个线程,则需要使用同步来保证更改可见。

另一方面,如果您不希望更改转义您的类,则可以在构造函数中创建一个新的 List,并在原始列表中添加所有项。在这种情况下,对列表所做的更改从外部将不可见,但如果对列表中的项目进行更改,这些更改将会显示。

最新更新