Обычно мы создаем объекты, используя new
ключевое слово, например:
Object obj = new Object();
Строки - это объекты, но мы не используем их new
для их создания:
String str = "Hello World";
Почему это? Могу ли я сделать строку с помощью new
?
Обычно мы создаем объекты, используя new
ключевое слово, например:
Object obj = new Object();
Строки - это объекты, но мы не используем их new
для их создания:
String str = "Hello World";
Почему это? Могу ли я сделать строку с помощью new
?
new String(...)
это было использовано для обхода деталей реализации при подстроке больших строк. Это было исправлено в Java 7 и больше не требуется.
Ответы:
В дополнение к тому, что уже было сказано, строковые литералы [т. Е. Строки, подобные, "abcd"
но не похожие new String("abcd")
] в Java интернированы - это означает, что каждый раз, когда вы ссылаетесь на «abcd», вы получаете ссылку на один String
экземпляр, а не на новый. каждый раз. Итак, у вас будет:
String a = "abcd";
String b = "abcd";
a == b; //True
но если бы у вас было
String a = new String("abcd");
String b = new String("abcd");
тогда возможно иметь
a == b; // False
(и если кому-то нужно напоминание, всегда используйте .equals()
для сравнения строк; ==
тесты на физическое равенство).
Интернирование строковых литералов - это хорошо, потому что они часто используются более одного раза. Например, рассмотрим (надуманный) код:
for (int i = 0; i < 10; i++) {
System.out.println("Next iteration");
}
Если бы у нас не было интернирования строк, «Следующая итерация» должна была бы быть создана 10 раз, тогда как теперь она будет создана только один раз.
Строки - это «особые» объекты в Java. Разработчики Java мудро решили, что строки используются так часто, что им нужен собственный синтаксис, а также стратегия кэширования. Когда вы объявляете строку, говоря:
String myString = "something";
myString - это ссылка на объект String со значением «что-то». Если вы позже заявите:
String myOtherString = "something";
Java достаточно умен, чтобы решить, что myString и myOtherString одинаковы, и будет хранить их в глобальной таблице String как один и тот же объект. Он основан на том факте, что вы не можете изменять Strings для этого. Это снижает объем требуемой памяти и может ускорить сравнение.
Если вместо этого вы напишете
String myOtherString = new String("something");
Java создаст для вас совершенно новый объект, отличный от объекта myString.
String a = "abc"; // 1 Object: "abc" added to pool
String b = "abc"; // 0 Object: because it is already in the pool
String c = new String("abc"); // 1 Object
String d = new String("def"); // 1 Object + "def" is added to the Pool
String e = d.intern(); // (e==d) is "false" because e refers to the String in pool
String f = e.intern(); // (f==e) is "true"
//Total Objects: 4 ("abc", c, d, "def").
Надеюсь, это развеет некоторые сомнения. :)
Это ярлык. Изначально это было не так, но Java изменила это.
В этом FAQ кратко об этом говорится. Об этом также говорится в руководстве по спецификациям Java. Но я не могу найти его в Интернете.
Строка подверглась нескольким оптимизациям (из-за отсутствия лучшей фразы). Обратите внимание, что String также имеет перегрузку оператора (для оператора +) - в отличие от других объектов. Так что это особый случай.
Обычно мы используем строковые литералы, чтобы избежать создания ненужных объектов. Если мы используем оператор new для создания объекта String, он будет каждый раз создавать новый объект.
Пример:
String s1=“Hello“;
String s2=“Hello“;
String s3= new String(“Hello“);
String s4= new String(“Hello“);
Для приведенного выше кода в памяти:
В Java строки - это особый случай, многие правила применяются только к строкам. Двойные кавычки заставляют компилятор создать объект String. Поскольку объекты String неизменяемы, это позволяет компилятору вставлять несколько строк и создавать пул строк большего размера. Две идентичные строковые константы всегда будут иметь одну и ту же ссылку на объект. Если вы не хотите, чтобы это было так, вы можете использовать new String (""), и это создаст объект String во время выполнения. Раньше был общий метод intern (), который заставлял динамически создаваемые строки проверяться по таблице поиска строк. После интернирования строки ссылка на объект будет указывать на канонический экземпляр String.
String a = "foo";
String b = "foo";
System.out.println(a == b); // true
String c = new String(a);
System.out.println(a == c); // false
c = c.intern();
System.out.println(a == c); // true
Когда загрузчик классов загружает класс, все константы String добавляются в пул String.
Синтаксический сахар. В
String s = new String("ABC");
синтаксис все еще доступен.
String small = new String(huge.substring(int, int));
позволяет повторно использовать большой базовый объект char[]
из исходной huge
String.
Вы все еще можете использовать new String("string")
, но было бы сложнее создавать новые строки без строковых литералов ... вам нужно будет использовать символьные массивы или байты :-) Строковые литералы имеют одно дополнительное свойство: все те же строковые литералы из любой точки класса в ту же строку экземпляр (они интернированы).
Практически нет необходимости создавать новую строку, поскольку литерал (символы в кавычках) уже является объектом String, созданным при загрузке класса хоста. Совершенно законно вызывать методы для литералов и доноров, главное отличие - удобство, обеспечиваемое литералами. Было бы большой проблемой и пустой тратой времени, если бы нам пришлось создать массив символов и заполнить его char за char, а они сделали бы новую строку (массив char).
Не стесняйтесь создавать новую строку с
String s = new String("I'm a new String");
Обычная нотация s = "new String";
- это более или менее удобный ярлык, который следует использовать по соображениям производительности, за исключением тех довольно редких случаев, когда вам действительно нужны строки, которые подходят для уравнения
(string1.equals(string2)) && !(string1 == string2)
РЕДАКТИРОВАТЬ
В ответ на комментарий: это не предназначалось для того, чтобы быть советом, а всего лишь прямым ответом на тезис вопрошающего, что мы не используем ключевое слово «новое» для строк, что просто неверно. Надеюсь, это изменение (включая приведенное выше) немного проясняет это. Кстати, есть несколько хороших и гораздо лучших ответов на вышеупомянутый вопрос о SO.
new String(...)
ЕСЛИ ваше приложение НЕ ТРЕБУЕТ, чтобы вы создавали String с отдельным идентификатором.
Пул литералов содержит любые строки, созданные без использования ключевого слова new
.
Есть разница: строка без новой ссылки хранится в пуле строковых литералов, а строка с новой говорит, что они находятся в памяти кучи.
Строки с new находятся где-то в памяти, как и любой другой объект.
Поскольку String - неизменный класс в java.
Теперь почему он неизменен? Поскольку String является неизменяемым, его можно использовать в нескольких потоках, и нам не нужно синхронизировать операцию String извне. As String также используется в механизме загрузки классов. Итак, если String был изменяемым, тогда java.io.writer можно было изменить на abc.xyz.mywriter
TString obj1 = new TString("Jan Peter");
TString obj2 = new TString("Jan Peter");
if (obj1.Name == obj2.Name)
System.out.println("True");
else
System.out.println("False");
Вывод:
Правда
Я создал два отдельных объекта, у обоих есть поле (ссылка) «Имя». Так что даже в этом случае "Ян Питер" является общим, если я понимаю, как работает Java.
Ну, StringPool реализован с использованием Hashmap в java. Если мы всегда создаем с новым ключевым словом, он не выполняет поиск в String Pool и не создает для него новую память, которая может понадобиться позже, если у нас выполняется операция с интенсивным использованием памяти, и если мы создаем все строки с новым ключевым словом, которое повлияет на производительность нашего приложения. Поэтому рекомендуется не использовать новые ключевые слова для создания строки, потому что тогда только она перейдет в пул строк, который, в свою очередь, является Hashmap (память сохранена, представьте, если у нас есть много строк, созданных с новым ключевым словом), здесь он будет сохранен и если строка уже существует, ссылка на нее (которая обычно находится в памяти стека) будет возвращена во вновь созданную строку. Итак, это сделано для повышения производительности.