Developer Tales or everything about everything

26Май/124

Сравнение строк в Java

Разработчики, погружающиеся в мир Java иногда впадают в недоумение, когда читают в книжке или на форумах что-нибудь подобное:

Никогда не используйте оператор сравнения (==) для сравнения строковых переменных. Используйте String.equals()

"Что серьезно?!" - спросите вы. Да, это действиетельно так. Пояснение ниже.

Java - объектно-ориентированный язык до мозга костей. Что произойдет если сравнить объект с целым числом или строкой? Ничего хорошего.

Однако, Java предоставляет нам решение на этот случай - автобоксинг (англ. autoboxing). Это механизм автоматического "оборачивания" скалярных типов данных в объекты.

То есть, Java там, где это нужно, самостоятельно оборачивает целочисленные типы, типы с плавающей точкой и пр. в объекты. И это работает: при сравнении объектного типа Integer со скалярным int не будет никакой разницы, как если бы сравнивали два обычных числа.

Другое дело - строковые константы. Строковая константа изначально является объектом типа String. Что же тут плохого? Проблема заключается в том, что Java поддерживает неявное сравнение объектов. Например:

На самом деле, Java сравнивает не объекты, а указатели на них. Если они совпадают, значит объекты эквивалентны.

Что же происходит, когда сравнивается строка со строкой?

Почему false? Потому что Java сравнивает объекты, а не строковые значения, которые хранятся "внутри" этих объектов:

Сравнение строковых объектов в Java

Сравнение строковых объектов в Java

Решение? Элементарно:

В этих случаях происходит явный вызов методов сравнения строк ("foo" & "bar") внутри строковых контейнеров (объекты типа String).

Да, это немного неудобно и может породить малозаметные, но очень серьезные ошибки. Но такова уж природа Java - ООП ради ООП

 

Просмотров: 11080
Комментарии (4) Пинги (0)
  1. Как ни странно, сравнение, в случае строк, присвоенных через "=" возвращает true. Т.к. автоматически присваивается ссылка на тот же участок памяти, чтобы не тратить её на одинаковые массивы. Но если прописать присвоение через new String() - тогда уже (foo == bar) вернет false.

    • Да, компилятор соптимизирует константные значения. Строки, "присвоенные через =", понятие недетерминированное. В примере ниже абсолютно нормально инициализируется строка, но результаты совсем не те, которые стоило бы ожидать (если не знать принципов сравнения объектов в Java).

      public class Test
      {
      public static String rnd;

      public static String getS()
      {
      if (rnd == null)
      {
      rnd = String.valueOf((int)(Math.random() * 100));
      }

      String s = "1" + rnd;
      return s;
      }

      public static void main(String[] args)
      {
      String s1 = getS();
      String s2 = getS();
      System.out.println(s1 == s2);
      System.out.println(s1);
      System.out.println(s2);
      }
      }

  2. Если один из операндов в выражении содержит строку, то другие операнды также должны быть строками. Поэтому Java сама может привести переменные к строковому представлению, даже если они не являются строками.

    • Это Вы к чему? Если сравниваются две строки с помощью оператора ==, то Java будет сравнивать ссылки, а не сами значения строк. Именно поэтому в Java есть метод equals и equalsIgnoreCase специально реализованный в классе String.


Leave a comment


4 × = двадцать

http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_bye.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_good.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_negative.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_scratch.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_wacko.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_yahoo.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_cool.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_heart.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_rose.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_smile.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_whistle3.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_yes.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_cry.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_mail.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_sad.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_unsure.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_wink.gif 
 

Trackbacks are disabled.