#java #enums
Вопрос:
Учитывая следующее перечисление:
public enum Letter {
Alpha, Beta, Gamma, Delta;
}
Затем оба следующих действия компилируются без ошибок:
Letter letter1 = Letter.Alpha;
Enum<Letter> letter2 = Letter.Beta;
Вызов getClass()
или name()
или ordinal()
на обоих letter1
и letter2
показывает одни и те же результаты.
Но! Следующее будет скомпилировано:
switch( letter1 ) {
case Alpha:
case Beta:
}
Пока этого не будет:
switch( letter2 ) {
case Alpha:
case Beta:
}
Так в чем же, если таковые имеются, заключается точная техническая разница между этими двумя переменными?
Комментарии:
1. Оказывается, что из-за ограничительного типа bound (
T extends Enum<T>
) единственным классом, который может быть реализованEnum<Letter>
, являетсяLetter
он сам. Но система типов этого не знает, поэтому она не делает вывод, что набор значенийEnum<Letter>
состоит только из константLetter
и ничего больше. В общем, вы очень редко используетеEnum
напрямую, кроме как в качестве привязки к типу. (Мало чем отличаетсяAbstractList
; почти единственные места, где он используется, — этоextends
предложения его подклассов.)2. @Zabuzard Нет, это не так. Это базовый класс
Letter
, вот так просто. Вот почему назначение возможно, но случаи переключения-нет.
Ответ №1:
Letter
это Enum<Letter>
так, как Integer
есть Number
. Подкласс к суперклассу. Единственная разница в том, что Enum<>
это привилегированный суперкласс, связанный с определенной функцией языка. (Смотрите java.lang.Record
еще один такой привилегированный суперкласс.)
Если у нас есть эти две переменные:
Integer n1 = 1;
Number n2 = 2;
… тогда это работает:
jshell> switch(n1) { case 1: System.out.println("one"); break; default: System.out.println("not one"); break;}
one
… но это не значит:
jshell> switch(n2) { case 1: System.out.println("one"); break; default: System.out.println("not one"); break;}
| Error:
| incompatible types: java.lang.Number cannot be converted to int
| switch(n2) { case 1: System.out.println("one"); break; default: System.out.println("not one"); break;}
| ^--^
В обоих случаях компилятор не может доказать (до выполнения), что Number
или Enum<Letter>
является чем-то, что он может включить, поэтому он не позволит вам этого сделать.