java编译时确定值,java中的编译时常量与运行时常量

本文详细介绍了程序设计语言中的编译时常量和运行时常量,以C++的const和Java的final为例。通过Java代码示例展示了编译时常量在编译时即确定值并替换,而运行时常量则需要在运行时计算。讨论了两者对类初始化的影响,以及在字节码层面的表现。
摘要由CSDN通过智能技术生成

常量是程序运行期间恒定不变的量,许多程序设计语言都有某种方式,向编译器告知一块数据是恒定不变的,例如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."":()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

#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 // "":()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."":()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压入栈中。

ce3ec4ad35fda9bcfa345c2d9313ee3d.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值