Java перечисления великолепны.Как и дженерики.Конечно, мы все знаем ограничения последнего из-за стирания типа.Но есть одна вещь, которую я не понимаю: почему я не могу создать перечисление вот так:
public enum MyEnum<T> {
LITERAL1<String>,
LITERAL2<Integer>,
LITERAL3<Object>;
}
Этот параметр общего типа <T>
, в свою очередь, может быть полезен в разных местах.Представьте параметр универсального типа для метода:
public <T> T getValue(MyEnum<T> param);
Или даже в самом классе enum:
public T convert(Object o);
Более конкретный пример # 1
Поскольку в приведенном выше примереможет показаться слишком абстрактным для некоторых, вот более реальный пример того, почему я хочу это сделать.В этом примере я хочу использовать
- Enums, потому что тогда я могу перечислить конечный набор ключей свойств
- Generics, потому что тогда у меня может быть безопасность типов на уровне метода для хранениясвойства
public interface MyProperties {
public <T> void put(MyEnum<T> key, T value);
public <T> T get(MyEnum<T> key);
}
Более конкретный пример # 2
У меня есть перечисление типов данных:
public interface DataType<T> {}
public enum SQLDataType<T> implements DataType<T> {
TINYINT<Byte>,
SMALLINT<Short>,
INT<Integer>,
BIGINT<Long>,
CLOB<String>,
VARCHAR<String>,
...
}
Каждый литерал перечисления, очевидно, будет иметь дополнительные свойства на основедля универсального типа <T>
, в то же время являясь перечислением (неизменяемое, однозначное, перечислимое и т. д.).
Вопрос:
Никто не подумал об этом?Это ограничение, связанное с компилятором?Учитывая тот факт, что ключевое слово " enum " реализовано как синтаксический сахар, представляющий сгенерированный код для JVM, я не понимаю этого ограничения.
Кто может мне это объяснить?Прежде чем ответить, рассмотрим следующее:
- Я знаю, что универсальные типы стерты: -)
- Я знаю, что есть обходные пути с использованием объектов Class.Это обходные пути.
- Универсальные типы приводят к приведениям типов, генерируемым компилятором, где это применимо (например, при вызове метода convert ()
- Универсальный тип будет в перечислении. Следовательно,он ограничен каждым из литералов перечисления, поэтому компилятор будет знать, какой тип применять при записи чего-то вроде
String string = LITERAL1.convert(myObject); Integer integer = LITERAL2.convert(myObject);
- То же самое относится к параметру универсального типа в методе
T getvalue()
. Компиляторможет применять приведение типа при вызове String string = someClass.getValue(LITERAL1)