«1. Введение
Java String — один из самых важных классов, и мы уже рассмотрели множество его аспектов в серии руководств, посвященных String.
В этом руководстве мы сосредоточимся на инициализации строк в Java.
2. Создание
Прежде всего, мы должны помнить, как создаются строки в Java.
Мы можем использовать ключевое слово new или литеральный синтаксис:
String usingNew = new String("baeldung");
String usingLiteral = "baeldung";
Также важно понимать, как строки управляются в специализированном пуле.
3. Объявление только строк
Во-первых, давайте просто объявим строку, без явного присвоения значения.
Мы можем сделать это либо локально, либо как переменная-член:
public class StringInitialization {
String fieldString;
void printDeclaredOnlyString() {
String localVarString;
// System.out.println(localVarString); -> compilation error
System.out.println(fieldString);
}
}
Как мы видим, если мы попытаемся использовать localVarString до присвоения ей значения, мы получим ошибку компиляции. С другой стороны, консоль покажет «null» для значения fieldString.
Видите, переменные-члены инициализируются значением по умолчанию при создании класса, нулевым в случае String. Но мы должны сами инициализировать локальные переменные.
Если мы присвоим localVarString значение null, мы увидим, что они теперь действительно равны:
String localVarString = null;
assertEquals(fieldString, localVarString);
4. Инициализация строки с использованием литералов
Давайте теперь создадим две строки, используя один и тот же литерал :
String literalOne = "Baeldung";
String literalTwo = "Baeldung";
Мы подтвердим, что создается только один объект, сравнив ссылки:
assertTrue(literalOne == literalTwo);
Причина этого восходит к тому факту, что строки хранятся в пуле. literalOne добавляет строку «baeldung» в пул, а literalTwo повторно использует ее.
5. Инициализация строки с помощью new
Однако мы увидим несколько иное поведение, если воспользуемся ключевым словом new.
String newStringOne = new String("Baeldung");
String newStringTwo = new String("Baeldung");
Хотя значение обеих строк будет таким же, как и раньше, на этот раз мы будем иметь разные объекты:
assertFalse(newStringOne == newStringTwo);
6. Пустые строки
Давайте теперь создадим три пустые строки: ~ ~~
String emptyLiteral = "";
String emptyNewString = new String("");
String emptyNewStringTwo = new String();
Как мы уже знаем, emptyLiteral будет добавлен в пул строк, а два других — непосредственно в кучу.
Хотя это не будут одни и те же объекты, все они будут иметь одно и то же значение:
assertFalse(emptyLiteral == emptyNewString)
assertFalse(emptyLiteral == emptyNewStringTwo)
assertFalse(emptyNewString == emptyNewStringTwo)
assertEquals(emptyLiteral, emptyNewString);
assertEquals(emptyNewString, emptyNewStringTwo);
7. Значения null
Наконец, давайте посмотрим, как ведут себя строки null.
Давайте объявим и инициализируем нулевую строку:
String nullValue = null;
Если бы мы напечатали nullValue, мы бы увидели слово «null», как мы видели ранее. И если бы мы попытались вызвать какие-либо методы для nullValue, то получили бы исключение NullPointerException, как и ожидалось.
Но почему печатается «null»? Что такое ноль на самом деле?
Спецификация JVM говорит, что null является значением по умолчанию для всех ссылок, поэтому оно не привязано конкретно к String. И на самом деле спецификация не требует какой-либо конкретной кодировки значения для null.
Итак, откуда тогда взялся «null» для печати строки?
Если мы посмотрим на реализацию PrintStream#println, то увидим, что она вызывает String#valueOf:
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
И если мы посмотрим на String#valueOf, то получим ответ:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
~ ~~ И, очевидно, это причина для «null».
8. Заключение
В этой статье мы рассмотрели инициализацию строк. Мы объяснили разницу между объявлением и инициализацией. Мы также коснулись использования нового и литерального синтаксиса.
Наконец, мы рассмотрели, что значит присвоить String нулевое значение, как нулевое значение представляется в памяти и как оно выглядит при печати.
Все примеры кода, использованные в статье, доступны на Github.