← Назад к вопросам
В чем разница между инициализацией String через new String и через " "?
1.2 Junior🔥 181 комментариев
#JVM и управление памятью#Основы Java
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Разница между инициализацией String через new String() и через литерал ""
Основное различие
В Java есть два способа создания String объектов: через литерал (нативный синтаксис) и через конструктор new String(). Эти подходы создают строки в разных местах памяти и имеют различные последствия для производительности и поведения.
1. String литерал ("hello")
Когда вы создаете строку через литерал, Java помещает ее в специальную область памяти под названием String Pool (String Intern Pool).
String str1 = "hello";
String str2 = "hello";
String str3 = "hello";
// Все три переменные указывают на один и тот же объект в String Pool
System.out.println(str1 == str2); // true (один объект в памяти)
System.out.println(str1.equals(str2)); // true
Характеристики:
- Строка помещается в String Pool (heap memory)
- Если строка уже существует в pool, создается новая ссылка на существующий объект
- Экономия памяти благодаря дедупликации
- Очень быстрое сравнение через
==(сравнение ссылок)
2. Создание через конструктор new String()
Когда вы используете конструктор new String(), Java ВСЕГДА создает новый объект в heap памяти, даже если такая строка уже существует в String Pool.
String str1 = new String("hello");
String str2 = new String("hello");
String str3 = "hello";
// str1 и str2 - разные объекты в heap
// str3 - объект в String Pool
System.out.println(str1 == str2); // false (разные объекты)
System.out.println(str1.equals(str2)); // true (одинаковое содержимое)
System.out.println(str1 == str3); // false (разные объекты)
Характеристики:
- Создается новый объект в обычной heap памяти
- String Pool все равно заполняется для литерала
- Больше потребления памяти
- Сравнение через
==будет false
Визуальная демонстрация в памяти
Литерал (""):
┌─────────────────────┐
│ String Pool │
├─────────────────────┤
│ "hello" @2548 │ ← str1, str2, str3 указывают сюда
└─────────────────────┘
Конструктор new String():
┌──────────────────────┐ ┌──────────────────────┐
│ Обычная heap │ │ String Pool │
├──────────────────────┤ ├──────────────────────┤
│ "hello" @1234 │ │ "hello" @2548 │
│ "hello" @5678 │ └──────────────────────┘
└──────────────────────┘
str1 @1234, str2 @5678 указывают на heap
Практические примеры
Пример 1: Сравнение через ==
String s1 = "hello"; // String Pool
String s2 = "hello"; // String Pool (тот же объект)
String s3 = new String("hello"); // Heap
String s4 = new String("hello"); // Heap (новый объект)
// Сравнение ссылок (==)
System.out.println(s1 == s2); // true - один объект
System.out.println(s1 == s3); // false - разные объекты
System.out.println(s3 == s4); // false - разные объекты
// Сравнение значений (equals)
System.out.println(s1.equals(s3)); // true - одинаковое содержимое
System.out.println(s3.equals(s4)); // true - одинаковое содержимое
Пример 2: Использование concat() и new String()
String result1 = "Hello" + " World"; // Результат в String Pool
String result2 = new String("Hello" + " World"); // Новый объект в Heap
System.out.println(result1 == result2); // false
Пример 3: String.intern()
Метод intern() добавляет строку в String Pool (или возвращает ссылку на существующую).
String s1 = new String("hello");
String s2 = "hello";
System.out.println(s1 == s2); // false
// Добавляем s1 в String Pool
String s3 = s1.intern();
System.out.println(s3 == s2); // true (обе указывают на pool)
Таблица сравнения
| Аспект | Литерал "" | new String() |
|---|---|---|
| Размещение | String Pool | Heap |
| Переиспользование | Да (дедупликация) | Нет |
| Потребление памяти | Минимальное | Больше |
| Производительность | Быстрее | Медленнее |
| Сравнение == работает | Да | Нет |
| Создание при каждом вызове | Нет | Да |
Какой способ использовать?
Используйте литерал "" когда:
// 1. Обычное объявление строковых констант
String error = "File not found";
String apiUrl = "https://api.example.com";
// 2. Вам нужна экономия памяти
for (int i = 0; i < 1000; i++) {
String msg = "Processing item"; // Использует одну строку из pool
}
// 3. Вы сравниваете строки через ==
if (status == "ACTIVE") { // Работает только с литералами
// ...
}
Используйте new String() когда:
// 1. Нужна новая копия строки (очень редко)
char[] data = "secret".toCharArray();
String secret = new String(data);
// Теперь можно очистить массив, оригинальная строка не затрагивается
Arrays.fill(data, ' ');
// 2. Нужно конвертировать массив байт
byte[] bytes = "Hello".getBytes();
String str = new String(bytes, StandardCharsets.UTF_8);
Производительность
Тест на большом количестве строк
// Создание 100,000 одинаковых строк
long start = System.nanoTime();
for (int i = 0; i < 100_000; i++) {
String str = "test"; // Все указывают на один объект в pool
}
long literalTime = System.nanoTime() - start;
start = System.nanoTime();
for (int i = 0; i < 100_000; i++) {
String str = new String("test"); // 100,000 разных объектов
}
long newStringTime = System.nanoTime() - start;
System.out.println("Literal: " + literalTime);
System.out.println("new String: " + newStringTime);
// new String() будет медленнее и потребит больше памяти
Правильное сравнение String
// ❌ Неправильно - зависит от того, как была создана строка
if (str1 == str2) {
// Может работать или не работать
}
// ✅ Правильно - всегда безопасно
if (str1.equals(str2)) {
// Гарантированно сравнивает содержимое
}
// ✅ Для игнорирования регистра
if (str1.equalsIgnoreCase(str2)) {
// Сравнивает без учета регистра
}
Выводы
- Используйте литералы ("") как основной способ создания строк - это экономит память и улучшает производительность
- Используйте new String() очень редко - только для специальных случаев (работа с байтами, особые требования к изоляции)
- Сравнивайте строки через equals(), а не через
== - String Pool - это автоматическая оптимизация, которая экономит память за счет дедупликации строк
- JVM автоматически управляет String Pool, поэтому не нужно вызывать intern() в обычном коде