Для примера кода
public class Main {
private static final String HELLO = "hello";
private static final String WORLD = "world";
private static void goodMethod(){
System.out.println(HELLO);
System.out.println(WORLD);
}
private static void badMethod(){
System.out.println("hello");
System.out.println("world");
}
}
Нет никакой разницы между goodMethod()
и badMethod()
.
Ключевым моментом является то, что не только "hello"
и "world"
являются константами времени компиляции, но HELLO
и WORLD
также.
Как Спецификация языка Java® выражает это:
A константа - это final
переменная примитивного типа или типа String
, которая инициализируется константным выражением ( §15.28 ).Является ли переменная постоянной или нет, может иметь значение в отношении инициализации класса ( §12.4.1 ), двоичной совместимости ( §13.1 ), достижимости ( §14.21) и определенное назначение ( §16.1.1 ).
И в §13.1 :
Ссылка на поле, являющееся постоянной переменной ( §4.12.4 ), должна быть разрешена во время компиляции до значения V, обозначаемого инициализатором постоянной переменной.
Если такое полестатический, тогда в коде двоичного файла не должно быть ссылки на поле, включая класс или интерфейс, объявивший поле.
Другими словами, поле ссылается на HELLO
иWORLD
разрешается во время компиляции и заменяется их постоянными значениями, как если бы вы записали эти значения в первую очередь.
Вы можете убедиться в этом, посмотрев на байт-код, например, javap -p -c Main
:
Compiled from "Main.java"
public class Main {
private static final java.lang.String HELLO;
private static final java.lang.String WORLD;
public Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
private static void goodMethod();
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #4 // String hello
5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: ldc #6 // String world
13: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
16: return
private static void badMethod();
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #4 // String hello
5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: ldc #6 // String world
13: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
16: return
}
Вам не нужно нижнее бельево всех подробностях байт-код, чтобы увидеть, что скомпилированный код обоих методов, goodMethod()
и badMethod()
, идентичен.Конечно, идентичный код не может иметь различий в производительности, связанных с тем, как он был создан.
То же самое относится и ко второму примеру, нет разницы между использованием строкового литерала или постоянной переменной.
Что касается стиля кодирования, я согласен с Ответом Питера Лоури .Использование постоянной переменной не улучшает код, если его имя не дает дополнительного значения.Без такого значения фактическое значение говорит больше, чем имя переменной.Смотри также этот ответ .