List<String> stringList = new ArrayList<>();
List rawList = stringList;
rawList.add(10);
Таким образом, приведенный выше код компилируется с предупреждением, но прерывается во время выполнения. Это было представлено как один из случаев, когда удаление стирания типов в Java имело бы положительный эффект (хотя я понимаю, что в целом мы никогда его не удалим).
Меня смущает то, что мы выполняем проверку типа до того, как произойдет стирание типа. Так как же решение не выполнять какой-либо последующий этап процесса компиляции поможет нам обнаружить проблемы, которые мы раньше не могли обнаружить?
Случай 1:
Случай 2:
Но если это возможно, почему бы просто не сделать вариант 3:
Надеюсь, понятно то, чего я не понимаю.
Если вы хотите предотвратить эту ошибку во время компиляции, проблема не в стирании типа; он использует необработанные типы. Компилятор предупреждает вас об использовании необработанных типов, но не запрещает вам игнорировать предупреждения.
Вот что я бы тоже сказал. Если мы удалим стирание типов, но сохраним необработанные типы, эта проблема сохранится? Этот пример по сути не имеет ничего общего со стиранием типа. Единственная ошибка компиляции, которую мы исправляем, — это перегруженный метод, в котором разные типы списков сворачиваются в одну и ту же сигнатуру метода. Было бы это правильно?
Наличие этих типов в дженериках — очень полезная функция языка и замечательная вещь, о которой знает компилятор. Если ваш код работает только тогда, когда вы удаляете типы, он почти наверняка выдаст исключение во время выполнения, поэтому вы просто создали проблему позже.
«Удалено стирание типов, но сохранены необработанные типы» не имеет особого смысла. Что тогда будет означать необработанный тип? Вы можете придумать любое значение, которое оно имеет, чтобы удовлетворить себя.
но они уже это делают. необработанные типы означают все, что вы хотите, и именно поэтому у нас возникают эти проблемы.
Но, кажется, я понимаю — нам нужны сырые типы из-за старого кода. чтобы их учесть, нам нужно стирание типов, а пример в ФП представляет собой проблему необработанных типов и, следовательно, косвенно стирания типов.
что вы подразумеваете под перерывами в «приведенном выше коде компилируется с предупреждением, но прерывается во время выполнения»? Опубликованный код, если его поместить внутрь метода (или в jshell), будет работать без проблем — в конечном итоге он выдаст исключение ClassCastException, если будет получен добавленный элемент из stringList
в виде строки (например, String s = stringList.get(0)
или System.out.println(stringList.get(0))
).
Меня смущает то, что мы выполняем проверку типов ДО того, как произойдет стирание типа...
В этом конкретном примере вы используете необработанные типы, поэтому проверка типа для параметра типа также не производится.
До того, как в Java были добавлены дженерики, в коде не было параметров типа, но люди все еще хотят, чтобы код того времени компилировался, поэтому некоторые части проверки типов приходится отключать для необработанных типов.
Без стирания типов не было бы и необработанных типов, которые представляют собой стертые формы параметризованных типов, поэтому этот вопрос является спорным.
Вы говорите об «удалении стирания типов», как будто стирание типов — это какая-то дополнительная функция языка. Это не. Компилятор просто делает то, что он всегда делал еще до появления дженериков - не выдает информацию об универсальном типе локальных переменных в файл класса, поскольку JVM не поддерживает универсальные типы.
Что изменилось бы, если бы JVM действительно поддерживала универсальные типы, так это то, что исключения могли бы создаваться во время выполнения гораздо раньше. Предположим, вы приводите некоторую переменную типа Object
к List<String>
. Предположим, что переменная действительно хранит List<Integer>
. JVM может проверить, что приведение недопустимо во время выполнения, и выдать исключение прямо там, где находится приведение. На самом деле JVM не может этого сделать и выдаст исключение только тогда, когда вы попытаетесь получить String
из этого List<Integer>
, что потенциально может произойти намного позже.
Именно поэтому предупреждения компиляции так важны. Очень часто предупреждение компиляции означает: «Это может сломаться во время выполнения — действуйте на свой страх и риск».