常量是程序运行期间恒定不变的量,许多程序设计语言都有某种方式,向编译器告知一块数据是恒定不变的,例如C++中的const和Java中的final。

根据编译器的不同行为,常量又分为编译时常量运行时常量,其实编译时常量肯定就是运行时常量,只是编译时常量在编译的时候就被执行计算,并带入到程序中一切可能用到它的计算式中。

以Java为例,static final int a = 1将是一个编译时常量,编译后的符号表中将找不到a,所有对a的引用都被替换成了1。
而static final int b = “”.length()将是一个运行时常量。测试代码如下:

class Test {
public static final int a = 10;
public static final int b = "test".length();
static {
System.out.println("Class Test Was Loaded !");
}
} public class CompilConstant {
public static void main(String[] args) {
System.out.println(Test.a);
System.out.println(Test.b);
}
}

输出:

10
Class Test Was Loaded !
4

即:
1. a被作为编译期全局常量,并不依赖于类,而b作为运行期的全局常量,其值还是依赖于类的。
2. 编译时常量在编译时就可以确定值,上例中的a可以确定值,但是b在编译期是不可能确定值的。
3. 由于编译时常量不依赖于类,所以对编译时常量的访问不会引发类的初始化。

测试:

//System.out.println(Test.b);//注释掉该条代码

执行

javac CompilConstant.java
del Test.class

也就是把编译生成的Test.class 删除,并执行java CompilConstant,输出:
10

执行反汇编:
javap -v CompilConstant

D:\N3verL4nd\Desktop>javap -v CompilConstant
Classfile /D:/N3verL4nd/Desktop/CompilConstant.class
Last modified 2017-10-21; size 440 bytes
MD5 checksum faf8cf7e41ff58ae190d78fbb7e7635c
Compiled from "CompilConstant.java"
public class CompilConstant
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #7.#16 // java/lang/Object."<init>":()V
#2 = Fieldref #17.#18 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Class #19 // Test
#4 = Methodref #20.#21 // java/io/PrintStream.println:(I)V
#5 = Fieldref #3.#22 // Test.c:I
#6 = Class #23 // CompilConstant
#7 = Class #24 // java/lang/Object
#8 = Utf8 <init>
#9 = Utf8 ()V
#10 = Utf8 Code
#11 = Utf8 LineNumberTable
#12 = Utf8 main
#13 = Utf8 ([Ljava/lang/String;)V
#14 = Utf8 SourceFile
#15 = Utf8 CompilConstant.java
#16 = NameAndType #8:#9 // "<init>":()V
#17 = Class #25 // java/lang/System
#18 = NameAndType #26:#27 // out:Ljava/io/PrintStream;
#19 = Utf8 Test
#20 = Class #28 // java/io/PrintStream
#21 = NameAndType #29:#30 // println:(I)V
#22 = NameAndType #31:#32 // b:I
#23 = Utf8 CompilConstant
#24 = Utf8 java/lang/Object
#25 = Utf8 java/lang/System
#26 = Utf8 out
#27 = Utf8 Ljava/io/PrintStream;
#28 = Utf8 java/io/PrintStream
#29 = Utf8 println
#30 = Utf8 (I)V
#31 = Utf8 b
#32 = Utf8 I
{
public CompilConstant();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 9: 0 public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: bipush 10
5: invokevirtual #4 // Method java/io/PrintStream.println:(I)V
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: getstatic #5 // Field Test.b:I
14: invokevirtual #4 // Method java/io/PrintStream.println:(I)V
17: return
LineNumberTable:
line 11: 0
line 12: 8
line 13: 17
}
SourceFile: "CompilConstant.java" D:\N3verL4nd\Desktop>

可见,对于Test.a的输出直接把bipush 10 10压入栈中。

转载自 :作者:N3verL4nd 出处: https://blog.csdn.net/lgh1992314/article/details/78303623
 

