Что такое Reified Generics? Как они решают проблемы стирания типа и почему их нельзя добавить без серьезных изменений? - PullRequest
63 голосов
/ 19 мая 2009

Я прочитал блог Нила Гафтера на эту тему и до сих пор неясен по ряду вопросов.

Почему невозможно создать реализации API коллекций, которые сохраняют информацию о типе, учитывая текущее состояние Java, JVM и API существующих коллекций? Разве они не могут заменить существующие реализации в будущей версии Java таким образом, чтобы была сохранена обратная совместимость?

Как пример:

List<T> list = REIList<T>(T.Class);

Где REIList выглядит примерно так:

public REIList<T>() implements List {
  private Object o;
  private Class klass;

  public REIList(Object o) {
    this.o = o;
    klass = o.getClass();
  }
... the rest of the list implementation ...

А методы используют Object o и Class klass для получения информации о типе.

Почему для сохранения общей информации о классе требуются языковые изменения, а не просто изменение реализации JVM?

Что я не понимаю?

Ответы [ 4 ]

33 голосов
/ 19 мая 2009

Суть в том, что в обобщенных обобщенных типах есть поддержка в компиляторе для сохранения информации о типах, в то время как в обобщенных типах нет. AFAIK, весь смысл того, чтобы в первую очередь было удаление типа, состояло в том, чтобы обеспечить обратную совместимость (например, JVM с более низкой версией могут все еще понимать универсальные классы).

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

19 голосов
/ 27 января 2011

Вопреки мнению большинства разработчиков Java, можно хранить информацию о типе во время компиляции и извлекать эту информацию во время выполнения, несмотря на то, что она очень ограничена. Другими словами: Java предоставляет расширенные дженерики очень ограниченным образом .

Относительно типа стирания

Обратите внимание, что во время компиляции у компилятора имеется полная информация о типе, но эта информация намеренно отбрасывается в общем при генерировании двоичного кода в процессе, известном как стирание типа . Это делается из-за проблем совместимости: целью разработчиков языка было обеспечение полной совместимости исходного кода и полной двоичного кода между версиями платформы. Если бы он был реализован по-другому, вам пришлось бы перекомпилировать устаревшие приложения при переходе на более новые версии платформы. Таким образом, все сигнатуры методов сохраняются (совместимость с исходным кодом), и вам не нужно ничего перекомпилировать (двоичная совместимость).

Относительно улучшенных обобщений в Java

Если вам нужно хранить информацию о типе во время компиляции, вам нужно использовать анонимные классы. Дело в том, что в особом случае анонимных классов можно получить полную информацию о типе во время компиляции, что, другими словами, означает: reified generics.

Я написал статью на эту тему:

http://rgomes -info.blogspot.co.uk / 2013/12 / с использованием-typetokens к извлечению-generic.html

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

Пример кода

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

12 голосов
/ 19 мая 2009

IIRC (и на основе ссылки), дженерики Java являются просто синтаксическим сахаром для существующей техники использования коллекции объектов и приведения назад и вперед. Использование обобщений Java безопаснее и проще, поскольку компилятор может выполнить проверку, чтобы убедиться, что вы поддерживаете безопасность типа compile . Время выполнения, однако, является совершенно другой проблемой.

.NET-дженерики, с другой стороны, фактически создают новые типы - List<String> в C # отличается от типа List<Int>. В Java под чехлами они одно и то же - List<Object>. Это означает, что если у вас есть один из них, вы не можете смотреть на них во время выполнения и видеть то, что они были объявлены - только то, что они есть сейчас.

Усовершенствованные дженерики изменили бы это, предоставив разработчикам Java те же возможности, которые существуют сейчас в .NET.

4 голосов
/ 19 мая 2009

Я не специалист по этому вопросу, но, насколько я понимаю, информация о типе теряется во время компиляции. В отличие от C ++, Java не использует систему шаблонов, безопасность типов полностью достигается с помощью компилятора. Во время выполнения список на самом деле всегда является списком.

Итак, я предполагаю, что изменение спецификации языка требуется из-за того, что информация о типе недоступна для JVM , поскольку ее там нет .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...