Строки-это объекты в Java, так почему бы нам не использовать' new ' для их создания?


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

Object obj = new Object();

строки являются объектами, но мы не используем new создать их:

String str = "Hello World";

почему это? Могу ли я сделать строку с new?

14 88

14 ответов:

в дополнение к тому, что уже было сказано, строку литералы [т. е. строки типа "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() to сравнение строк;== тесты на физическое равенство).

интернирование строковых литералов хорошо, потому что они часто используются более одного раза. Например, рассмотрим (надуманный) код:

for (int i = 0; i < 10; i++) {
  System.out.println("Next iteration");
}

если бы у нас не было интернирования строк, "следующая итерация" должна была бы быть создана 10 раз, тогда как теперь она будет создана только один раз.

строки являются "специальными" объектами в Java. Разработчики Java мудро решили, что строки используются так часто, что им нужен свой собственный синтаксис, а также стратегия кэширования. Когда вы объявляете строку, говоря:

String myString = "something";

myString-это ссылка на объект String со значением "something". Если вы позже объявите:

String myOtherString = "something";

Java достаточно умен, чтобы понять, что myString и myOtherString одинаковы и будут хранить их в глобальной таблице строк как одно и то же объект. Это зависит от того, что вы не можете изменить строки для этого. Это снижает объем необходимой памяти и может сделать сравнение быстрее.

Если, вместо этого, вы пишите

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 также говорит об этом. Но я не могу найти его в интернете.

строка подвергается нескольким оптимизациям (за неимением лучшей фразы). Обратите внимание, что строка также имеет перегрузку оператора (для оператора+) - в отличие от других объектов. Так что это очень особый случай.

в Java строки являются особым случаем, со многими правилами, которые применяются только к строкам. Двойные кавычки, компилятор создает объект String. Поскольку строковые объекты неизменяемы, это позволяет компилятору интернировать несколько строк и создавать более крупный пул строк. Две одинаковые строковые константы всегда будут иметь одну и ту же ссылку на объект. Если вы не хотите, чтобы это было так, то вы можете использовать новую строку (""), и это создаст объект 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 s = new String("ABC");

синтаксис по-прежнему доступен.

вы все еще можете использовать new String("string"), но было бы сложнее создавать новые строки без строковых литералов ... вам придется использовать символьные массивы или байты : -) строковые литералы имеют одно дополнительное свойство: все те же строковые литералы из любого класса указывают на один и тот же экземпляр строки (они интернированы).

почти нет необходимости создавать новую строку, поскольку литерал (символы в кавычках) уже является строковым объектом, созданным при загрузке класса хоста. Совершенно законно вызывать методы на литерале и Доне, главное различие-это удобство, предоставляемое литералами. Было бы большой болью и тратой tine, если бы нам пришлось создать массив символов и заполнить его char by char, а они делают новую строку(массив символов).

не стесняйтесь создавать новую строку с

String s = new String("I'm a new String");

обычная нотация s = "new String"; это более или менее удобный ярлык - который следует использовать по соображениям производительности, за исключением тех довольно редких случаев, когда вы действительно нужны строки, которые подходят для уравнения

(string1.equals(string2)) && !(string1 == string2)

EDIT

В ответ на комментарий: Это был не предназначен для консультирования, но только для прямого ответа на вопрошающие тезис, что мы не используем ключевое слово 'new' для строк, что просто не соответствует действительности. Надеюсь, что это редактирование (в том числе выше) немного проясняет это. Кстати-есть несколько хороших и гораздо лучших ответов на вышеуказанный вопрос о SO.

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

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

строки с new находятся в другом месте в памяти, как и любой другой объект.

потому что String является неизменяемым классом в java.

теперь почему она неизменна? Поскольку строка неизменна, поэтому она может быть разделена между несколькими потоками, и нам не нужно синхронизировать строковую операцию извне. Как строка также используется в механизме загрузки классов. Поэтому, если строка была изменчивой, то 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");

выход:

True

Я создал два отдельных объекта, оба имеют поле (ref)'Name'. Поэтому даже в этом случае" Jan Peter " является общим,если я понимаю, как работает java..

мы обычно используем строковые литералы, чтобы избежать создания ненужных объектов. Если мы используем оператор new для создания объекта String , то он будет создавать новый объект каждый раз .

пример:

String s1=“Hello“;
String s2=“Hello“;
String s3= new String(“Hello“);
String s4= new String(“Hello“);

для приведенного выше кода в памяти:

enter image description here