Java常量这个“坑”

Java常量的探索

本文由此而来

先看代码:A.java

class A 
{
    public static void main(String[] args) 
    {
        System.out.println(B.WORD);
    }
}

B.java

class B
{
    public static final String WORD = "测试1";
}

运行结果自然是:

测试1


注意了,现在将 B.java 中静态字段“测试1” 改为 “测试2”,然后重新编译 B.java,再运行A类


运行结果会是什么?

测试1

没错,不是测试2,是测试1。重新编译A.java,再次运行A类
运行结果:

测试2

这时就出现问题了,真正开发中,我们往往想通过维护一部分代码来改变程序的执行效果,而出现这种情况是会让我们始料未及的。

接下来,我们来详细的探究一下原因以及解决方案

将B.java改写成如下代码:
class B
{
    static {
        System.out.println("B被使用了");
    }
    public static final String WORD = "测试3";
}

编译运行程序,结果如下

测试3

程序并没有打印“B被使用了”,这是为什么呢?
通过 javap 反编译A类的class文件可得到如下信息:

class A {
A();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object.””:()V
4: return

public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #4 // String 测试3
5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}

   3: ldc           #4                  // String 测试3

可以看出常量WORD被编译到A类的class文件中了,所以程序执行的时候并没有加载B类。也就不难明白为什么程序没有随着B类的改变而改变执行结果。
将AB两个java文件改写成如下代码:

class A 
{
    public static void main(String[] args) 
    {
        System.out.println(B.WORD);
        System.out.println(B.getWord());
    }
}

class B
{
    static {
        System.out.println("B被使用了");
    }

    public static final String WORD = "测试3";

    public static String getWord() {
        return WORD;
    }
}

程序执行结果:

测试4
B被使用了
测试4

由此可以得出,开发中使用常量时,一定要谨慎。考虑你的实现,决定是否使用get方法获取常量,或者直接使用枚举,或将常量写入配置文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值