Вступление
Проще говоря, String
используется для хранения текста, то есть
последовательности символов. Наиболее часто используемый класс Java -
это String
, и при таком частом использовании разработчики Java должны
быть полностью знакомы с этим классом и его общими операциями.
Нить
String
много сказать, начиная с способов их инициализации в пул
строковых литералов , однако в этой статье мы сосредоточимся на общих
операциях, а не на самом классе.
Хотя, если вы хотите узнать больше о различных способах создания строк в Java, вам следует проверить String vs StringBuilder vs StringBuffer .
Здесь мы предполагаем, что вы знакомы с тем фактом, что String
неизменяемы , так как это очень важно знать, прежде чем обрабатывать
их. Если нет, обратитесь к ранее связанной статье, где это подробно
объясняется.
Класс String
имеет множество вспомогательных методов, которые помогают
нам обрабатывать наши текстовые данные:
- Определить длину строки
- Поиск символов и подстрок
- Сравнение строк
- Извлечение подстрок
- Изменение регистра строки
- Удаление пробелов
- Форматирование строк
- Регулярное выражение и проверка подстрок
- Замена символов и подстрок
- Разделение и соединение строк
- Создание массивов символов
- Строковое равенство
Конкатенация строк
Прежде чем мы начнем использовать какой-либо из этих методов для строк,
мы должны взглянуть на конкатенацию строк, поскольку это довольно
распространенная вещь. Начнем с оператора +
Класс String
перегружает
этот оператор и используется для объединения двух строк:
String aplusb = "a" + "b";
// The operands can be String object reference variables as well
String a = "a";
String b = "b";
aplusb = a + b;
Оператор +
работает очень медленно. String
неизменяемы, поэтому
каждый раз, когда мы хотим объединить n строк, Java должна копировать
символы из всех строк в новый объект String
Это дает нам квадратичную
(O (n ^ 2)) сложность.
Это не проблема с небольшими строками или когда мы объединяем сразу
несколько строк ( String abcd = "a" + "b" + "c" + "d";
). Java
автоматически использует StringBuilder
для объединения нескольких
строк одновременно, поэтому причиной потери производительности является
объединение в циклы. Обычно для чего-то подобного мы использовали
вышеупомянутый класс StringBuilder
Он работает как изменяемый объект String
Он обходит все копирование
при конкатенации строк и дает нам линейную (O (n)) сложность.
int n = 1000;
// Not a good idea! Gives the right result, but performs poorly.
String result = "";
for (int i = 0; i < n; i++) {
result += Integer.valueOf(i);
}
// Better, performance-friendly version.
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < n; i++) {
sb.append(i);
}
Мы также можем объединить с помощью метода concat()
String str1 = "Hello";
System.out.println(str1.concat("World"));
Выход:
Hello World
Примечание . При использовании конкатенации строк с другими типами данных они неявно преобразуются в их строковое представление:
System.out.println("2 = " + 2);
Это дает ожидаемый результат «2 = 2».
System.out.println("2 = " + 1 + 1);
В обычных обстоятельствах 1+1
, поскольку Java обрабатывает операции
справа налево. Однако на этот раз этого не произойдет - результат будет
«2 = 11». Это происходит из-за того, что называется «приоритетом
оператора».
По сути, когда встречаются два или более операторов «+» (без других операторов и скобок), Java начинается с самого левого оператора «+» и продолжается оттуда. Если мы хотим, чтобы результат снова был «2 = 2», нам нужно было бы добавить круглые скобки в соответствующее место.
System.out.println("2 = " + (1 + 1));
С другой стороны, если мы попытаемся использовать метод concat()
с
другим типом данных:
String str1 = "Hello";
System.out.println(str1.concat(53));
Нас встретят с исключением:
incompatible types: int cannot be converted to String
При использовании +
Java автоматически преобразует тип данных в
String, тогда как при использовании метода concat()
этого не
происходит.
Кстати, для всех методов, которые мы рассмотрим в этой статье, нам не нужно предоставлять ссылочную переменную, иногда для краткости проще просто использовать их в литерале:
// Instead of this...
String ourString = "this is just some string";
System.out.println(ourString.substring(5,10));
// ...we can do this:
System.out.println("this is just some string".substring(5,10));
На самом деле, любой способ хорош, но второй способ дает меньше кода.
Определить длину строки
length()
возвращает общее количество символов в нашей String
.
isEmpty()
возвращает true
или false
зависимости от того String
или нет. Это означает, что isEmpty()
возвращает true
для того же
случая, когда length()
возвращает 0.
Например:
if (s.length() == 0) // or s.isEmpty() {
System.out.println("s is empty");
}
else System.out.println("s isn't empty, it's: " + s + "\n");
Здесь мы покажем, как вы можете использовать эти методы для проверки
наличия пустой строки. Условную проверку можно также заменить на
s.isEmpty()
и она будет работать точно так же.
Поиск символов и подстрок
Поскольку String
представляет собой неизменяемую последовательность
символов, мы можем спросить, какой символ находится в какой позиции, или
найти позицию символа. Индексирование String
начинается с 0, как мы
привыкли к массивам.
charAt(int index)
возвращает значение символа по заданному индексу.
indexOf()
перегружен и поэтому имеет несколько применений:
indexOf(int ch)
возвращает первую позицию индекса, которая соответствует заданному значению символаindexOf(int ch, int fromIndex)
возвращает первый индекс, который соответствует заданному значению символа ПОСЛЕfromIndex
indexOf(String substring)
возвращает (первую) начальную позициюsubstring
вString
она была вызванаindexOf(String substring, int fromIndex)
же, что и в предыдущем методе, но поиск начинается сfromIndex
вместо 0
Все перегруженные indexOf()
возвращают -1, если индекс не был
найден.
lastIndexOf()
также перегружен и имеет эквивалентные сигнатуры метода
indexOf()
, а также возвращает -1, если соответствующий индекс не был
найден. Он ищет String
обратном направлении, если не указан
fromIndex
Индекс, переданный методу, должен быть в пределах диапазона
[0, example.length() - 1]
чтобы быть действительным. В противном
случае создается StringIndexOutOfBoundsException
.
String example = "This should be complicated enough to show some things we should show";
// Find the characters at the indexes given
System.out.println(example.charAt(0));
System.out.println(example.charAt(5));
// An StringIndexOutOfBoundsException is thrown in both these cases:
// System.out.println(example.charAt(-1));
// System.out.println(example.charAt(200));
// Find the index of characters or substrings
System.out.println(example.indexOf('s')); // returns the first occurence of 's'
System.out.println(example.indexOf('s', 4)); // the first 's' after index 4
System.out.println(example.indexOf("should")); // the index of the first "should" in our string
System.out.println(example.indexOf("should", 15)); // the index of the first "should" in our
// string _after_ index 15
// Find the last index of characters or substrings
System.out.println(example.lastIndexOf('s')); // returns the first occurence of 's' when we look backwards from the end of the string
System.out.println(example.lastIndexOf('s', 45)); // searches for 's' backwards from the position 45
System.out.println(example.lastIndexOf("should")); // returns the position at which the substring 'should' appears, looking backwards from the end of the string
System.out.println(example.lastIndexOf("should", 20)); // finds substring 'should' from position 20 backwards, and returns the position at which it begins
Это выведет следующее:
T
s
3
5
5
57
64
42
57
5
Примечание : indexOf(int ch, int fromIndex)
часто используется в
циклах, когда мы хотим что-то делать для каждого вхождения символа в
String
.
int foundAt = -1;
String example = "This should be complicated enough to show some things we should show";
while (true) {
foundAt = example.indexOf('s', foundAt + 1);
if (foundAt == -1)
break;
else {
// do something with that information
}
}
Сравнение строк
Метод compareTo()
лексикографически сравнивает нашу String
с другой.
Фактическое сравнение двух строк основано на значении Unicode каждого
символа в строке. Метод возвращает либо положительное число, либо
отрицательное число, либо 0.
Если бы все символы в нашей строке были полностью строчными (или
полностью прописными) буквами, возвращаемое значение метода
compareTo()
можно интерпретировать как «если бы возвращаемое значение
было отрицательным, моя строка была бы перед другой строкой в словаре» .
Я подчеркиваю, что буквы должны быть в одном и том же регистре, поскольку в противном случае функция может выдать неожиданный результат.
Метод compareTo()
не перебирает все символы в наших строках, он
возвращается, как только достигает конца любой из строк или как только
он находит несовпадающий символ. В этом случае функция возвращает
(значение Unicode несовпадающего символа в нашей строке) - (значение
Unicode несовпадающего символа в данной строке) .
Для всех, кому интересно - ASCII является частью Unicode. Это означает, что az и AZ находятся в том же порядке, что и в кодировке ASCII, то есть все они идут один за другим в своих соответствующих случаях. А именно, az - это коды между 97-122 и AZ 65-90 . Таким образом, значение «a» - 97, значение «b» - 98 и так далее. Таким образом, когда мы вычитаем значение Unicode для «b» из «a», мы получаем -1. Это означает, что «а» - это одна буква перед «б», что и есть.
System.out.println("a".compareTo("a"));
System.out.println("a".compareTo("b"));
System.out.println("1".compareTo("12345678"));
System.out.println("2".compareTo("12345678"));
System.out.println("abcd".compareTo("abgggggggggg"));
0
-1
-7
1
-4
В третьей строке приведенного выше кода в этом случае compareTo
возвращает разницу в длинах строк, поскольку он не обнаружил
несовпадающий символ до того, как в одной строке «закончились» символы.
И в последней строке мы видим, что -4 печатается из-за 'c' - 'g'
,
поскольку это первое обнаруженное несоответствие, а все остальное не
заботит.
Примечание . «Неожиданная» часть при использовании compareTo()
происходит, когда мы сравниваем строки с разными регистрами.
System.out.println("ORANGE".compareTo("apple"));
Мы могли бы ожидать, что метод вернет положительное значение, поскольку «яблоко» должно стоять перед «ОРАНЖЕВЫМ». Однако значение Unicode для «O» меньше, чем значение Unicode для «a».
Иногда это может быть предпочтительным поведением, но если это не так,
мы используем compareToIgnoreCase()
. Этот метод, по сути, делает то
же самое, что и compareTo()
, он просто делает вид, что все в одном
регистре, и дает нам «правильный» порядок словаря.
Примечание : compareTo()
и compareToIgnoreCase()
часто
используются, когда мы создаем Comparator
для настраиваемого класса.
Например, предположим, что у нас есть Person
подобный следующему:
class Person {
String firstName;
String lastName;
// ...
}
Теперь предположим, что у нас есть список ArrayList
называемый
«people» из множества Person
, без определенного порядка. Мы хотели бы
отсортировать этот ArrayList
так, чтобы они были упорядочены в
лексикографическом порядке на основе их фамилий, и если у людей
одинаковая фамилия, мы хотели бы отсортировать их на основе их имени.
Comparator<Person> personComparator = new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
if (p1.firstName.compareTo(p2.firstName) != 0) {
return p1.firstName.compareTo(p2.firstName);
}
else return p1.lastName.compareTo(p2.lastName);
}
};
Collections.sort(people, personComparator);
Извлечение подстрок
«Подстрока» - это подмножество (или часть) другой строки. Метод
substring()
возвращает новую строку, которая является подстрокой
строки, в которой мы используем метод.
Другими словами, если нам нужна новая строка, содержащая первые три
символа нашей строки, мы должны использовать ourString.substring(0, 3)
.
У substring()
есть два варианта:
substring(int startIndex)
возвращаетString
содержащую все символы отstartIndex
(включительно) до конца нашейString
. Он ведет себя так же, какsubstring(int startIndex, ourString.length())
.substring(int startIndex, int endIndex)
возвращаетString
содержащую все символы отstartIndex
(включительно) доendIndex
(исключая, т.е. символ вendIndex
не возвращается)
Примечание . Указанные индексы должны по-прежнему находиться в
интервале [0, ourString.length()-1]
. Java, в отличие от некоторых
других языков, НЕ поддерживает отрицательные индексы в методе
substring()
Java выдаст StringIndexOutOfBoundsException
по любой из
следующих причин:
startIndex
отрицательныйendIndex
больше, чем длина нашего объектаString
startIndex
большеendIndex
Хотя в документации прямо не говорится, что «отрицательные значения
вообще не допускаются» (у кого-то может быть привычка давать -1 в
качестве endIndex
из других языков программирования), это правило
может быть выведено из того факта, что startIndex
не может быть
отрицательным, и этот endIndex
должен быть больше startIndex
.
Однако Java просто заставляет нас сделать дополнительный шаг и написать
ourString.length() - someNumber
как endIndex
вместо просто
- someNumber
.
String ourString = "abcdef";
System.out.println(ourString.substring(0,3));
System.out.println(ourString.substring(2));
System.out.println(ourString.substring(1,3));
// If we want the last few characters
System.out.println(ourString.substring(ourString.length()-3));
abc
cdef
bc
def
Изменение регистра строки
Эти два простых метода используются для изменения регистра символов в строке.
toLowerCase()
: заменяет все символы верхнего регистра на нижний регистр (игнорирует все остальное)toUpperCase()
: заменяет все символы нижнего регистра на верхний регистр (игнорирует все остальное)
|
|
String ourString = "ThInK oF a ClEvEr StRiNg";
System.out.println(ourString.toLowerCase());
System.out.println(ourString.toUpperCase());
System.out.println(ourString);
Это выведет следующее:
think of a clever string
THINK OF A CLEVER STRING
ThInK oF a ClEvEr StRiNg
Обратите внимание, что сам исходный String
не изменился.
Удаление пробелов
Этот метод возвращает копию исходного String
в котором удаляются все
начальные и конечные пробелы (пробелы, табуляции, новые строки).
String ourString = " Any non-leading and non-trailing whitespace is \n preserved ";
System.out.println(ourString.trim());
Выход:
Any non-leading and non-trailing whitespace is
preserved
trim()
часто используется при обработке пользовательского ввода,
поскольку он гарантирует, что у нас нет бесполезных пробелов, и не
изменяет строку, если мы этого не сделаем.
Очень распространенное использование trim()
с пользовательским вводом
-
проверка того, были ли введены вообще какие-либо непробельные символы:
// Usually we check for empty inputs like this: if (userinput.isEmpty()) { … } // …or the equivalent if (userinput.length() != 0) { … }
// But a better way to check would be this, which // handles cases where the user entered only // whitespace (ie " “) if (userinput.trim().isEmpty()) { … }
Форматирование строк
Метод format()
возвращает отформатированную строку с заданным форматом
и аргументами. Он используется, чтобы упростить жизнь при форматировании
сложных строк в Java. Он работает аналогично printf
в C:
public static String format(String form, Object... args)
Объявление этого метода может показаться сложным, но давайте рассмотрим его подробнее:
- Для наших целей
static
часть означает, что этот метод вызывается черезString
, а не через объект классаString
Это означает, что когда мы хотим использовать этот метод, мы должны писатьString.format(...)
а неourString.format(...)
. Мы можем вызвать метод вторым способом, ноourString
случае не будет играть роль в методе. - Символ
...
(три точки) послеObject
просто говорит о том, что здесь может быть передано переменное количество аргументов. Один, два или пятьдесят, все зависит отString form
.
Начнем с простого примера.
int a = 2;
int b = 3;
int c = 4;
int d = 1;
// %d indicates we want to print an integer
System.out.println(String.format("%d", a));
2
Метод format()
просматривает form
ищет специальные символы и
заменяет их аргументами в args
.
Специальные символы начинаются с %
. В нашем примере мы использовали
%d
, что Java понимает как «Я попробую проанализировать
предоставленный аргумент в args
как целое число».
Чуть более информативный пример того, когда может быть полезен
format()
// Very messy, hard to read, and hard to maintain
System.out.println("a = " + a + "\n" + "b = " + b + "\n" + "c = " + c + "\n" + "d = " + d + "\n");
// Much prettier
System.out.println(String.format("a = %d \nb = %d \nc = %d \nd = %d", a, b, c, d));
Как мы видим в этом примере, Java %
с аргументами. Это означает, что
когда он видит первый %d
он сопоставляет его с a
, второй %d
с b
и так далее.
format()
существует множество специальных символов, и вы можете найти
их полный список в
документации
(включая целую кучу параметров даты и времени), но чаще всего вы будете
видеть и использовать следующие:
%d
: целые типы (byte, short, int, long, BigInteger)%s
: строки%f
: для числа сfloat
в виде десятичного числа,%e
отформатирован как десятичное число в компьютеризированной научной записи, а%g
выводит то же самое, что и%f
или%e
зависимости от значения точности после округления.%b
: дляBoolean
значений. Если значение равноnull
, печатается "false".
Вообще говоря, метод format()
имеет на вид сложный синтаксис:
%[argument_index$][flags][width][.precision]conversion
argument_index
, flags
, width
и precision
являются
необязательными, как указано []
.
Точность может означать разные вещи для разных типов данных. Для чисел с плавающей запятой / двойным числом точность имеет очевидное значение: «сколько цифр я должен показать после десятичной точки». Помимо этого, точность определяет максимальное количество символов, которое будет записано на выходе.
double ourDouble = 1123.9303;
System.out.println(String.format("%f", ourDouble));
System.out.println(String.format("%.3f", ourDouble)); // specifies that we only want 3 digits after decimal point
System.out.println(String.format("%e", ourDouble));
String ourString = "what does precision do with strings?";
System.out.println(String.format("%.8s", ourString)); // prints the first 8 characters of our string
int ourInt = 123456789;
// System.out.println(String.format("%.4d", ourInt)); // precision can't be used on ints
Это выведет:
1123.930300
1123.930
1.123930e+03
what doe
Необязательная width
указывает минимальную ширину вывода.
// If our number has less than 6 digits, this will
// add extra 0s to the beginning until it does
System.out.println(String.format("%06d", 12));
// If our number has more than 6 digits, it will just print it out
System.out.println(String.format("%06d", 1234567));
// We can specify output width, with the output being aligned
// to the right if it's shorter than the given space. If it's
// longer, everything gets printed. The || are added for
// demonstration purposes only
System.out.println(String.format("|%20d|", 12));
// Or we can align the output to the left
System.out.println(String.format("|%-20d|", 12));
// We can also easily print an octal/hexadecimal value of an integer
System.out.println(String.format("Octal: %o, Hex: %x", 10, 10));
Запуск этого кода приведет к следующему:
000012
1234567
| 12|
|12 |
Octal: 12, Hex: a
Регулярное выражение и проверка подстрок
contains(CharSequence s)
возвращает true
если s
является частью
нашего String
объекта ( s
может быть String
сама или
StringBuilder
объект, или на самом деле все , что орудия
CharSequence
), в противном случае она возвращает false
.
startsWith(String prefix)
возвращает true
если наш String
буквально начинается с данного prefix
, в противном случае он
возвращает false
.
endsWith(String suffix)
возвращает true
если наш String
буквально
заканчивается заданным suffix
, в противном случае он возвращает
false
.
matches(String regex)
возвращает true
если вся наша String
соответствует заданному регулярному
выражению .
Все эти методы довольно просты. Хотя matches()
предполагает знание
регулярных выражений.
String ourString = "This string contains a contains.";
System.out.println(ourString.contains("contains"));
System.out.println(ourString.startsWith("T"));
System.out.println(ourString.endsWith(":)"));
System.out.println(ourString.matches(".*string.*"));
Эти операции выводят следующее:
true
true
false
true
Замена символов и подстрок
replace(char oldChar, char newChar)
заменяет все вхождения oldChar
на newChar
.
replace(CharSequence target, CharSequence replacement)
заменяет все
вхождения target
строки replacement
строкой (что означает, что мы
можем заменять целые подстроки, а не только символы).
replaceAll(String regex, String replacement)
заменяет все подстроки,
которые соответствуют аргументу regex
строкой replacement
replaceFirst(String regex, String replacement)
заменяет только первую
подстроку, которая соответствует аргументу regex
строкой replacement
Чтобы избежать путаницы, replace()
также заменяет ВСЕ вхождения
последовательности символов, даже если существует метод с именем
replaceAll()
. Разница в том, что replaceAll()
и replaceFirst()
используют регулярное выражение для поиска последовательностей символов,
которые необходимо заменить.
String ourString = "We really don't like the letter e here";
System.out.println(ourString.replace('e', 'a'));
System.out.println(ourString.replace("here", "there"));
System.out.println(ourString.replaceAll("e(r+)", "a"));
System.out.println(ourString.replaceFirst("e(r+)", "a"));
Wa raally don't lika tha lattar a hara
We really don't like the letter e there
We really don't like the letta e hae
We really don't like the letta e here, only the first occurrence was replaced
Разделение и соединение строк
Методы split()
и join()
- две стороны одной медали.
split(String regex)
разбивает эту строку с использованием заданного
регулярного выражения и возвращает массив символов.
split(String regex, int limit)
похож на предыдущий метод, но разбивает
только limit
количество раз.
join(CharSequence delimiter, CharSequence... elements)
с другой
стороны, возвращает String
содержащую все перечисленные нами
elements
delimiter
.
join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
-
это очень сложный способ сказать, что мы можем использовать
join()
для таких вещей, как списки, чтобы объединить все элементы вString
с использованием заданногоdelimiter
.String ourString = “apples, oranges, pears, pineapples”; String[] fruits = ourString.split(”,");
System.out.println(Arrays.toString(fruits));
// This is a great place to use the aforementioned trim() method // to remove the space at the beginning of some of the words for(int i = 0; i < fruits.length; i++) { fruits[i] = fruits[i].trim(); }
System.out.println(Arrays.toString(fruits)); // Arrays.toString() formats the output array on its own
[apples, oranges, pears, pineapples] [apples, oranges, pears, pineapples]
Имейте в виду, что split()
принимает регулярное выражение, чтобы
решить, где разделить строку, поэтому будьте осторожны при использовании
символов, которые имеют особое значение в регулярных выражениях.
Поскольку эти символы являются общими (особая проблема - ".",
Поскольку это означает "любой символ" в регулярном выражении),
безопасный способ использования split()
- с Pattern.quote(".")
гарантирует, что ничто не понимается как специальный символ регулярного
выражения.
String ourString = "apples.oranges.pears.pineapples";
// This returns then prints an empty array, since every
// character is interpreted as something to be split at
// and ignored
System.out.println(Arrays.toString(ourString.split(".")));
// The "regex safe" way of doing this would be
System.out.println(Arrays.toString(ourString.split(Pattern.quote("."))));
// Splits our string to two substrings at most,
// completely ignoring all other occurrences of "."
System.out.println(Arrays.toString(ourString.split(Pattern.quote("."), 2)));
[]
[apples, oranges, pears, pineapples]
[apples, oranges.pears.pineapples]
join()
делает полную противоположность split()
. Мы используем
join()
когда у нас есть массив / список / и т. Д. строк (или
StringBuilders
/ StringBuffers
), которые мы хотим сформировать в
одну новую String
используя какой-либо (или не используя) разделитель.
// A common use is to avoid repetitive concatenation,
// ie "1" + "," + "2" + "," + "3" + "," + "4"
System.out.println(String.join(",", "1", "2", "3", "4"));
// We can pass an array or any class that implements
// Iterable (containing character sequences) as the
// second parameter as well
String arrayOfStrings[] = {"1","2","3","4","5"};
System.out.println(String.join("-", arrayOfStrings));
System.out.println(String.join("-", Arrays.asList(arrayOfStrings))); // Works just fine with lists as well
// Join them with an empty string to convert an array
// of Strings to one single String without any extra data
System.out.println(String.join("", arrayOfStrings));
1,2,3,4
1-2-3-4-5
1-2-3-4-5
12345
Создание массивов символов
Этот метод преобразует используемую String
в массив символов. Он
возвращает новый массив символов, содержащий все символы (по порядку),
которые находятся в String
.
toCharArray()
прямая подпись метода.
String ourString = "These will all become separate characters";
System.out.println(Arrays.toString(ourString.toCharArray()));
Это распечатает следующее:
[T, h, e, s, e, , w, i, l, l, , a, l, l, , b, e, c, o, m, e, , s, e, p, a, r, a, t, e, , c, h, a, r, a, c, t, e, r, s]
Строковое равенство
equals(Object str)
сравнивает две строки и возвращает true
если
строки содержат одинаковые символы в том же порядке, и false
противном
случае. При сравнении equalsIgnoreCase()
для сравнения без учета
регистра).
Важно понимать, что equals()
и ==
выполняют две разные операции.
equals()
сравнивает символы внутри String
, как упоминалось ранее, а
==
сравнивает равенство ссылок на объекты, чтобы увидеть, относятся ли
они к одному и тому же экземпляру. В то время как такие операторы, как
1 == 1
, вернут истинную "string" == "string"
возможно, нет.
Сложность здесь в том, что вывод ==
зависит от того, как мы
инициализировали сравниваемые объекты String
String s1 = "Just a String";
String s2 = "Just a String";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
s2 = new String("Just a String");
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
true
true
false
true
equals()
возвращает true
в обоих случаях. Поэтому вам всегда следует
использовать equals()
если вы действительно не хотите видеть,
ссылаются ли две ссылочные переменные на один и тот же экземпляр, хотя
это довольно редко.
Заключение
Важно понимать нюансы использования String и String методов в Java.
Незаметные, трудно обнаруживаемые ошибки могут возникать с такими
вещами, как split()
и regex, или из-за ошибочного использования ==
когда мы хотели использовать equals()
.
Лучше всегда смотреть, как работает метод, проверять его на себе, чтобы помнить о вещах, на которые нужно обратить внимание. Кроме того, знание имеющихся у вас методов избавляет вас от ненужной работы по реализации уже имеющихся методов самостоятельно.