Java类工作流
如果我有一个带有常量的类,例如AppConstants,并使用公共静态final变量,比如AppConstants.MY_STRING,它会一直重新创建这个类,或者在运行时创建它,因为类中的字段是静态的?所以,最好是在常量中定义文件还是在指定的位置定义文件?类加载程序会加载一次类,通常在需要时加载1。加载一个类时,它的所有静态成员也会加载,并与该类一起使用,而不是与该类的特定对象引用一起使用。多次使用该类的静态字段不会重新加载该类。重新加载类的唯一方法是使用自定义类装入器 在常量中定义文件更好还是在位置上定义文件更好 将它们定义为类上的静态最终字段或使用枚举 1需要时的定义: 如果像这样声明基元或字符串常量:Java类工作流,java,Java,如果我有一个带有常量的类,例如AppConstants,并使用公共静态final变量,比如AppConstants.MY_STRING,它会一直重新创建这个类,或者在运行时创建它,因为类中的字段是静态的?所以,最好是在常量中定义文件还是在指定的位置定义文件?类加载程序会加载一次类,通常在需要时加载1。加载一个类时,它的所有静态成员也会加载,并与该类一起使用,而不是与该类的特定对象引用一起使用。多次使用该类的静态字段不会重新加载该类。重新加载类的唯一方法是使用自定义类装入器 在常量中定义文件更好还
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:
现在提供java-verbose:class ClientTest的相关输出:
@我要说的是,这个问题是相关的,但并没有回答OP的问题,因为OP询问类加载。@LuiggiMendoza-这个问题的第一个答案是:每个类加载程序一个。似乎它直接回答了这个问题,但如果不是重复的话,在过去的6年里还有其他几个答案,也许,或者,或者……对不起,如果你认为我很恶劣,我真的不是,它是为了帮助人们更容易地找到正确的答案,通常有两个问题。@AndyBrown您提供的链接谈论静态成员。请理解OP的查询不是100%与静态成员相关,更多的是关于类加载。虽然解释了回答这个问题的概念,但它并没有直接做到这一点。因此OP提出了一个问题并得到了直接的答案。如果你仍然反对这一点,那么就提出一个问题并询问。我建议你再次回顾我的答案,以便更好地理解在需要时加载类意味着什么。除了重复的讨论之外,这有点误导。AFAIK公共静态最终变量的使用实际上是由编译器在可能的情况下内联的,因此相应的类根本没有通过此类引用加载。@AndyBrown我不明白您的评论有什么误导性。OP说:如果我有一个带有常量的类。。。并使用。。。从那里像AppConstants.MY_字符串一样,它会一直重新创建这个类,还是在运行时创建它,因为类中的字段是静态的?在他的特定情况下,它根本不会创建那个类——常量将被内联。在你的回答中你说。。。需要时,但不要解释在这种情况下不会加载它,因为它不是必需的。@AndyBrown如果您有一个类AppConstants,但不使用它,则不会加载它。如果您有这样一行字符串s=AppConstants.MY_字符串,并且执行了这一行,那么将使用AppConstants类,因此它将被加载一次,因为需要该类。这正是我的观点-如果这就是您所做的全部,那么该类将不会被加载。常量是内联的,因此类加载器不会加载该类。试试看,如果你愿意,我可以给你发密码。
[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]
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);
}
}
//...
[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