Подтвердить что ты не робот

Подсчет объектов String, созданных кодом Java

Сколько объектов String создается следующим кодом?

String x = new String("xyz");
String y = "abc";
x = x + y;

Я посетил многие веб-сайты, где некоторые говорят, что эта строка кода создает 3 объекта, а некоторые говорят, что она создает 4. Я просто хотел узнать, сколько объектов создано после выполнения этой строки кода.

4b9b3361

Ответ 1

К концу прогона будут четыре объекта String:

  • A String, который соответствует интернированному литералу "xyz"
  • Его копия, созданная new String("xyz")
  • A String, который соответствует интернированному литералу "abc"
  • A String, который соответствует конкатенации "xyz" + "abc"

Реальный вопрос заключается в том, что некоторые или все эти объекты относятся к вашей программе. Можно разумно утверждать, что ваш код составляет всего два или четыре элемента String. Несмотря на то, что существует всего четыре объекта String, объекты 1 и 3 могут не обязательно создаваться вашим кодом, потому что они находятся в постоянном пуле, поэтому они создаются вне прямого управления вашим кодом.

Ответ 2

Этот ответ должен исправить ошибочное представление, которое вызывает некоторые другие ответы:

Например:

Компилятор может заменить x + y константой ( "xyzabc" ). @Binkan Salaryman

... и объект String 4 [строка, соответствующая конкатенации] может быть вычислен компилятором и также превращена в интернированную константу. @dasblinkenlight

Это неверно. В JLS указано следующее:

15.18.1. Оператор конкатенации строк +

....

Объект String только что создан (§12.5), если выражение не является постоянным выражением (§15.28).

Чтобы квалифицироваться как константное выражение, имена переменных в выражении должны быть:

Простые имена (§6.5.6.1), которые относятся к постоянным переменным (§4.12.4).

где "постоянная переменная" определяется как:

Постоянная переменная является конечной переменной примитивного типа или типа String, которая инициализируется константным выражением (§15.28).

В этом примере ни x, либо y не являются final, поэтому они не являются постоянными переменными. И даже если они были final, y по-прежнему не будет постоянной переменной из-за использования оператора new в его инициализации.


Короче говоря, компилятору Java не разрешено использовать постоянную константу "xyzabc" в результате выражения конкатенации.

Если в конце я добавил следующий оператор:

    System.out.println(x == "xyzabc");

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

Ответ 3

Взгляните на декомпилированный класс, и вы увидите все:) Ответ должен быть:

  • две строки ("xyz" и "abc") - это только ссылки на позиции в постоянном пуле, поэтому они не созданы вашим кодом.
  • создается одна строка напрямую (new String("xyz"))
  • конкатенация строк оптимизирована компилятором и изменена на StringBuilder, поэтому последняя строка создается косвенно

    public java.lang.String method();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=3, args_size=1
     0: new           #2                  // class java/lang/String
     3: dup
     4: ldc           #3                  // String xyz
     6: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
     9: astore_1
    10: ldc           #5                  // String abc
    12: astore_2
    13: new           #6                  // class java/lang/StringBuilder
    16: dup
    17: invokespecial #7                  // Method java/lang/StringBuilder."<init>":()V
    20: aload_1
    21: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    24: aload_2
    25: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    28: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
    31: astore_1
    32: aload_1
    33: areturn
    

Ответ 4

Ответ 4.

Как вы использовали ключевое слово new, Java создаст новый объект String в обычной (не пул) памяти, а x будет ссылаться на него. В дополнение к этому, буквальный "xyz" будет помещен в пул строк, который снова является другим строковым объектом.

Итак, 4 строковых объекта:

  • "xyz" (в памяти без пула)
  • "xyz" (в памяти пула)
  • "abc" (в памяти пула)
  • "xyzabc" (в памяти без пула)

Если ваш код был таким:

String x = "xyz";
String y = "abc";
x = x + y;

тогда ответ будет 3.

Примечание. Строка №4 находится в памяти без пула, так как строковые литералы и строки, полученные путем вычисления постоянных выражений (см. JLS §15.28), являются единственными строками, которые неявно интернированы.

Источник: SCJP Sun Certified Programmer для Java 6 (Страница: 434, глава 6)

Ответ 5

Если вы хотите протестировать экземпляры, запустите этот фрагмент кода и посмотрите на вывод:

import static java.lang.System.identityHashCode;

public class Program {
    public static void main(String... args) {
        String x = new String("xyz");
        String y = "abc";
        String z = x + y;

        System.out.printf("x: %d | %d\n", identityHashCode(x), identityHashCode(x.intern()));
        System.out.printf("y: %d | %d\n", identityHashCode(y), identityHashCode(y.intern()));
        System.out.printf("z: %d | %d\n", identityHashCode(z), identityHashCode(z.intern()));
    }
}

У меня есть следующий вывод, используя jdk1.7.0_67:

x: 414853995 | 1719175803
y: 1405489012 | 1405489012
z: 1881191331 | 1881191331

Это всего 4 String экземпляров...

Ответ 6

new String("xyz") наверняка создаст новый экземпляр. "abc" и "xyz" сохраняются в пуле констант класса, x = x + y создает StringBuilder под капотом и поэтому создает new String, поэтому количество строк здесь 4.


