修改了常量,对引用它的那些类有什么影响?

有一个常量类Constant,如下:

package com.example.goodforjava.constant;

public class Constant {
    public static final int P = 100;
}

有一个测试类Test,测试类中引用了Constant类中定义的常量P,如下:

package com.example.goodforjava.betterCode;

import com.example.goodforjava.constant.Constant;

public class Test {
    public static void main(String[] args) {
        System.out.println(Constant.P);
    }
}

先分别编译下以上两个类,如下:
在这里插入图片描述

运行Test类,查看结果:
在这里插入图片描述
此时结果为100。

这时候,需求变更了,常量P的值需要改成66,但是因为项目启动太耗时了,所以开发决定直接改Constant类,如下:

package com.example.goodforjava.constant;

public class Constant {
    public static final int P = 66;
}

然后编译该类,把该类的class文件放到服务器上直接替换覆盖原先的文件,因为是本地环境,所以只需要再次编译Constant类就好了,如下:
在这里插入图片描述
然后运行Test类,查看结果:
在这里插入图片描述
发现结果竟然还是100,这样就完全不符合业务要求了。

那么为什么会这样呢?看看Test类的class文件,如下:
在这里插入图片描述
会发现常量P的值100已经直接被写到了字节码文件中了,所以如果只编译常量类Constant,而不重新编译引用了它的类比如Test类,那么Test类字节码就不会变,那么修改就是无效的,结果依旧是旧的。

总结

为了提高代码的执行效率,对于final修饰的基本类型和String类型,编译器会认为它是稳定态的,所以就像上图中class文件内容所体现的一样,编译器会直接在编译时就把值100直接写入到字节码文件中,避免了运行期引用。所以建议不要做这种直接替换类文件的操作,因为一旦修改的常量被大量的类引用,而引用该常量的那些类又没有重新编译,那引起的问题就很难排查了,特别是一般会做这种替换文件操作的,都是生产环境。

猜你喜欢

转载自blog.csdn.net/weixin_38106322/article/details/108288735
今日推荐