Java Enum access to private instance variable

25,073

Solution 1

No-one seems to have addressed the private aspect. My guess is that you're accessing the private field from a containing type - that your enum is actually a nested type, like this:

class Test
{
    static void Main() {
        // Entirely valid
        SomeEnum.VALUE1.value = "x";
    }

    enum SomeEnum {
        VALUE1("value1");

        private String value;

        private SomeEnum(final String value) {
            this.value = value;
        }
    }
}

That's entirely legitimate and normal - you can always access private members of a nested type from the containing type.

If you make the enum a top-level type, you won't see this.

As for changing values - as everyone else has said, VALUE1 is implicitly static and final, but that doesn't stop you from changing VALUE1.value. Again, this is entirely in accordance with how Java works elsewhere - if you have a static field of type List, you can still add entries to it, because that's not modifying the field itself.

If you want to make SomeEnum properly immutable, make the value field final.

Solution 2

You can't do

SomeEnum.VALUE1 = "Value4";
System.out.println(SomeEnum.VALUE1);

but you can do

SomeEnum.VALUE1.value = "Value4";
System.out.println(SomeEnum.VALUE1);

and value really changes, but not the static final VALUE1.

Also, since value is private, why can I access it outside other classes?

You can access a private field in an outer/inner class, but I cannot find an example of where you can access it from another class (in the same package for example).

Solution 3

Isn't that enum instance(s) are implicitly static and final?

Nope. Members of enum-instances such as value in your example can be mutable.

