سؤال

My question is very basic, but I would like to understand everything in 100%. Many questions in SO referes to my post, but I haven't find a satisfying answer.

We know that Enums in java are reference type. Let's consider the following snippet:

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);

}

Output is quite obvious because copy constructor of Test makes a shallow copy:

10 100
200 3983
10 3983

BUT because enums in java are also reference types I do not understand one thing. Let's replace A class by Enum:

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);

}

I was expecting output:

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

But I've got:

10 ONE
200 THREE
10 ONE

Question: Why? Where my thinking is incorrect?

هل كانت مفيدة؟

المحلول

There's nothing special about enums here. You'll see the exact same behaviour if you use strings or any type, basically.

Your two Test objects are entirely separate. When you write:

t2.enumValue = TestEnum.THREE;

you're changing the value of the enumValue field within the second object to be a reference to the object referred to by TestEnum.THREE.

The two enumValue fields (one via t1 and one via t2) are entirely separate. Changing one field doesn't change another.

Now, if instead you made your enum mutable (which I would strongly discourage) and changed your code to something like this:

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

... then that would be visible via t1.enumValue, because they both refer to the same object.

It's really important to differentiate between changing a field within an instance of Test, and changing a field within an object that you happen to reach via an instance of Test.

Again, this really isn't about enums. You may well find it's simpler to get your head round the idea by changing the enumValue field to a String field, and experimenting that way.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top