java中的编译时常量与运行时常量的更多相关文章

  1. java中最常见的几种运行时异常,你get了吗?

    NullPointerException (空指针异常) ClassCastException (类型强制转换异常) NumberFormatException (数字格式异常) NegativeAr ...

  2. Java 9 揭秘(7. 创建自定义运行时映像)

    Tips 做一个终身学习的人. 在第一章节中,主要介绍以下内容: 什么是自定义运行时映像和JIMAGE格式 如何使用jlink工具创建自定义的运行时映像 如何指定命令名称来运行存储在自定义映像中的应用 ...

  3. Java内存区域与内存溢出异常---运行时数据区域

    运行时数据区域 Java虚拟机所管理的内存将会包括以下几个运行时数据区域 线程私有区域 1.程序计数器   程序计数器记录的是当前正在执行的虚拟机字节码指令所在的地址.在虚拟机的概念模型中,字节码解释 ...

  4. Java中的栈,堆,方法区和常量池

    要说Java中的栈,堆,方法区和常量池就要提到HotSpot,HotSpot是Sun JDK 和 Open JDK中所带的虚拟机. (Sun JDK 和 Open JDK除了注释不同,代码实现基本上是 ...

  5. java中使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?

    java中使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变? 是引用对象的地址值不能变,引用变量所指向的对象的内容是可以改变. final变量永远指向这个对象,是一个常量指针,而 ...

  6. Stack overflow 编译能通过,运行时出现Stack overflow

    Stack overflow 编译能通过,运行时出现Stack overflow 大家都知道,Windows程序的内存机制大概是这样的,全局变量(局部的静态变量本质也属于此范围)存储于堆内存,该段内存 ...

  7. Java 中的编译期常量是什么?使用它又什么风险?

    公共静态不可变(public static final )变量也就是我们所说的编译期常量,这里 的 public 可选的.实际上这些变量在编译时会被替换掉,因为编译器知道这些 变量的值,并且知道这些变 ...

  8. java多态的向上转型与向下转型(与编译时类型与运行时类型有关)

    1.编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定. 当编译时类型和运行时类型不一致时,就会出现所谓的多态. 因为子类是一个特殊的父类,因此java允许把一个子类对象直接 ...

  9. 读书笔记:深入理解java虚拟机(一)虚拟机的运行时的数据区域

    最近在看深入了解java虚拟机第一版(周志明著),特此写读书笔记,整理其中重要的东西和自己的理解. ”java与c++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却 ...

随机推荐

  1. 18.18 Datasheet Note

    18.18.1 DM9000A datasheet Ethernet Controller with General Processor Interface Ethernet interface pr ...

  2. 嵌入式C语言常见的错误

    预处理的错误: #include “stdio.h”   //引用符号错误 #inlcude <name>  //自定义文件用 "  " not find gcc -I ...

  3. 为服务器设置SSL证书,配置Https协议

    注意 服务器要打开443端口 1.申请证书,这里推荐腾讯云或者阿里云的,有免费的证书,要求不高的盆友可以试一试 2.打开php.ini扩展. extension=php_openssl.dll 3.打 ...

  4. MPU9250九轴陀螺仪--读接口数据

    1.使用i2c链接到树莓派的scl , sda 接口vcc给3v引脚,gnd接树莓派gnd就ok. 2.要操作mpu必须使用mpu的寄存器实现对参数的设定以及读取,取官方下载资料看了一下,在githu ...

  5. OSPF Sham-Link配置示例

    在MPLS/VPN环境中,如果PE-CE之间使用OSPF交换路由信息,OSPF route将作为VPNv4 route(携带OSPF domain ID,OSPF Router ID,OSPF Rou ...

  6. 工控随笔_07_西门子_WinCC利用命令行实现操作log日志

    在WinCC中可以通过报警纪录来实现操作员纪录,这个需要WinCC的消息系统进行组态和配置. 利用消息系统进行实现上诉功能不但复杂而且时间久啦也不方便查询.那么有没有一种简单的方法来 实现操作员纪录呢 ...

  7. react连连看

      // Math.floor(t * Math.random()); var isInclude = function (array, element) { let alen = array.len ...

  8. 学习python第三天

    变量的命名规范 1.只能有 字母 数字 及_组成 2.不能以数字开头 3.避免与系统关键词重名:重名不会报错,但系统的功能就被自定义的功能屏蔽掉了(严重不建议这样做) 4._开头的变量都有特出含义 5 ...

  9. (最详细)小米Note 2的usb调试模式在哪里开启的教程

    当我们使用安卓手机链接Pc的时候,或者使用的有些工具比如我们学院营销团队当使用的工具引号精灵,之前使用的老版本就需要开启USB开发者调试模式下使用,现当新版本不需要了,如果手机没有开启USB开发者调试 ...

  10. 理解OpenShift(6):集中式日志处理

    理解OpenShift(1):网络之 Router 和 Route 理解OpenShift(2):网络之 DNS(域名服务) 理解OpenShift(3):网络之 SDN 理解OpenShift(4) ...