Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Enum access to private instance variable

Tags:

java

enums

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?

like image 652
Buhake Sindi Avatar asked Feb 27 '12 12:02

Buhake Sindi


People also ask

Can enum have private variables?

Enum FieldsThe enum constructor must be private . You cannot use public or protected constructors for a Java enum . If you do not specify an access modifier the enum constructor it will be implicitly private .

How do I access private instance variables?

We have used the getter and setter method to access the private variables. Here, the setter methods setAge() and setName() initializes the private variables. the getter methods getAge() and getName() returns the value of private variables.

Can an enum be an instance variable?

Enums are very powerful as they may have instance variables, instance methods, and constructors. Each enum constant should be written in capital letters. Every enum constant is by default internally public static final of type Enum declared.

Can we use private modifier in enum in Java?

About Java EnumsJava enum constructors must use a private or default package-level modifier.


3 Answers

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.

like image 200
Jon Skeet Avatar answered Sep 24 '22 09:09

Jon Skeet


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

like image 32
Peter Lawrey Avatar answered Sep 23 '22 09:09

Peter Lawrey


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);
like image 2
aioobe Avatar answered Sep 24 '22 09:09

aioobe