Переменные Java отлично. Так что дженерики. Конечно, мы все знаем ограничения последнего из-за стирания стилей. Но есть одна вещь, которую я не понимаю, почему я не могу создать перечисление вроде этого:
public enum MyEnum<T> {
LITERAL1<String>,
LITERAL2<Integer>,
LITERAL3<Object>;
}
Этот общий параметр типа <T>
, в свою очередь, может быть полезен в разных местах. Представьте себе общий тип параметра для метода:
public <T> T getValue(MyEnum<T> param);
Или даже в самом классе перечисления:
public T convert(Object o);
Более конкретный пример # 1
Поскольку приведенный выше пример может показаться слишком абстрактным для некоторых, вот более реальный пример того, почему я хочу это сделать. В этом примере я хочу использовать
- Перечисляет, потому что тогда я могу перечислить конечный набор ключей свойств
- 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>
, и в то же время быть перечислением (неизменяемым, одиночным, перечислимым и т.д. и т.д.).
Вопрос:
Не думал ли об этом? Является ли это ограничение, связанное с компилятором? Учитывая тот факт, что ключевое слово " перечисление" реализовано как синтаксический сахар, представляющий сгенерированный код для JVM, я не понимаю этого ограничения.
Кто может это объяснить? Прежде чем ответить, рассмотрите следующее:
- Я знаю, что общие типы стираются: -)
- Я знаю, что есть обходные пути с использованием объектов класса. Это обходные пути.
- Общие типы приводят к генерации типов, генерируемых компилятором, где это применимо (например, при вызове метода convert()
- Общий тип <T> будет на перечислении. Следовательно, он связан каждым из литералов перечисления. Следовательно, компилятор знал бы, какой тип применять при написании чего-то вроде
String string = LITERAL1.convert(myObject); Integer integer = LITERAL2.convert(myObject);
- То же самое относится к параметру generic type в методе
T getvalue()
. Компилятор может применять приведение типов при вызовеString string = someClass.getValue(LITERAL1)