Почему не нужно, чтобы литералы enums Java могли иметь параметры типового типа?

Переменные Java отлично. Так что дженерики. Конечно, мы все знаем ограничения последнего из-за стирания стилей. Но есть одна вещь, которую я не понимаю, почему я не могу создать перечисление следующим образом:

public enum MyEnum { LITERAL1, LITERAL2, LITERAL3; } 

Этот общий параметр типа в свою очередь, может тогда быть полезен в разных местах. Представьте общий тип параметра для метода:

 public  T getValue(MyEnum param); 

Или даже в classе enum:

 public T convert(Object o); 

Более конкретный пример № 1

Поскольку приведенный выше пример может показаться слишком абстрактным для некоторых, вот более реальный пример того, почему я хочу это сделать. В этом примере я хочу использовать

  • Enums, потому что тогда я могу перечислить конечный набор ключей свойств
  • Generics, потому что тогда у меня может быть тип-тип-тип безопасности для хранения свойств
 public interface MyProperties { public  void put(MyEnum key, T value); public  T get(MyEnum key); } 

Более конкретный пример # 2

У меня есть перечисление типов данных:

 public interface DataType {} public enum SQLDataType implements DataType { TINYINT, SMALLINT, INT, BIGINT, CLOB, VARCHAR, ... } 

Каждый литерал enums, очевидно, имел бы дополнительные свойства, основанные на родовом типе , в то же время, являясь перечислением (неизменяемым, одиночным, перечислимым и т. Д. И т. Д.),

Вопрос:

Никто не думал об этом? Является ли это ограничение, связанное с компилятором? Учитывая тот факт, что ключевое слово « enum » реализовано как синтаксический сахар, представляющий сгенерированный код для JVM, я не понимаю этого ограничения.

