Перейти к основному содержимому

Инициализация строки в Java

· 4 мин. чтения

1. Введение

Java String — один из самых важных классов, и мы уже рассмотрели многие его аспекты в нашей серии руководств, связанных со строками .

В этом руководстве мы сосредоточимся на инициализации строк в Java.

2. Создание

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

Мы можем использовать новое ключевое слово или литеральный синтаксис:

String usingNew = new String("foreach");
String usingLiteral = "foreach";

И также важно, чтобы мы понимали, как String управляются в специализированном пуле .

3. Только объявление строки

Во-первых, давайте просто объявим String без явного присвоения значения.

Мы можем сделать это локально или в качестве переменной-члена:

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 , используя один и тот же литерал:

String literalOne = "ForEach";
String literalTwo = "ForEach";

Мы подтвердим, что создан только один объект, сравнив ссылки:

assertTrue(literalOne == literalTwo);

Причина этого восходит к тому факту, что String хранятся в пуле . literalOne добавляет строку «foreach» в пул, а literalTwo повторно использует ее.

5. Инициализация строки с помощью new

Однако мы увидим другое поведение, если будем использовать новое ключевое слово.

String newStringOne = new String("ForEach");
String newStringTwo = new String("ForEach");

Хотя значение обоих String будет таким же, как и раньше, на этот раз нам понадобятся разные объекты:

assertFalse(newStringOne == newStringTwo);

6. Пустая строка

Давайте теперь создадим три пустых String s:

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 String s.

Давайте объявим и инициализируем нулевую строку :

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();
}

И, очевидно, в этом причина «нуля».

8. Заключение

В этой статье мы рассмотрели инициализацию строк . Мы объяснили разницу между объявлением и инициализацией. Мы также коснулись использования нового и литерального синтаксиса.

Наконец, мы рассмотрели, что значит присвоить String нулевое значение , как нулевое значение представляется в памяти и как оно выглядит при печати.

Все примеры кода, использованные в статье, доступны на Github .