类加载
现有如下代码
/* * 对于静态字段来说,只有直接定义了该字段的类才会被初始化 * 当一个类在初始化时,要求其父类全部都已经初始化完毕了 * -XX:+TraceClassLoading,用于追踪类的加载信息并打印出来 */ public class MyTest{
public static void main(String[] args) {
System.out.print("输出MyChild.str1\n"); System.out.println(MyChild.str1); } } class MyParent{
public static String str1 = "hello world"; static {
System.out.println("MyParent static block"); } } class MyChild extends MyParent{
public static String str2 = "welcome"; static {
System.out.println("MyChild static block"); } }
JVM参数
所有的JVM参数都以 -XX: 开始,若后面为
+,表示开启option选项-,表示关闭option选项,表示将option选项的值设置为value
常量
public class MyTest2 {
public static void main(String[] args) {
System.out.println(MyParent2.str); } } class MyParent2{
public static final String str = "hello world"; static {
System.out.println("MyParent static block"); } }
在str前加上final关键字后
// 常量在编译阶段会被存到调用这个常量的方法的类的常量池中 public class MyTest2 {
public static void main(String[] args) {
System.out.println(MyParent2.str); } } class MyParent2{
public static final String str = "hello world"; static {
System.out.println("MyParent static block"); } }
重点:
- 常量会被存入到调用该常量的方法所在的类的常量池中
- 本质上,调用类并没有直接引用到定义该常量的类,因此不会触发定义常量的类的初始化
- 这里是将常量
str存放到MyTest2的常量池中,之后MyTest2与MyParent2就没有任何关系了 - 甚至我们可以在运行一次后将MyParent2的class文件删除,而不会对结果产生任何影响
此时打开Terminal进入class文件所在的目录,使用javap -c MyTest2.class对class文件反编译的到下图

对比不加final关键字时的反编译信息

可见助记符ldc后面是一个String类型的字符串,而不再是MyParent2.str的变量
ldc:表示将int,float或是String类型的常量值从常量池中推送至栈顶
若使用如下代码:
public class MyTest2 {
public static void main(String[] args) {
System.out.println(MyParent2.s); } } class MyParent2{
public static final short s = 7; static {
System.out.println("MyParent static block"); } }
bipush:表示将单字节(-128 ~ 127)得常量值推送至栈顶
public class MyTest2 {
public static void main(String[] args) {
System.out.println(MyParent2.i); } } class MyParent2{
public static final int i = 128; static {
System.out.println("MyParent static block"); } }
sipush:表示将一个短整型常量值(-32768 ~ 32767)推送至栈顶
public class MyTest2 {
public static void main(String[] args) {
System.out.println(MyParent2.m); } } class MyParent2{
public static final int m = 1; static {
System.out.println("MyParent static block"); } }
iconst_1:表示将int类型1推送至栈顶(iconst_1 ~ iconst_5)
总结
常量
若使用 final 关键字,则得到常量。在编译阶段,常量会被存入到调用该常量的方法所在的类的常量池中,再次调用此常量时不一定会初始化定义其值的类,而是初始化调用该常量的方法所在的类。
助记符
ldc:表示将int,float或是String类型的常量值从常量池中推送至栈顶bipush:表示将单字节(-128 ~ 127)得常量值推送至栈顶sipush:表示将一个短整型常量值(-32768 ~ 32767)推送至栈顶iconst_1:表示将int类型1推送至栈顶(iconst_1 ~ iconst_5)
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/177603.html原文链接:https://javaforall.net
