Почему Java (но не .NET) не может использовать дженерики без необработанных типов/удаления типов?

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

Обобщения также были введены в .NET в какой-то момент в будущем, но эта функция была реализована таким образом, что не зависит от необработанных типов или стирания типов (а если и зависит, то таким образом, который является прозрачным для пользователя). ). Таким образом, существующие API остались без изменений (например, код в пространстве имен System.Collections) и были введены новые универсальные API (например, код в пространстве имен System.Collections.Generic).

Так почему же дженерики Java, в отличие от дженериков .NET, требуют необработанных типов/стирания типов?


person J Smith    schedule 12.07.2013    source источник


Ответы (2)


.Net представила дженерики, изменив язык байт-кода, виртуальную машину и JITter для распознавания универсальных типов.
Это был огромный объем работы, который занял около двух лет.

Java представила дженерики исключительно как функцию времени компиляции с небольшими изменениями во время выполнения (новые метаданные и API отражения).
Это была гораздо более простая задача, и она поддерживала обратную совместимость со старыми средами выполнения, но работать с ней было гораздо сложнее. с.

person SLaks    schedule 12.07.2013
comment
Кроме того, .Net заменил существующие контейнеры универсальными версиями в другом пространстве имен. Код, который хочет их использовать, должен быть портирован почти весь сразу. Путь Java позволил им просто сделать существующие контейнеры универсальными, поэтому перенос по частям означает только случайное приведение типов и подавление предупреждений. - person Sebastian Redl; 12.07.2013
comment
@SebastianRedl: это в основном расширение дженериков, являющееся функцией только во время компиляции. - person SLaks; 12.07.2013
comment
Хотя .NET изменил язык байт-кода, я не думаю, что Java обязательно должен был сделать это, чтобы позволить универсальным объектам знать свой тип. Я бы подумал, что каждый экземпляр универсального объекта мог бы содержать одно или несколько полей, сгенерированных компилятором, обозначающих комбинацию типов, с которыми был создан экземпляр, и чтобы компилятор сгенерировал код, который проверял бы такие поля, когда это уместно. Я думаю, что более серьезной проблемой было бы то, что если бы ArrayList<String> был реализован как любой другой тип, кроме ArrayList... - person supercat; 22.07.2013
comment
... единственный способ для кода, который предполагает использовать неуниверсальный ArrayList, для хранения ссылки на ту же коллекцию, что и код, который предполагает использовать ArrayList<String>, - это ArrayList<String> быть оболочкой вокруг ArrayList. Такая вещь могла бы работать семантически, но если бы язык байт-кода не был изменен, чтобы облегчить это, некоторые вещи были бы довольно медленными (например, если бы не было добавлено поле к ArrayList, преобразование ссылки ArrayList в ссылку ArrayList<String> потребовало бы поиска ее в статическом WeakDictionary). - person supercat; 22.07.2013

Sun особенно стремилась гарантировать обратную совместимость, поскольку у нее была большая устоявшаяся база программного обеспечения Java. Для этого они посчитали, что минимум изменений в JVM лучше всего. Оглядываясь назад, кажется, что это не было лучшим решением в долгосрочной перспективе, поскольку это означает, что JVM на самом деле не понимает дженериков и не может оптимизировать многие избыточные проверки классов.

Для сравнения, Oracle менее неохотно меняла JVM и сталкивалась с более серьезными и общедоступными ошибками, особенно. делать с безопасностью. (Они не означают одно и то же, но одно может привести к другому). Тем не менее, Oracle добавила в JVM только одну инструкцию, которую Java даже не использует, тогда как Sun не добавила ни одной, так что на самом деле это относительно. ;)

С другой стороны, у Microsoft была меньшая кодовая база для C#, и клиенты больше привыкли к значительным, даже критическим изменениям между основными версиями. Это означает больше боли в краткосрочной перспективе, но может быть лучшим выбором в долгосрочной перспективе. У вас меньше проблем, которые по историческим причинам остались.

Короче разница не техническая, она больше политическая и историческая.

person Peter Lawrey    schedule 12.07.2013
comment
Разница чрезвычайно техническая. - person SLaks; 12.07.2013