Перегрузка операторов в Java
Насколько я знаю в java, я знаю, что на языке Java нет перегрузки оператора.
Итак, почему этот код дважды печатает "true"?
String s1 = "abc";
String s2 = "abc";
System.out.println(s1==s2);
Integer i1 = 1;
Integer i2 = 1;
System.out.println(i1==i2);
Ответы
Ответ 1
==
для ссылочных типов сравнивает ссылки; ==
для примитивных типов сравнивает значения. В случае вашего первого примера, две ссылки на объекты оказываются одинаковыми из-за концепции, известной как пул строк. Следовательно, в данном случае два true
. Еще один фрагмент кода, который вы можете попробовать:
String s1 = "abc";
String s2 = new String("abc");
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
Как вы, должно быть, уже опробовали; он печатает false
, а затем true
. Причина этого в том, что использование ключевого слова new
приводит к созданию полностью новой строки, даже если строковый объект с таким же содержимым уже существует в пуле строк. В этом случае s1
теперь указывает на интернированную строку с содержимым "abc" (или на строку в пуле строк), тогда как s2
теперь указывает на совершенно новый объект строки (опять же с содержимым "abc" ), Следовательно, false
в первом заявлении печати.
Во втором заявлении печати мы делаем сравнение содержимого объекта String, а не его ссылки, которое должно печатать true
.
Это одна из самых распространенных ошибок, допущенных новичками языка Java; они используют ==
для логического сравнения, когда это фактически приводит к сравнению сравнения. Прочтите ссылку, размещенную в одном из ответов здесь, для получения более подробной информации о пуле объединения строк. В связанной заметке класс String "переопределяет" метод equals
класса Object
для обеспечения логического сравнения. Если класс, который вы пишете, не обеспечивает логическую реализацию метода equals
, не имеет значения, звоните ли вы equals
или используете оператор ==
; результат будет таким же, как сравнение ссылок.
Для более глубокого представления о равенстве прочитайте статью Брайана; отличный читать.
Ответ 2
Не совсем верно, что в Java нет перегрузки оператора. Просто не существует какой-либо пользовательской перегрузки оператора. Например, существует некоторая перегрузка оператора с помощью +
, которая добавляется как дополнение, так и как String
-конкатенация. Это определяется языком и не может быть изменено разработчиком.
Ваш пример, однако, не использует перегрузку оператора в любом месте. ==
в ссылочных типах всегда делает одно и то же: return true
, когда левая и правая стороны относятся к точному тем же объекту.
В этом случае s1
и s2
ссылаются на один и тот же объект и i1
и i2
ссылаются на тот же объект.
-
s1
и s2
ссылаются на один и тот же интернированный String
, потому что строковые литералы гарантированно будут интернированы.
-
i1
и i2
ссылаются на один и тот же кешированный Integer
, потому что авто-бокс будет повторно использовать фиксированный пул объектов Integer
для общих числовых значений.
Ответ 3
Вы не можете перегружать операторы, но это не значит, что он не встроен в JVM. Очевидным примером счетчика является оператор плюс и различное поведение для строк и чисел.
Ответ 4
Это происходит потому, что "Все литералы и строковые константные выражения интернированы".
См. http://download.oracle.com/javase/6/docs/api/java/lang/String.html#intern%28%29
Ответ 5
Это замечательно читать Почему Java не предлагает перегрузку оператора?.
Ответ 6
Ваш код показывает, что он был связан с перегрузкой оператора, но это не так.
Строковый оператор "==", похоже, "перекрыт" с помощью оператора "==" Integer. Как упоминал в предыдущем ответе @Sanjay T. Sharma, в Java существуют "ссылочные" типы и "примитивные" типы, которые обрабатывают разные операторы "==".
Строки в Java являются "ссылочными" типами, а целые являются "примитивными" типами. Если у вас есть указатели и объекты на других языках, вы обнаружите, что в Java строковые переменные действительно являются указателем на объект, а использование оператора "==" ведет себя по-разному.