Компилятор может заменить x + y константой ("xyzabc").

Ответ 7

Я бы сказал 4, потому что:

Вот как:

String x = new String("xyz"); // 2 objects created: the variable and the constant
String y = "abc"; // 1 object created: the variable
x = x + y; // 1 object created: the one by the StringBuilder class

Ответ 8

Причина, по которой вы видите разные ответы на вопрос, (частично), что она неоднозначна.

"Сколько объектов String создается следующим кодом?"

Неопределенность выражается в фразе "созданной следующим кодом":

  • Он спрашивает о количестве объектов String, созданных (просто) при выполнении кода?

  • Или... спрашивает о количестве объектов String, которые должны существовать во время выполнения кода?

Можно утверждать, что код неявно создает объекты String, которые соответствуют литералам, а не когда они запускаются, но когда они загружаются. Однако эти объекты могут использоваться совместно с другим кодом, который использует те же литералы. (И если вы выглядите достаточно сложно, возможно, что во время процесса загрузки класса создаются другие строковые объекты, содержащие одни и те же строки символов.)


Другая причина, по которой вы видите разные ответы, состоит в том, что не совсем понятно, сколько строк создается. В разных спецификациях утверждается, что в определенные моменты будут созданы новые объекты String, но есть "комната для изгибания" относительно того, могут ли быть созданы промежуточные объекты String.

Например, JLS утверждает, что new всегда создает новый объект и что оператор конкатенации строк создает новый объект, за исключением определенных явно определенных случаев (см. мой другой ответ). Однако спецификации не запрещают создание других строк за кадром.


Но в этом случае, если предположить, что мы используем современный Hotspot JVM, то:

  • 2 строковых объекта существуют (для строковых литералов) до начала запуска кода и
  • При выполнении кода создаются 2 новых строковых объекта (оператором new и +).

Существование/создание этих 4 строк гарантируется JLS.

Ответ 9

Ответ 4

String x = new String("xyz");//First Object

String y = "abc";//Second Object

x = x + y;//Third, fourth Object

Ответ 10

Иногда лучше указывать байт-код Изучение кода с помощью JAVAP

public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=3, args_size=1
         0: new           #16                 // class java/lang/String
         3: dup
         4: ldc           #18                 // String xyz
         6: invokespecial #20                 // Method java/lang/String."<init>":(Ljava/lang/String;)V
         9: astore_1
        10: ldc           #23                 // String abc
        12: astore_2
        13: new           #25                 // class java/lang/StringBuilder
        16: dup
        17: aload_1
        18: invokestatic  #27                 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
        21: invokespecial #31                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
        24: aload_2
        25: invokevirtual #32                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/St
ringBuilder;
        28: invokevirtual #36                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        31: astore_1
        32: return
      LineNumberTable:
        line 6: 0
        line 7: 10
        line 8: 13
        line 9: 32
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0      33     0  args   [Ljava/lang/String;
              10      23     1     x   Ljava/lang/String;
              13      20     2     y   Ljava/lang/String;
}

Теперь, как видно, код

At `0: new` Creates a new String Object 
At `3:dup` ; make an extra reference to the new instance

    At `4:ldc #18` as seen literal "xyz" has been placed in the pool (one string Object) 
At `6: invokespecial;` ; now call an instance initialization method with parameter and creates a object in nonpool memory.
At `9: astore_1` Stores the above reference in local variable 1(i.e x)

Итак, к этому времени у нас есть два объекта String

At `10:ldc #23` as seen literal "abc" has been placed in the pool (third string ) 

    At `12: astore_2` Stores the above reference in local variable (i.e y)

Итак, к этому времени у нас есть три объекта String

    28: invokevirtual #36 // Method java/lang/StringBuilder.toString:
()Ljava/lang/String;;(fourth String Object is Created)

Итак, у нас есть всего четыре объекта String в этом коде.

Поскольку я новичок в программировании и начал его, изучая только несколько месяцев назад, напомните мне, если я где-то ошибся и что это правильная версия. Спасибо:)

Ответ 11

Line 1:String x = new String("xyz");
Line 2:String y = "abc";
Line 3:x = x + y;

Строки неизменяемы, поэтому, если необходимо изменить существующую строковую переменную, тогда для назначения будет создан новый объект. Строка 1, строка 2 являются строковыми объектами, где, поскольку строка 3 является модификацией существующей строковой переменной, необходимо выполнить новое распределение, чтобы добавить x + y. Поэтому он должен создать создает 3 объекта.

Ответ 12

1.объекты, созданные в области кучи "xyz"//созданные с помощью String x и xyzabc//созданные с помощью x + y (объединение)

2.объекты, созданные в scp (пул строковых констант) "xyz"//созданы для будущих целей, которые недоступны для сборки мусора, а "abc"//созданы литералом 'String y'

поэтому общее количество созданных объектов в этом случае составляет 4

Ответ 13

Ответ 5

  1. XYZ в памяти без пула
  2. XYZ в памяти пула без ссылки
  3. abc в пуле памяти со ссылкой
  4. xyz все еще находится в памяти без пула, ссылка изменена на xyzabc в памяти без пула
  5. xyzabc в пуле памяти без ссылки