среда, 6 марта 2013 г.

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

Очень много ошибок возникает от того, что мы забываем, что строки – это объекты, а не примитивы. Поэтому они и ведут себя как объекты. И даже тип данных String пишется с большой буквы, как пишутся и другие объектные типы в отличие от примитивных типов (boolean, char, byte, short, int, long, float, double).

Замечу, что примитивные типы данных имеют своих дублёров в виде классов-обёрток, которые представляют эти типы, как объекты, снабжая их необходимыми методами. Поскольку такие типы являются объектами, они и пишутся с большой буквы (Boolean, Character, Byte, Short, Integer, Long, Float, Double).

Итак, как же правильно сравнивать строки? Изначально хочется написать такое:
if (sting1 == string2) {} 
Но поскольку строки — это объекты, а не примитивы, то вышеприведённой строкой мы сравниваем содержимое ссылок на строки, то есть адреса, по которым они располагаются в памяти. А так как два объекта не могут располагаться по одному и тому же адресу, то такое условие всегда будет возвращать false.

Чтобы сравнить строки, надо использовать метод equals() одной из сравниваемых строк:
if (sting1.equals(string2)) {} 
Следует обязательно использовать метод той строки, которая инициализирована реальным адресом, а не нулевым указателем, поскольку при вызове метода несуществующего объекта произойдёт исключение NullPointerExeption. Проверка на существование строки осуществляется так:
if (sting1 == null) {} 
То есть, мы проверяем, имеется ли в данной ссылке какой-нибудь реальный адрес, или она инициализирована значением null. Такую проверку надо обязательно производить при получении данных из полей интерфейса, файлов настроек, баз данных и пр., поскольку там не всегда могут оказаться нужные вам данные.

Кроме проверки наличия самого строкового объекта можно осуществлять также проверку наличия содержимого в этом объекте. Такая проверка может осуществляться несколькими способами:
if (string1.length() == 0) {} 
if (string1.isEmpty()) {} 
if (string1.equals("")){} 
Первый вариант самый предпочтительный — просто проверяется длина строки в объекте строки. Можно добавить к проверке удаление начальных и конечных пробелов: (string1.trim().length() == 0).

Второй вариант возможен только начиная с версии API 9 (Android 2.3), но, по сути, это тот же первый вариант, записанный более наглядно.

Третий вариант самый плохой. Такая конструкция работает медленнее остальных, потому что в ней создаётся дополнительный объект пустой строки "", с содержимым которого и производится сравнение.


Полезный пример

Часто требуется одновременная проверка строки на существование и на пустоту. Для этого можно использовать следующий метод:
public static boolean isZero(final String string) 
{ 
    return (string == null) || (string.trim().length() == 0); 
} 

Неизменяемость объекта строки

Замечу, что создание нового строкового объекта происходит всякий раз, когда мы присваиваем строку переменной:
String string1 = "Строка"; 
Объект строки является неизменяемым, и при попытке его изменить просто создаётся новый объект с новым значением:
String string1 = "Строка"; 
string1 = string1 + "Дополнительная строка"; 
или
String string1 = "Строка"; 
string1 = "Другая строка"; 
После выполнения этих действий в обоих случаях string1 будет указывать на совсем другую область памяти (на другой объект), чем он указывал до этого в первых строчках примеров.

Комментариев нет:

Отправить комментарий