Кто может это объяснить? Прежде чем ответить, рассмотрите следующее:

  • Я знаю, что общие типы стираются 🙂
  • Я знаю, что есть обходные пути с использованием объектов classа. Это обходные пути.
  • Типичные типы приводят к генерации типов, генерируемых компилятором, где это применимо (например, при вызове метода convert ()
  • Общий тип будет на перечислении. Следовательно, он связан каждым из перечислений enum. Следовательно, компилятор должен знать, какой тип применять при написании чего-то типа String string = LITERAL1.convert(myObject); Integer integer = LITERAL2.convert(myObject); String string = LITERAL1.convert(myObject); Integer integer = LITERAL2.convert(myObject);
  • То же самое относится к параметру generic type в T getvalue() . Компилятор может применять тип casting при вызове String string = someClass.getValue(LITERAL1)

7 Solutions collect form web for “Почему не нужно, чтобы литералы enums Java могли иметь параметры типового типа?”

В настоящее время это обсуждается с расширенными enumsми JEP-301 . Пример, приведенный в JEP, является именно тем, что я искал:

 enum Argument { // declares generic enum STRING(String.class), INTEGER(Integer.class), ... ; Class clazz; Argument(Class clazz) { this.clazz = clazz; } Class getClazz() { return clazz; } } Class cs = Argument.STRING.getClazz(); //uses sharper typing of enum constant 

К сожалению, JEP по-прежнему борется со значительными проблемами: http://mail.openjdk.java.net/pipermail/amber-spec-experts/2017-May/000041.html

Ответ на вопрос:

из-за стирания типа

Ни один из этих двух методов невозможен, поскольку тип аргумента стирается.

 public  T getValue(MyEnum param); public T convert(Object); 

Чтобы реализовать эти методы, вы, однако, можете создать свой список как:

 public enum MyEnum { LITERAL1(String.class), LITERAL2(Integer.class), LITERAL3(Object.class); private Class< ?> clazz; private MyEnum(Class< ?> clazz) { this.clazz = clazz; } ... } 

Потому что ты не можешь. Шутки в сторону. Это можно добавить к спецификации языка. Этого не было. Это добавит некоторую сложность. Это преимущество для стоимости означает, что это не является первоочередной задачей.

Обновление: в настоящее время добавляется к языку в JEP 301: Enhanced Enums .

В ENUM есть другие методы, которые бы не сработали. Что MyEnum.values() ?

Что относительно MyEnum.valueOf(String name) ?

Для valueOf, если вы думаете, что компилятор может сделать общий метод, например

public static MyEnum valueOf (имя строки);

для того, чтобы называть его как MyEnum myStringEnum = MyEnum.value("some string property") , это тоже не сработало. Например, что, если вы вызываете MyEnum myIntEnum = MyEnum.value("some string property") ? Невозможно реализовать этот метод для правильной работы, например, для исключения или возврата null, когда вы вызываете его как MyEnum.value("some double property") из-за стирания типа.

Честно говоря, это похоже на большее решение в поисках проблемы, чем что-либо.

Вся цель java enum состоит в том, чтобы моделировать перечисление экземпляров типа, которые разделяют сходные свойства таким образом, чтобы обеспечить согласованность и богатство, превышающее сопоставимые представления String или Integer.

Возьмем пример enums текстовой книги. Это не очень полезно или непротиворечиво:

 public enum Planet{ Earth, Venus, Mars ...etc. } 

Почему я хочу, чтобы мои разные планеты имели разные преобразования общего типа? Какую проблему он решает? Оправдывает ли это усложнение семантики языка? Если мне это нужно, это перечисление – лучший инструмент для его достижения?

Кроме того, как вы будете управлять сложными преобразованиями?

например

 public enum BadIdea{ INSTANCE1, INSTANCE2; } 

Его достаточно просто с String Integer чтобы указать имя или порядковый номер. Но дженерики позволят вам поставлять любой тип. Как бы вы MyComplexClass с преобразованием в MyComplexClass ? Теперь вы удаляете две конструкции, заставляя компилятор знать, что существует ограниченное подмножество типов, которое может быть предоставлено общим enumsм и вводит дополнительную путаницу в концепцию (Generics), которая уже, похоже, ускользнула от многих программистов.

Becumue «enum» – это аббревиатура для enums. Это просто набор именованных констант, которые стоят вместо порядковых номеров, чтобы сделать код более читаемым.

Я не понимаю, что может означать предполагаемое значение константы, параметризованной по типу.

Я думаю, потому что в основном Enums не может быть инстансом

Где бы вы установили class T, если JVM разрешил вам это сделать?

Перечисление – это данные, которые должны быть всегда одинаковыми или, по крайней мере, что они не будут изменяться динамически.

новый MyEnum <> ()?

Тем не менее может быть полезным следующий подход

 public enum MyEnum{ LITERAL1("s"), LITERAL2("a"), LITERAL3(2); private Object o; private MyEnum(Object o) { this.o = o; } public Object getO() { return o; } public void setO(Object o) { this.o = o; } } 
  • Исключение Null Pointer при использовании Java Compiler API
  • Каков наилучший способ рекурсивного преобразования строки в Java?
  • Как избежать Java-кода в JSP-файлах?
  • Какая хорошая Java, curses-like, библиотека для терминальных приложений?
  • Чтение Eclipse stdin (System.in) из файла
  • В Java можно проверить, является ли String только ASCII?
  • Как написать файл UTF-8 с Java?
  • Как перейти к новому окну браузера, который открывается после нажатия кнопки?
  • WebDriver: проверьте, существует ли элемент?
  • Regex Именованные группы в Java
  • Можете ли вы порекомендовать библиотеку Java для чтения (и, возможно, записи) файлов CSV?
  • Interesting Posts

    Проблема с разделом с установкой Windows 8.1

    Как я могу ограничить GenericForeignKey Django списком моделей?

    Как обновить MediaStore на Android?

    Динамическое создание вкладок с графиками в блестящем состоянии без повторного создания существующих вкладок

    Создание инициализатора массива из параметров кортежа или вариационного шаблона

    Найти записи MongoDB, где поле массива не пустое

    Просмотры в отдельных assemblyх в ASP.NET MVC

    обновление игровых сервисов Google в эмуляторе

    KDE Konsole для выбора текста и копирования в буфер обмена

    STL-вектор и безопасность streamов

    Почему мой планшет HP Touchpad показывает, что он не получает достаточную энергию?

    Как использовать GhostScript для Windows для восстановления поврежденных файлов PDF

    Отключение жестов касания в Windows 8.1

    Как конвертировать DP, PX, SP между собой, особенно DP и SP?

    Как выполнить rsync большой файл с минимальными затратами на процессор и пропускную способность?

    Давайте будем гением компьютера.