编译时常量:
这种类型的常量的值早在编译期间就已经确定,相当于这个常量值被固化到APP安装包里,APP在何时、何处安装运行,编译时常量的值都是统一且唯一的,不会随环境的变化而产生任何变化。
运行时常量:
严格意义上说不算是常量。常量应该是一个仅能赋值一次的只读属性。运行时常量的赋值操作可以在声明属性时就赋值,也可以在首次使用的时候赋值,赋值的时候还可以吧另外一个变量的数值赋值给val变量。App在每次启动运行之后,运行时常量都可能被赋予不同的数值,只是一旦完成赋值,其值就不能再做修改。
综上所述,编译时常量才是真正意义上的常量,而运行时常量是为伪常量。
举个例子
- public static final int a = 10就是一个编译时常量,在编译后的符号中找不到a,所有对a的引用都被替换成了20;它是不依赖于类的,在编译时就可以确定值。
- public static final int b = “hello”.length()就是一个运行时常量;它是依赖于类的,它的赋值会引起类的初始化。
- 归根结底还是javac的编译机制导致了这样的结果。当涉及到方法的调用时,必须在运行的时候才能确定结果。
public class ConstantTest {
public final int a = 1; //编译时常量
public final int b = 1+2; //编译时常量 支持加减乘除等简单运算
public final int c = b+3; //编译时常量
public final static int d = 10; //编译时常量
public final String str1 = "abc"; //编译时常量
public final String str2 = "def" + "ghi"; //编译时常量 支持字符串的连接
public final String str3 = str2 + "jkl"; //编译时常量
public final static String str4 = "static str"; //编译时常量
public final double e = Math.random(); //运行时常量
public final ConstantTest test = new ConstantTest(); //运行时常量
}