Заключительная строка внутри частного статического метода создает экземпляр нового объекта при вызове? - PullRequest
4 голосов
/ 16 октября 2010

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

private static String Test() {
    final String foo = "string literal";
    return foo;
}

Или компилятор знает, что внутри метода есть только один строковый литерал? Или я должен сделать это частным статическим полем финального класса? Это приводит к снижению читабельности за счет распространения кода по классу.

Ответы [ 4 ]

8 голосов
/ 16 октября 2010

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

final String foo = new String("string literal");

Тогда каждый раз при вызове метода будет создаваться новый.

Вот свидетельство:

public static void main(String[] args) throws Exception {
    String s1 = test1();
    String s2 = test1();
    System.out.println(s1 == s2); // true

    String s3 = test2();
    String s4 = test2();
    System.out.println(s3 == s4); // false
}

private static String test1() {
    final String foo = "string literal";
    return foo;
}

private static String test2() {
    final String foo = new String("string literal");
    return foo;
}

Обратите внимание, чтомодификатор final не имеет никакого влияния в данном конкретном случае.Он только запрещает переназначение переменной.

1 голос
/ 16 октября 2010

Вам не нужно слишком беспокоиться о строковых литералах.Строковые литералы обрабатываются JVM специально для повышения производительности и уменьшения накладных расходов памяти.Строковый литерал, используемый в любом месте вашего кода (локальный или другой), объединяется и повторно используется JVM.Это сделано, чтобы сократить количество объектов String, созданных в JVM.Каждый раз, когда ваш код создает строковый литерал, JVM сначала проверяет строковый литерал в пуле.Если строка уже существует в пуле, возвращается ссылка на экземпляр пула.Если строка не существует в пуле, создается новый объект String, а затем помещается в пул.Java может сделать эту оптимизацию, поскольку строки неизменяемы и могут использоваться совместно, не опасаясь повреждения данных.Однако такое поведение верно только для строковых литералов, а не для объектов, созданных с ключевым словом «new».

Таким образом, создание строкового литерала переменной класса (частное статическое конечное поле класса) или сохранение его в качестве локальной переменной имеет тот же эффект.

1 голос
/ 16 октября 2010

Только один экземпляр String создан для строкового литерала.Они хранятся в «внутреннем пуле» класса String.Итак, с учетом этих String инициализаций:

String copy = new String("x");
String alias = copy.intern();

Утверждения copy != "x" и alias == "x" являются истинными.

В этом случае было бы гораздо более читабельным, если вы простобыло поле.

0 голосов
/ 16 октября 2010

foo будет создаваться каждый раз, когда вызывается ваша функция, потому что это локальная переменная внутри метода.Тот факт, что этот конкретный метод является статическим, не имеет значения.foo, являющийся final, также не влияет на то, когда он создается, это просто означает, что foo не может измениться после первоначального присваивания.

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

...