如果我有一个带有常量的类,例如AppConstants
,并且从那里使用public static final
变量,如AppConstants.MY_STRING
,它将一直重新创建此类,或者在运行时创建它,因为这些字段在班上是静态的?那么在常量或“在这个地方”定义文件更好吗?
答案 0 :(得分:3)
类加载器一次加载类,通常在需要时 1 。加载类时,它的所有static
成员都会被加载,并且"与类#34;一起使用,而不是与该类的特定对象引用一起使用。使用该类的static
字段几次就不会重新启动该类。重新加载类的唯一方法是使用自定义类加载器。
最好在常量中定义文件,还是在#34;?
处定义文件
将其定义为一个类static final
字段,或使用enum
s。
1 的定义:
如果你声明这样的原始或String
常量:
public class AppConstants {
public static final int ONE = 1;
public static final int TWO = 2;
public static final int TEN = 10;
}
public class ClientTest {
public static void main(String[] args) {
System.out.println(AppConstants.ONE);
System.out.println(AppConstants.TWO);
System.out.println(AppConstants.TEN);
}
}
在编译这两个类并执行ClientTest
时,AppConstants
类不会被加载(使用HotSpot测试),因为常量将由编译器内联。为了评估结果,请执行以下操作:
> javac -cp:. AppConstants.java ClientTest.java
> javap -c ClientTest //you can see the generated bytecode
> java -verbose:class ClientTest //shows you the classes loaded to execute this app
你会看到这一点。
来自javap -c ClientTest
(正确代码):
public static void main(java.lang.String[]);
Code:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: iconst_1 //My Comment: constant with value 1
4: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
7: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
10: iconst_2 //My Comment: constant with value 2
11: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
14: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
17: bipush 10 //My Comment: constant with value 10
19: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
22: return
}
来自java -verbose:class ClientTest
:
[Opened C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.lang.Object from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
// Lots of classes from rt.jar
[Loaded java.security.UnresolvedPermission from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.security.BasicPermissionCollection from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded ClientTest from file:/D:/tmp/] //<-- Class being executed
[Loaded sun.launcher.LauncherHelper$FXHelper from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.lang.Class$MethodArray from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.lang.Void from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
1
2
10
[Loaded java.lang.Shutdown from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.lang.Shutdown$Lock from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
没有加载AppConstants
类的跟踪,只有ClientTest
。
但是如果你添加一个引用对象引用的常量,例如一个List
,然后将加载该类。从上面的例子:
public class AppConstants {
public static final int ONE = 1;
public static final int TWO = 2;
public static final int TEN = 10;
public static final List<String> NAMES = Collections.unmodifiableList(Arrays.asList("Luiggi", "Andy"));
}
public class ClientTest {
public static void main(String[] args) {
System.out.println(AppConstants.ONE);
System.out.println(AppConstants.TWO);
System.out.println(AppConstants.TEN);
System.out.println(Foo.NAMES);
}
}
现在提供java -verbose:class ClientTest
的相关输出:
//...
[Loaded ClientTest from file:/D:/tmp/] //our class being executed
[Loaded sun.launcher.LauncherHelper$FXHelper from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.lang.Class$MethodArray from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.lang.Void from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
1 //output of constants
2
10
[Loaded AppConstants from file:/D:/tmp/] //loads AppConstants class here because it's needed
[Loaded java.util.Arrays$ArrayList from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.util.AbstractList$Itr from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Luiggi, Andy] //output of AppConstants#NAMES