美文网首页
编译期常量运行期常量

编译期常量运行期常量

作者: rock_fish | 来源:发表于2018-06-01 11:26 被阅读0次

所属文集:ClassLoader串烧


编译期常量

在编译阶段,常量就被放到使用这个常量的方法的所在的类的常量池中
调用类,并没有直接引用到定义常量的类,因此不会触发定义常量的类 的初始化。
因此两者没有了关联,删除定义常量的类的.class文件也不影响。
如:i'm strChild会被放到Test06的常量池中。

摘自https://www.cnblogs.com/grefr/p/6094871.html
以Java为例,static final int a = 1将是一个编译时常量,编译后的符号表中将找不到a,所有对a的引用都被替换成了1
对于这句话,要确认如何查看符号表,怎么识别变成了1

案例1:

public class Test06 {
    public static void main(String[] args) {
        System.out.println(MyChild.strChild);
        //只输出:i'm strChild
        //System.out.println(MyParent.strParent);
        //只输出:i'm parent
    }
}
class MyChild extends MyParent {
    public static final String strChild = "i'm strChild";
    static {
        System.out.println("this is MyChild static...");
    }
}
class MyParent {
    public static final String strParent ="i'm parent";
    static {
        System.out.println("this is MyParent static");
    }
}
image.png
ldc命令参考

四、ldc系列
该系列命令负责把数值常量或String常量值从常量池中推送至栈顶。该命令后面需要给一个表示常量在常量池中位置(编号)的参数,
哪些常量是放在常量池呢?比如:final static int id=32768;final static float double=6.5。
对于const系列命令和push系列命令操作范围之外的数值类型常量,都放在常量池中.
另外,所有不是通过new创建的String都是放在常量池中的。
指令码 助记符 说明
0x12 ldc 将int, float或String型常量值从常量池中推送至栈顶
0x13 ldc_w 将int, float或String型常量值从常量池中推送至栈顶(宽索引)
0x14 ldc2_w 将long或double型常量值从常量池中推送至栈顶(宽索引)


运行期常量

public class Test07 {
    public static void main(String[] args) {
        System.out.println(MyParent07.a);
        System.out.println(MyParent07.str);
        System.out.println(MyParent07.str);
    }
}
class MyParent07{
    public static final String str = UUID.randomUUID().toString();
    public static final int a = 10;
    static {
        System.out.println("MyParent07 static executed");
    }
}

查看输出

[Loaded sun.nio.cs.US_ASCII$Decoder from C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar]
10//先输出了10,之后才加载了MyParent07这个类
[Loaded MyParent07 from file:/C:/Users/rock/IdeaProjects/jvm-learn-07/jvmlearn07/target/classes/]
[Loaded java.util.UUID from C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar]
[Loaded java.util.UUID$Holder from C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar]
...
n多类加载信息忽略
...
MyParent07 static executed//静态代码块执行,只有首次加载才执行初始化
19019819-1961-4e92-8816-8d2dab9df34c//输出结果
19019819-1961-4e92-8816-8d2dab9df34c//输出结果
[Loaded java.lang.Shutdown from C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar]
[Loaded java.lang.Shutdown$Lock from C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar]

Process finished with exit code 0

MyParent07.str是运行期常量;
不在调用者所在类的常量池中;
System.out.println(MyParent07.str);这样的调用就是对MyParent07的主动调用,会引起类的初始化(初始化之前肯定要先加载);

相关文章

  • 编译期常量运行期常量

    所属文集:ClassLoader串烧 编译期常量 在编译阶段,常量就被放到使用这个常量的方法的所在的类的常量池中调...

  • 常量

    常量  Java中由final修饰的就是常量。如下:  分类:编译期常量和运行时常量 编译期常量:它的值在编译期就...

  • 编译期常量与运行期常量的区别

    我们先来看一下下面这个程序 运行程序,输出: 很明显访问MyParent2的常量,并不会导致MyParent2的初...

  • 02_JVM学习笔记_类加载机制详解二

    编译期常量与运行期常量的区别 如下代码执行后会输出什么结果? 输出 修改后的代码执行后会输出什么结果? 输出 小结...

  • 巧用 readonly与 const

    c# 中的常量有两种,分别是编译期常量和运行期常量。通过名字我们就可以看出来它俩在行为上是不同的。在开发中如果这两...

  • Java基础-String可以多长

    主要分编译期和运行期。1.编译期 这样定义的字符串在编译期就已经确定了,aaa字符串存放在方法区的常量池。代码编译...

  • Java知识点总结

    static final 和 static 的区别 static+final 静态常量,编译期常量,编译时就确定值...

  • Java常量和C#常量

    常量是固定值,程序执行期间不会改变。常量可以是整数常量、浮点常量、字符常量或者字符串常量,还有枚举常量。 1. 定...

  • 改善Java程序建议2

    建议2:莫让常量蜕变成变量 RAND_CONST 这种常量的定义方式是极不可取的,常量就是常量,在编译期就必须确定...

  • 字符串常量池

    静态常量池,运行期常量池,字符串常量池 静态常量池 运行时常量池 字符串常量池 问题 结果: 验证new Stri...

网友评论

      本文标题:编译期常量运行期常量

      本文链接:https://www.haomeiwen.com/subject/xocylftx.html