Java Enum access to private instance variable

后端 未结 6 1819
名媛妹妹
名媛妹妹 2021-02-05 10:50

Consider the example:

enum SomeEnum {
    VALUE1(\"value1\"),
    VALUE2(\"value2\"),
    VALUE3(\"value3\")
    ;
    private String value;

    private SomeEnu         


        
相关标签:
6条回答
  • 2021-02-05 11:22

    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.

    0 讨论(0)
  • 2021-02-05 11:25

    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.

    0 讨论(0)
  • 2021-02-05 11:35

    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.

    0 讨论(0)
  • 2021-02-05 11:40

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

    0 讨论(0)
  • 2021-02-05 11:42

    The enums itself (VALUE1, VALUE2 and VALUE3) are static and final. They are three instances of the SomeEnum type and we can't change them (like deleting VALUE1 from the enum or adding a VALUE4 at runtime).

    But we can add public fields to the instances (like in your example) and alter the content of those fields at runtime.

    0 讨论(0)
  • 2021-02-05 11:43

    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);
    
    0 讨论(0)
提交回复
热议问题