Enum как переменные экземпляра
Если у вас есть перечисление, например
enum Coffee {
BIG,
SMALL
}
и класс, который имеет переменную экземпляра, такую как перечисление:
public class MyClass {
private Coffee coffee;
// Constructor etc.
}
Почему в конструкторе возможно говорить, например. coffee.BIG
?
Я не понимаю, что вы можете использовать ссылку? Является ли перечисление как переменные экземпляра инициализированным чем-то другим, кроме null
? Это вопрос самопроверки № 4 в книге SCJP в первой главе. Я попытался сократить код и вопрос.
Ответы
Ответ 1
В
enum Coffee {
BIG,
SMALL
}
BIG или SMALL являются полями public static final
класса Coffee, и, как и все статические поля, к ним может обращаться имя класса, например
Coffee b1 = Coffee.BIG;
или по ссылке того же типа, что и класс, например
Coffee s2 = b1.SMALL;
Coffee s3 = Coffee.BIG.SMALL; //BIG is reference of type Coffee so it is OK (but looks strange)
Но помните, что нам следует избегать доступа к статическим членам через ссылки. Это создает путаницу, поскольку мы действительно не обращаемся к членам экземпляра, а к членам класса (так, например, полиморфное поведение отсутствует).
Ответ 2
Вот что происходит за кадром:
E:\workspace>type Coffee.java
public enum Coffee {
BIG,
SMALL
}
E:\workspace>javap Coffee
Compiled from "Coffee.java"
public final class Coffee extends java.lang.Enum<Coffee> {
public static final Coffee BIG;
public static final Coffee SMALL;
public static Coffee[] values();
public static Coffee valueOf(java.lang.String);
static {};
}
Как вы можете видеть, BIG
и SMALL
являются по существу статическими полями в вашем перечислении.
JLS также очистить эту часть:
В дополнение к членам, которые наследуют тип перечисления E от Enum, для каждого объявленного enum константы с именем n, тип перечисления имеет неявно объявленное публичное статическое конечное поле с именем n типа E. Эти поля считаются объявленными в том же порядке, что и соответствующие константы enum, прежде чем какие-либо статические поля будут явно объявлен в типе перечисления. Каждое такое поле инициализируется перечислением константа, которая ему соответствует.
Надеюсь, это прояснит ваш вопрос.
Ответ 3
Перед Java 5 способ реализации перечислений состоял в том, чтобы создать класс с закрытым конструктором и общедоступными конечными полями того же класса, инициализированными определенными значениями.
Так как Java 5, конструкция enum фактически является сахаром, который делает то же самое, и заботится о вещах, таких как пустые значения, недопустимы, значения enum становятся общедоступными статическими полями и т.д.