Как можно инициализировать строку с помощью «»?

154

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

splitgames
источник
25
Струна VIP класса. " "это уже строка!
johnchen902
2
Никакого особого значения. Я просто имел в виду очень важно. То есть java.lang.Stringимеют особое отношение к языку Java.
johnchen902
16
Кто сказал, что строка "класс, как и любой другой"? Это очень особенный класс, в отличие от любого другого. Поскольку ваше предположение неверно, вопрос на самом деле не отвечает.
Эрик Липперт
5
То, что предположение ложно, не означает, что вопрос не несет ответственности. И правильный ответ уже имеет 197 голосов.
Корай Тугай

Ответы:

293

Java String является особенной

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

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

Например

String s1 = "Hello";              // String literal
String s2 = "Hello";              // String literal
String s3 = s1;                   // same reference
String s4 = new String("Hello");  // String object
String s5 = new String("Hello");  // String object

введите описание изображения здесь

Примечание. Строковые литералы хранятся в общем пуле. Это облегчает совместное использование хранилища для строк с одинаковым содержимым для сохранения хранилища.Stringобъекты, выделенные через новый оператор, хранятся в heap, и для этого же содержимого нет общего хранилища.

Суреш Атта
источник
72
Обратите внимание, что «общий пул» обычно является частью кучи.
Йоахим Зауэр
3
@JoachimSauer Да .. с небольшими выгодами :) добавил, что в примечании. Спасибо за запоминание.
Суреш Атта
2
Так что быстрее написать String s1 = "Hello"; чем String s2 = новая строка («Привет») ;?
user2097804
28
Я бы добавил, что в вашем примере s1 == s2 == s3, но s4! = S5
Альфредо Осорио
8
@AndrewJanke в недавней горячей точке jvm (7), пул строк не в perm gen, а в Java 8
perm
50

Java рассматривает String как специальный класс, который можно инициализировать двумя способами

  1. Прямое присвоение литерала

    String a = "adsasdf";
  2. В качестве других объектов используется новое ключевое слово

    String a = new String("adsasdf");

Вы должны быть особенно внимательны, если хотите сравнить со ==знаком:

String a = "asdf";
String b = "asdf";
System.out.println(a == b);  // True
System.out.println(a.equals(b)); // True

String a = new String("asdf");
String b = new String("asdf");
System.out.println(a == b);  // False
System.out.println(a.equals(b)); // True

Это потому, что в первом случае объекты a и b хранятся в вызываемом literal poolобъекте, и они оба ссылаются на один и тот же объект, поэтому они равны в обоих отношениях.

Но во втором случае a и b ссылаются на разные объекты, например, когда мы инициализируем любые другие объекты. поэтому они неравны по сравнению с ==оператором, тогда как они равны по значениям.

Четан
источник
18

String получает особую обработку в JLS: это один из двух не примитивных типов, для которых существуют литералы (другой есть Class) * .

Из JLS :

