3

我的问题非常基本,但我想 100% 了解所有内容。SO中的许多问题都参考了我的帖子,但我还没有找到令人满意的答案。

我们知道java中的枚举是引用类型。让我们考虑以下代码段:

public static class A {
    public int i;
    public A(int i) {
        this.i = i;
    }
}

public static class Test {
    int i;
    A a;

    public Test(int i, A a){
        this.i = i;
        this.a = a;
    }

    public Test(Test oldTest){
        this.i = oldTest.i;
        this.a = oldTest.a;
    }
}

public static void main(String[] args) {
    Test t1 = new Test(10, new A(100));
    System.out.println(t1.i + " " + t1.a.i);
    Test t2 = new Test(t1);
    t2.i = 200;
    t2.a.i = 3983;
    System.out.println(t2.i + " " + t2.a.i);
    System.out.println(t1.i + " " + t1.a.i);

}

输出非常明显,因为 Test 的拷贝构造函数做了一个浅拷贝:

10 100
200 3983
10 3983

但是因为 java 中的枚举也是引用类型,所以我不明白一件事。让我们用 Enum 替换 A 类:

public static enum TestEnum {
        ONE, TWO, THREE;        
    }

    public static class Test {
        int i;
        TestEnum enumValue;

    public Test(int i, TestEnum enumVar){
        this.i = i;
        this.enumValue = enumVar;  
    }

    public Test(Test oldTest){
        this.i = oldTest.i;
        this.enumValue = oldTest.enumValue;  // WHY IT IS OK ?? 
    }
}

public static void main(String[] args) {
    Test t1 = new Test(10, TestEnum.ONE);
    System.out.println(t1.i + " " + t1.enumValue);
    Test t2 = new Test(t1);
    t2.i = 200;
    t2.enumValue = TestEnum.THREE;  // why t1.emunValue != t2.enumValue  ??
    System.out.println(t2.i + " " + t2.enumValue);
    System.out.println(t1.i + " " + t1.enumValue);

}

我期待输出:

10 ONE
200 THREE
10 THREE   <--- I thought that reference has been copied... not value

但我有:

10 ONE
200 THREE
10 ONE

问:为什么?我的想法哪里不对?

4

1 回答 1

4

这里的枚举没有什么特别之处。基本上,如果您使用字符串或任何类型,您将看到完全相同的行为。

你的两个Test对象是完全分开的。当你写:

t2.enumValue = TestEnum.THREE;

您正在将enumValue第二个对象中的字段值更改为对TestEnum.THREE.

这两个enumValue字段(一个 viat1和一个 via t2)是完全独立的。改变一个领域不会改变另一个领域。

现在,如果您将枚举设置为可变的(我强烈反对)并将您的代码更改为如下所示:

t2.enumValue.someMutableField = "a different value";

...那么这通过 可见t1.enumValue,因为它们都引用同一个对象。

区分更改 的实例中Test的字段和更改您碰巧通过 的实例到达Test的对象中的字段非常重要。

同样,这真的与枚举无关。enumValue您可能会发现通过将字段更改为字段并以这种方式进行试验来更容易理解这个想法String

于 2013-06-05T09:24:36.067 回答