Доступ Java к переменной частного экземпляра

Рассмотрим пример:

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

Как мы можем это сделать (и значение действительно)?

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

Не является ли этот экземпляр enum неявным статичным и окончательным? Кроме того, поскольку value - private, почему я могу обращаться к нему за пределами других классов?

Ответы

Ответ 1

Никто, кажется, не рассмотрел частный аспект. Я предполагаю, что вы обращаетесь к частному полю из содержащего типа - что ваш enum на самом деле является вложенным типом, например:

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

Это полностью законно и нормально - вы всегда можете получить доступ к закрытым членам вложенного типа из содержащего типа.

Если вы сделаете перечисление типа верхнего уровня, вы не увидите этого.

Что касается изменения значений, как все остальные сказали, VALUE1 неявно статично и окончательно, но это не мешает вам изменить VALUE1.value. Опять же, это полностью соответствует тому, как Java работает в другом месте - если у вас есть статическое поле типа List, вы можете добавить к нему записи, потому что это не модифицирует само поле.

Если вы хотите сделать SomeEnum корректно неизменным, сделайте поле value final.

Ответ 2

Вы не можете сделать

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

но вы можете сделать

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

и value действительно изменяется, но не статический окончательный VALUE1.

Кроме того, поскольку значение является приватным, почему я могу получить доступ к нему за пределами других классов?

Вы можете получить доступ к закрытому полю во внешнем/внутреннем классе, но я не могу найти пример того, где вы можете получить доступ к нему из другого класса (например, в том же пакете).

Ответ 3

Не является ли этот экземпляр enum неявным статичным и окончательным?

Неа. Члены экземпляров enum, таких как value в вашем примере, могут быть изменены.

(Ссылки на экземпляры (SomeEnum.VALUE1 и т.д. в вашем примере) являются окончательными и статичными, хотя.

Кроме того, поскольку значение является приватным, почему я могу получить доступ к нему за пределами других классов?

Вы не можете. enum - это "класс" с перечислимым количеством экземпляров. Это все.

VALUE1 в этом случае является экземпляром "класса" SomeEnum, поэтому SomeEnum.VALUE1.value является обычным полем, как и любое другое.


Когда вы делаете

System.out.println(SomeEnum.VALUE1);

вы вызываете SomeEnum.VALUE1.toString, который обращается к полю value. Вы не сразу получаете доступ к полю value.

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

Ответ 4

Не является ли этот экземпляр enum неявным статичным и окончательным?

У экземпляров Enum эти черты. Но никто не сказал, что эти экземпляры неизменны, как Integer или String. Таким образом, вы можете изменить значения.

Это не значит, что это рекомендуется! Это не так.

Edit

Чтобы объяснить немного больше:

"Enum неявно статично" означает:

enum Foo { FOO };

Здесь FOO является статическим, хотя обычный синтаксис Java предполагает, что FOO является переменной экземпляра, неправильно названной как константа. Вы также обращаетесь к нему как к статической переменной.

"Enum imicitly final" означает:

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

не разрешено. Ссылка, хранящаяся в FOO, не может быть изменена. Вы также не можете создавать новые экземпляры.

"Enum not implicitly immutable" означает: Foo.FOO предоставит вам объект. Стандартный объект. Если объект допускает модификации собственного контента - так оно и есть. Это не запрещено.

Ответ 5

Сами перечисления (VALUE1, VALUE2 и VALUE3) являются статическими и окончательными. Это три экземпляра типа SomeEnum, и мы не можем их изменить (например, удаление VALUE1 из перечисления или добавление VALUE4 во время выполнения).

Но мы можем добавлять открытые поля к экземплярам (например, в вашем примере) и изменять содержимое этих полей во время выполнения.

Ответ 6

SomeEnum.VALUE1 = "Value4"... на самом деле не работает.

Более важно, VALUE1 всегда будет только VALUE1, а не VALUE2 или VALUE3, независимо от его значения члена.