(The references to the instances (SomeEnum.VALUE1 etc in your example) are final and static though.

Also, since value is private, why can I access it outside other classes?

You can't. An enum is a "class" with an enumerable number of instances. That's all.

VALUE1 is in this case a an instance of the "class" SomeEnum, thus SomeEnum.VALUE1.value is an ordinary field like any other.


When you do

System.out.println(SomeEnum.VALUE1);

you invoke SomeEnum.VALUE1.toString which accesses the value field. You're not accessing the value-field immediately.

// Not possible since field is private.
System.out.println(SomeEnum.VALUE1.value);

Solution 4

Isn't that enum instance(s) are implicitly static and final?

The Enum instances have these traits. But no one said, these instances are immutable like Integer or String. So you can modify the values.

That does not mean that this is recommended practice! It isn't.

Edit

To explain a little more:

"Enum implicitly static" means:

enum Foo { FOO };

Here FOO is static, although the normal Java syntax would suggest, that FOO is an instance variable wrongly named like a constant. You also access it like a static variable.

"Enum implicitly final" means:

enum Foo { FOO, BAR };
Foo.FOO = Foo.BAR;

is not allowed. The reference stored in FOO cannot be changed. You also cannot create new instances.

"Enum not implicitly immutable" means: Foo.FOO will give you an object. A standard object. If the object allows modifications of its own content - so it be. This is not forbidden.

Solution 5

SomeEnum.VALUE1 = "Value4" ... actually does not work.

More important, VALUE1 will always only be equal to VALUE1 and not VALUE2 or VALUE3, independent of it's member value.

Share:
25,073
Buhake Sindi
Author by

Buhake Sindi

First person in South Africa to receive a Gold Java Badge (Received on 5th November 2011) and 71st overall on StackOverflow. Whoohoo! :-) I also founded Devoxx4Kids South Africa to promote technology education among children. Where can you find me? Sindi Technologies (Founder) My Blog (A Developer's Enterprise Log...) GitHub Twitter LinkedIn Google+ SoundCloud #SOreadytohelp The following shows the experiences I have with computer programming languages & various frameworks. It is not a reflection of who I am. Professional experience: Enterprise Java (Jakarta EE/ Java EE, Spring Framework) JavaScript Frameworks: (Angular 1.x), ReactJS (JavaScript/TypeScript), jQuery VB .NET SQL (RDBMS independent) Web Technologies: HTML/XHTML/HTML 5, JavaScript, JavaScript/jQuery/Angular 1.x and higher --> CSS (from version 1 to 3), including Bootstrap Framework External Experience: Pascal / Delphi VB C/C++ Assembly language Adobe Flex PHP Scala Go (Briefly played with)

Updated on July 09, 2022

Comments

  • Buhake Sindi
    Buhake Sindi almost 2 years

    Consider the example:

    enum SomeEnum {
        VALUE1("value1"),
        VALUE2("value2"),
        VALUE3("value3")
        ;
        private String value;
    
        private SomeEnum(final String value) {
            this.value = value;
        }
    
        //toString
        public String toString() {
            return value;
        }
    }
    

    How come can we do this (and the value really changes)?

    SomeEnum.VALUE1.value = "Value4";
    System.out.println(SomeEnum.VALUE1);
    

    Isn't that enum instance(s) are implicitly static and final? Also, since value is private, why can I access it outside other classes?

  • Buhake Sindi
    Buhake Sindi about 12 years
    Sorry, just updated the question: It's `SomeEnum.VALUE1.value = "Value4";
  • Buhake Sindi
    Buhake Sindi about 12 years
    Sorry, just updated the question: It's `SomeEnum.VALUE1.value = "Value4";
  • Daniel Lubarov
    Daniel Lubarov about 12 years
    Good answer. In other words, final provides only shallow immutability.
  • Buhake Sindi
    Buhake Sindi about 12 years
    That's not what I asked at all. Consider changing the answer before it gets downvoted.
  • Buhake Sindi
    Buhake Sindi about 12 years
    You can view value outside other classes. I did a test case and it worked.
  • Vishy
    Vishy about 12 years
    similar to static only makes the reference static, volatile only make the reference volatile, transient only makes the reference transient (but not the object referenced) private/public only makes the reference private/public but not the contents. etc. etc. ;)
  • Buhake Sindi
    Buhake Sindi about 12 years
    Look at my question carefully. I said SomeEnum.VALUE1.value = "Value4", not SomeEnum.VALUE1 = "Value4".
  • Jon Skeet
    Jon Skeet about 12 years
    @TheEliteGentleman: Looks like what you asked to me, unless I'm not seeing the edit...
  • Buhake Sindi
    Buhake Sindi about 12 years
    True, but shouldn't I not be able to see value since it's private? I.e. I shouldn't be able to say, VALUE1.value at all (unless, I had a public getter method).
  • Buhake Sindi
    Buhake Sindi about 12 years
    @Jon Skeet, my question is not about modifying VALUE1 but why VALUE1.value can be modified at all, even though it's a private instance. Doesn't the enum rules (of implicit static and final) apply to its instances too?
  • A.H.
    A.H. about 12 years
    @TheEliteGentleman: Can you explain a little bit? Besides the wording I'm in the same ballpark as the other answers and your own observations. I simply stated, that the traits you mentioned are not relevant to your problem, it's the (missing) immutable trait that's linked to your problem.
  • Jon Skeet
    Jon Skeet about 12 years
    @TheEliteGentleman: You mean its fields (there's no such concept as a "private instance"), and no, certainly not. There's no transitive application of the final modifier anywhere in Java.
  • Jon Skeet
    Jon Skeet about 12 years
    @TheEliteGentleman: You did now, yes - but what did your question say before you updated it?
  • Vishy
    Vishy about 12 years
    Can you give an example of where you are accessing from another class (and not an outer or inner class)
  • Buhake Sindi
    Buhake Sindi about 12 years
    @JonSkeet, I updated my question 21 minutes ago. The OP answered 12 minutes ago. That is 9 minutes difference since my last update (of which I included the change).
  • A.H.
    A.H. about 12 years
    @JonSkeet: No, there was no edit you could miss at that point of time.
  • Buhake Sindi
    Buhake Sindi about 12 years
    That just gives a perspective of An enum type is a type whose fields consist of a fixed set of constants. I can have a mutable property inside an enum and change it at any time in my own leisure.
  • Jon Skeet
    Jon Skeet about 12 years
    @TheEliteGentleman: Do you not think it's possible that the answerer had your original question open all that time? I think it's entirely possible - and that if you originally made a mistake in the question, and others are trying to help you, then it's nice to give them the benefit of the doubt. Your comment should have at least suggested that the answerer might have only seen the (incorrect) original version of your question. Between this and "Consider changing the answer before it gets downvoted" it feels like you're not really in the spirit of things...
  • Buhake Sindi
    Buhake Sindi about 12 years
    The person who wrote the example, later removed the private keyword. value is now default (and hence why he could see it outside other classes). This was a stupid exercise.
  • Jon Skeet
    Jon Skeet about 12 years
    @A.H.: Okay, in that case it seems you did indeed answer exactly what was asked, and it's just the OP misunderstanding what it means for an enum value to be final.
  • Jon Skeet
    Jon Skeet about 12 years
    @TheEliteGentleman: Yes, you can - and that's a really bad idea. An enum type is a type with a fixed set of instances of that type. So there's a set of static final fields within type SomeEnum, which are fields of type SomeEnum. Those are used to access the instances. Any extra fields that you declare work exactly like other fields - you can have static fields or instance fields, final fields or non-final fields etc.
  • Buhake Sindi
    Buhake Sindi about 12 years
    Well, unfortunately, I maintain codes that do just that and I thought that it can't be since it breaks enum contracts (or I thought it does).
  • Jon Skeet
    Jon Skeet about 12 years
    @TheEliteGentleman: It's not clear what you mean - the enum contract in the JLS certainly doesn't guarantee that the instances will be immutable. I would strongly recommend that you make them immutable though.
  • Buhake Sindi
    Buhake Sindi about 12 years
    @Jon Skeet, thanks. I assumed the OP just opened the question now since 9 minutes is long enough to see an updated change. I will consider being more user-friendly on posts.
  • Jon Skeet
    Jon Skeet about 12 years
    @TheEliteGentleman: Consider a user who opens up SO, finds a bunch of questions and puts them in different tabs, then looks at each one in turn. Although there's notification of answers being added, I'm not sure there's notification of the question being updated...
  • Jon Skeet
    Jon Skeet about 12 years
    @TheEliteGentleman: So your enums aren't just mutable, but are being mutated? If so, that sounds like code which really needs to be addressed ASAP.