Comments 17
Я думал, что речь пойдет про баг в самой Java, а вы тут какие-то сферические примеры придумываете...
Не скажите, пример с
Object x = 1000;
List<?> list = new ArrayList<>();
list.remove(x);
вполне себе жизненный, по меньшей мере один раз я столкнулся с плавающей ошибкой при наличии List<Integer>
и вызова на нём метода remove()
.
Как создатели пошли на этот хак, особенно учитывая общую многословность Java, для меня загадка.
Тут нужно помнить, что грабли кроются в автоматическом разворачивании/заворачивании Integer
-a и int
-а, но так было не всегда. До 5 явы int
нужно было явно заворачивать в Integer
и наоборот.
Опять же, сами по себе методы List.remove(Object)
и List.remove(int)
, ИМХО, довольно логичны в контексте других методов интерфейса "список". Просто именно с int
-ом / Integer
-ом получилась бяка.
Кстати, про баги в самой яве: в заметке же была ссылка на эту статью http://wouter.coekaerts.be/2018/java-type-system-broken
Статья огонь, читал не отрываясь!
Умеет ли "Идея" распознавать подобный код с плавающими ошибками?
Про метод-референс мы говорим, что а-та-та будет:
Ну сравнение c new Integer()
понятно что подозрительное:
x = (Integer)null
— дело святое (конечно, варнинг исчезает, если тип Object):
Кое-что из остального поддержать можно, но не факт, что нужно...
Проверил,
var x = 1.0;
System.out.println(String.valueOf(false ? x : 100000000000L).substring(12) + "Ok");
определяется на ура. А то я уж было собрался расчехлять задачесоздатель ;)
А, кстати да. Я и забыл, что я сам это сделал.
List.remove тоже поддержал (добавил требование, что индекс должен быть от 0 до длины списка), хотя здесь простой пример, всё известно заранее. Не факт, что в реальной жизни пригодится.
Неожиданно, кстати, обнаружилась польза от контракта для remove — подсветилось res.remove(res.size())
. Видимо, никогда не выполнялась эта ветка.
wouter.coekaerts.be/2018/java-type-system-broken
Тип T выводится как StringBuilder, но в данном коде компилятор не обязан вставлять в байткод проверку типа в точке вызова. Ему достаточно, что StringBuilder можно присвоить в Object, а значит, всё хорошо.
Все носятся с null'ом — типа ошибка на миллион долларов… Реальная ошибка на миллион это реализация дженериков в Java 5… Эх, Мартин Мартин…
Вот интересно, кто то смог бы реализовать дженерики в Java по другому? (не создавая другой язык для jvm)
Заменить Object на var: что может пойти не так?