Что-то, стоило начаться праздникам, как стал писать про работу. Наверно тянет к ней неумолимо. Ну да ладно.
В языке программирования Java пофиксили большинство проблем С++, за что разработчикам честь и хвала. Особая хвала им и за то, что на достигнутом они не остановились: исправления продолжаются, а улучшения придумываются.
В плане борьбы за качество и удобство сообщаю о реальном просчёте в языке Java. А именно многозначительности оператора «==». Выражается многозначительность в том, что для простых типов этот оператор сравнивает значения переменных, а для ссылок он сравнивает ссылки, а не значения. Что приводит к ошибкам вида:
boolean isBlin(String str){
String strBlin = "Blin";
return strBlin == str;
}
Ясен пень, в данном случае программист был уверен, что сравнивает сами строки. Но сравнил при этом ссылки на строки. Функция в результате на все вопросы будет отвечать false. А среда разработки и компилятор не выдадут даже предупреждения. Что является реальной засадой.
Вообще идея придать операторам контекстный смысл изначально порочна. В С++, например, есть перегрузка операторов. С одной стороны, это даёт возможность реализовать, например, комплексные числа и производить над ними операции, пользуясь простыми операторами. С другой – этой возможностью многие злостно злоупотребляют. В том числе, переопределяя оператор «&», например. Программа от всего этого не прибавляет удобочитаемости, но приобретает нетривиальное поведение. Сначала такое кажется удобным, но идёт время, глубинный смысл перегрузок забывается и начинают вылезать неожиданные эффекты, что побуждает к долгому коллективному отлавливанию ошибок и необходимости просматривать исходники давно написанных библиотек.
В Java перегрузки операторов нет, поэтому нет проблем с ними. Заодно нет и их удобства. Но странность и неоднозначность двойного равно почему-то оставлена.
Причём, выбор в разрешении неоднозначности сделан неожиданный – сравниваются ссылки. По уму следовало бы ввести отдельный оператор для сравнения именно ссылок. А двойное равно для них вообще запретить. Или, что гораздо лучше, сделать двойное равно перегружаемым. По умолчанию, например, такой оператор производит побайтовое сравнение, но его можно переопределить. Оное же имело мы смысл сделать для операторов «+», «-» и прочих. За тем исключением, что по умолчанию они для объектов не компилируются вообще – то есть, их использование требует явного переопределения. Вот тогда было бы удобно и надёжно. Сейчас же наличиствует суровый соблазн все переменные сравнивать одинаковым образом.
void f(int x, String s){
...много кода...
if (x == my.x && s == my.s) { // Типа засада
...
}
}
Очень, скажу я вам, жаль. Осмысленная перегрузка операторов – вещь неплохая. Круто было бы её в Java вставить. И особенно хорошо было бы встроить её вместе с имплементацией ключевого слова const. Тогда арифметические операторы можно было бы захардкодить в язык в виде константных, что позволило бы избежать адских злоупотреблений при их переопределении.
Следует отметить, что проблема с неоднозначностью операторов присутствует и в С++, так что Java данную проблему успешно унаследовал.
К сожалению, изменить смысл оператора «==» и сохранить при этом совместимость с предыдущими версиями Java не удастся. То есть, эта проблема останется с нами навсегда. Но есть надежда, что хотя бы при имплементации перегрузки операторов введут особый оператор для сравнения объектов по значению. Не фонтан, но лучше, чем есть.