Почему новое ключевое слово не нужно для строки - PullRequest
32 голосов
/ 30 декабря 2011

Я новичок в Java.

В Java String является class. Но нам не нужно использовать ключевое слово new для создания объекта класса String, где new используется для создания объектов для других классов.

Я слышал о классах Wrapper, таких как Integer, Double, которые похожи на это. Но String не Wrapper, не так ли?

На самом деле, что происходит, когда я использую

     String message = "Hai";

?? Чем он отличается от

String message = new String("Hai");

Вот message ссылочная переменная или что-то еще ?? Существуют ли другие классы, которым не требуется new для создания объекта ??

Ответы [ 4 ]

24 голосов
/ 30 декабря 2011

С помощью следующей строки вы не создаете новый объект String в куче, но повторно используете строковый литерал (если он уже доступен):

String message = "Hai";

"Hai" - строковый литерал в пуле строковых литералов. Поскольку строки являются неизменяемыми, они могут использоваться повторно, поэтому они объединяются в пул строковых литералов JVM. И это рекомендуемый способ, потому что вы используете его повторно.

Но со следующим вы фактически создаете новый объект (в куче):

String message = new String("Hai");

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

Также смотрите этот пост: Вопросы о пуле строк Java

Существуют ли другие классы, которым не требуется новый для создания объекта ??

На самом деле вы не можете создавать объекты в Java без использования ключевого слова new.

, например

Integer i = 1;

Не означает, что объект Integer создан без использования new. Нам просто не нужно явно использовать ключевое слово new. Но под капотом, если объект Integer со значением 1 еще не существует в кеше (Integer объекты кэшируются JVM), для его создания будет использовано ключевое слово new.

8 голосов
/ 30 декабря 2011

Спецификация языка Java допускает представление строки в виде литерала .Вы можете рассматривать это как быструю инициализацию для строки, у которой есть один важный побочный эффект, который отличается от обычной инициализации с помощью new

Строковые литералы все interned , которыеозначает, что они являются постоянными значениями, хранящимися во время выполнения Java, и могут совместно использоваться несколькими классами.Например:

class MainClass (
    public String test = "hello";
}

class OtherClass {
   public String another = "hello";

   public OtherClass() {
       MainClass main = new MainClass();
       System.out.println(main.test == another);
   }
}

выведет «true», поскольку оба экземпляра String фактически указывают на один и тот же объект.Это не будет иметь место, если вы инициализируете строки с помощью ключевого слова new .

7 голосов
/ 30 декабря 2011

Создание строк и целых чисел различны.

String s = "Test";

Здесь оператор '=' перегружен для строки. Так же как и оператор «+» в «некоторых» + «вещах». Где, как,

Integer i = 2;

До Java 5.0 это ошибка времени компиляции; Вы не можете назначить примитив его оболочке. Но в Java 5.0 это называется автобоксом, где примитивы автоматически переносятся в свои оболочки, где это необходимо.

String h1 = "hi";

будет отличаться от

String h2 = new String("hi");

Причина в том, что JVM поддерживает таблицу строк для всех строковых литералов. поэтому в таблице будет запись "привет", скажем, ее адрес 1000.

Но когда вы явно создаете строковый объект, будет создан новый объект, скажем, его адрес равен 2000. Теперь новый объект будет указывать на запись в таблице строк, которая равна 1000.

Следовательно, когда вы говорите

h1 == h2

сравнивает

1000 == 2000

Так что это ложно

1 голос
/ 30 декабря 2011

В Яве
«==» сравнивает левые и правые ячейки памяти (а не значение в этой ячейке памяти) и, следовательно, в случае

new String("hai")==new String("hai")

возвращает false.

В случае "Hai" == "Hai", java не выделяет отдельную память для одного и того же строкового литерала, поэтому здесь "==" возвращает true. Вы всегда можете использовать метод equals для сравнения значений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...