2014-02-04 3 views
1

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

+4

Обратная совместимость. Старый код, который не использует generics, должен быть совместим с новым кодом, который делает, а старые JVM не понимают общий байт-код. – user2357112

+0

@ user2357112 это правильно, отправьте его как ответ, а не комментарий. – Xabster

+0

[Тип Erasure] (http://docs.oracle.com/javase/tutorial/java/generics/erasure.html) - «Заменить все параметры типа в родовых типах их границами или объектом, если параметры типа неограничены. Таким образом, созданный байт-код содержит только обычные классы, интерфейсы и методы ». –

ответ

4

Поскольку дженерики не были частью Java с самого начала (1.0). Если бы это было так, это было бы реализовано с использованием Reification. Цитирование Брюс Eckel на «Мышления в Java»:

В действительности, даже если программисты пишут только общий код, они будут иметь дело с необщей библиотекой, которые были написаны до Java SE5. У авторов этих библиотек никогда не может быть стимула генерировать свой код, или они могут просто потратить время на то, чтобы добраться до него. Таким образом, Java-генераторы не только должны поддерживать обратную совместимость. Существующие файлы кода и классов по-прежнему являются законными и продолжают означать, что они имели в виду до этого, но также должны поддерживать совместимость с миграцией, чтобы библиотеки могли стать универсальными в своем собственном темпе и когда библиотека становится универсальной, она не нарушает код и приложения, которые зависят от него. Поняв, что это была цель, разработчики Java и различные группы, работающие над проблемой, решили, что стирание является единственным возможным решением. Erasure позволяет эту миграцию в отношении дженериков, разрешая совместное существование не общего кода с общим кодом.

0

Как вы можете прочитать на http://www.artima.com/intv/generics2.html Первоначальная цель генерации Java была выполнена на немодифицированной виртуальной машине. Вот почему генераторы обрабатываются компилятором.

Реализация дженериков Java была основана на проекте, первоначально названном Pizza, который был сделан Мартином Одерским и другими. Пицца была переименована в GJ, затем она превратилась в JSR и в итоге была переведена на язык Java. И это конкретное предложение дженериков имело в качестве ключевой цели дизайна, что оно могло работать на немодифицированной виртуальной машине [Virtual Machine]. Разумеется, здорово, что вам не нужно изменять вашу виртуальную машину, но она также создает целую кучу странных ограничений. Ограничения не обязательно очевидны, но вы очень быстро идете: «Хм, это странно».

0

Вы должны прочитать о тире Erasure и о том, как он относится к сырым типам. Рассмотрим следующий код:

MyNode mn = new MyNode(5); 
Node n = mn;   // A raw type - compiler throws an unchecked warning 
n.setData("Hello");  // Causes a ClassCastException to be thrown. 
Integer x = mn.data; 

После типа стирания, этот код становится:

MyNode mn = new MyNode(5); 
Node n = (MyNode)mn;   // A raw type - compiler throws an unchecked warning 
n.setData("Hello"); 
Integer x = (String)mn.data; // Causes a ClassCastException to be thrown. 

Вот что происходит, когда код выполняется:

  • n.setData (» Здравствуйте"); вызывает метод setData (Object), который должен быть выполнен на объекте класса MyNode. (Класс MyNode унаследовал SetData (Object) от узла.)

  • В теле SetData (Object), поле данных объекта, на который ссылается п присваивается String.

  • Поле данных того же объекта, который ссылается через млн, может быть доступны и, как ожидается, быть целым числом (поскольку млн является MyNode, который является узлом.

  • Попытка назначить строку целым Integer вызывает ClassCastException из приведения, вставленного при назначении компилятором Java.

вы можете прочитать о типе Erasure здесь: http://docs.oracle.com/javase/tutorial/java/generics/erasure.html

Смежные вопросы