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

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

Object obj = new Object();

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

String str = "Hello World";

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

Ответ 1

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

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

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

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

Ответ 2

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

String myString = "something";

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

String myOtherString = "something";

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

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

String myOtherString = new String("something");

Java создаст для вас совершенно новый объект, отличный от объекта myString.

Ответ 3

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").

Надеюсь, что это несколько сомнений.:)

Ответ 4

Это ярлык. Первоначально это было не так, но Java изменила его.

Этот FAQ рассказывает об этом кратко. Об этом также говорит руководство по спецификации Java. Но я не могу найти его в Интернете.

Ответ 5

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

Ответ 6

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

Ответ 7

Невозможно создать новую строку с

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

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

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

ИЗМЕНИТЬ

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

Ответ 8

Синтаксический сахар.

String s = new String("ABC");
Синтаксис

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

Ответ 9

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

Ответ 10

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

Ответ 11

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

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

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

Ответ 12

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

Теперь почему он неизменен? Поскольку String является неизменным, поэтому он может быть разделен между несколькими потоками, и нам не нужно синхронизировать операцию String извне. Поскольку String также используется в режиме загрузки классов. Поэтому, если String изменен, тогда java.io.writer можно было бы изменить на abc.xyz.mywriter

Ответ 13

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'. Поэтому даже в этом случае "Ян Питер" является общим, если я понимаю, как работают java.