Доступ 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, независимо от его значения члена.