Строковый литерал является ссылкой на экземпляр класса `String [...].

* ну, есть также «нулевой тип» с его «нулевым литералом» null, но большинство людей не считают «нулевой тип» правильным типом.

Йоахим Зауэр
источник
1
Я также не знал, что «нулевой тип» является правильным типом в Java. Это очень полезная информация, вы должны увеличить размер шрифта.
Грижеш Чаухан,
1
@GrijeshChauhan: ну, «нулевой тип» - это просто изящная формулировка, позволяющая nullприсваивать любое значение любой переменной ссылочного типа. Это не интересный тип, в противном случае.
Иоахим Зауэр
15

Это особенность языка Java. Строковые литералы в исходном коде получают специальную обработку.

Спецификация языка здесь просто говорит, что строковый литерал имеет Stringтип

н.у.к.
источник
5

Текст внутри двойных кавычек создает буквальный Stringобъект.

String myString = "Some text";

Код выше создает Stringобъект, используя двойные кавычки.

tristan2468
источник
4

Строки очень часто используются в языке программирования. Поскольку Java является объектно-ориентированным, строка является объектом. Чтобы избежать громоздкой новой строки ("someString"); оператор каждый раз, когда вам нужен строковый объект java позволяет вам просто создать строковый объект, используя строковый литерал.

Но вы должны иметь в виду равенство строк. Вот короткий тест JUnit, чтобы продемонстрировать, что я имею в виду.

    @Test
    public void stringTest() {
       // a string literal and a string object created 
       // with the same literal are equal
       assertEquals("string", new String("string"));

       // two string literals are the same string object
       assertSame("string", "string"); 

       // a string literal is not the same object instance 
       // as a string object created with the same string literal
       assertFalse("string" == new String("string"));

       // java's String.intern() method gives you the same
       // string object reference for all strings that are equal.
       assertSame("string", new String("string").intern());
    }
Рене Линк
источник
Если бы вы могли только инициализировать строку с помощью new String(String src), то вы бы даже не смогли дать конструктору строковый литерал. Вам нужно будет инициализировать char [], а затем использовать String(char [] src)конструктор для создания строки, или вам придется читать строку из файла.
AJMansfield
Это не правильно. Строковый литерал - это только последовательность символов в исходном файле, заключенная в двойные кавычки. Java автоматически создает экземпляр строки, используя этот литерал. Поэтому литерал и объект String равны, но они не совпадают. Java также может быть реализован таким образом, что вы должны использовать new String (""); создать экземпляр объекта String, но это только усложнит нашу жизнь. Поэтому, когда вы пишете новую строку («строка»), Java создает объект String для литерала «строка» и передает этот строковый объект создателю новой строки.
Рене Линк
2

Просто чтобы упомянуть. Строковый литерал - это ссылка на экземпляр класса String, который вы можете написать так:

 "ABC" .getBytes ();

 "А: б: в" .split ( ":");

 "愛" .codePointAt (0);
mkdev
источник
2

- String - это класс в Java . Вы правы в этом, поэтому мы всегда можем инициализировать с newключевым словом.

- Но когда мы делаем что-то вроде:

String s = "";

Вышеприведенный оператор помечается компилятором как специальный объект String, а затем JVM во время загрузки класса (загрузка выполняется до инициализации), видит это так называемый строковый литерал , который хранится в пуле строкового литерала .

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

Кумар Вивек Митра
источник
2

Java делает для нас двухэтапный процесс.

String str = "hello";

эквивалентно

char data[] = {'h', 'e', 'l' , 'l', 'o'};
String str = new String(data);

Как [.NET] [1] получил похожую вещь.

String(Char[]) constructor

делает

String(char[] value)

Добавление ссылок: -

user1769790
источник
2
Процесс, который вы описываете, - это не то, что на самом деле делает Java: как уже говорили другие, "hello"это строковый литерал, который компилятор помещает в пул констант, см. JLS §3.10.5 и JVMS §5.1 .
siegi
1

Java.lang.Stringэто не просто класс. Это неотъемлемая часть основного языка. У компилятора есть синтаксический сахар для него. Например, ""это как сокращение для new String(""). При написании ""компилятор оптимизирует идентичные строки для одного и того же экземпляра для экономии места."a" + 5 == "a5" ==> true

У компилятора есть синтаксический сахар для многих вещей, включая отсутствие необходимости вставлять / снимать коробку между версиями объекта и их нативными типами, нет родительских средств Object, конструктор по умолчанию, ...

Сильвестер
источник
5
""это не сокращение для new String(""). Если вы используете "", первое, что будет сделано, - это поиск совпадений в пуле строк JVM, и если это так, он вернет эту строку. Используя new String(""), вы всегда будете создавать новую строку, даже если сама строка уже существует в пуле строк (поскольку она не будет храниться в пуле строк).
g00glen00b
Я обновил свой ответ. Используют ли люди это в своих интересах, например, используют строковые константы как эквивалент типа символа Лисп?
Сильвестр