Java Enum access to private instance variable
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.
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, 2022Comments
-
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
isprivate
, why can I access it outside other classes? -
Buhake Sindi about 12 yearsSorry, just updated the question: It's `SomeEnum.VALUE1.value = "Value4";
-
Buhake Sindi about 12 yearsSorry, just updated the question: It's `SomeEnum.VALUE1.value = "Value4";
-
Daniel Lubarov about 12 yearsGood answer. In other words, final provides only shallow immutability.
-
Buhake Sindi about 12 yearsThat's not what I asked at all. Consider changing the answer before it gets downvoted.
-
Buhake Sindi about 12 yearsYou can view
value
outside other classes. I did a test case and it worked. -
Vishy about 12 yearssimilar 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 about 12 yearsLook at my question carefully. I said
SomeEnum.VALUE1.value = "Value4"
, notSomeEnum.VALUE1 = "Value4"
. -
Jon Skeet about 12 years@TheEliteGentleman: Looks like what you asked to me, unless I'm not seeing the edit...
-
Buhake Sindi about 12 yearsTrue, 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 about 12 years@Jon Skeet, my question is not about modifying
VALUE1
but whyVALUE1.value
can be modified at all, even though it's a private instance. Doesn't the enum rules (of implicitstatic
andfinal
) apply to its instances too? -
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 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 about 12 years@TheEliteGentleman: You did now, yes - but what did your question say before you updated it?
-
Vishy about 12 yearsCan you give an example of where you are accessing from another class (and not an outer or inner class)
-
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. about 12 years@JonSkeet: No, there was no edit you could miss at that point of time.
-
Buhake Sindi about 12 yearsThat 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 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 about 12 yearsThe person who wrote the example, later
removed
theprivate
keyword.value
is now default (and hence why he could see it outside other classes). This was a stupid exercise. -
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 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 typeSomeEnum
. 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 about 12 yearsWell, 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 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 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 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 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.