inconstant constants(变化无常的常量)

简介:

看到这个题目也许你会感到奇怪,会想我在胡说八道什么,一定又是起个怪异的名字,骗取点击率。还请你耐心看完,如果你有所收获,那么我很高兴;如果你还是觉得上当了,那我继续努力写出点有用的东西,呵呵。
其实我想了很久,也还是不知道起一个什么题目好,就套用了《 The Java Language Specification 》中的一个名词“ inconstant constants”,我把他翻译成“变化无常的常量

注:部分内容在《 使用Java中的final变量需要注意的地方 》有提到,不过我转载的原文不够详细深入,这才重新写一下。

我们还是来先看一段代码,由代码引出问题:

public class   ClassX {
   
 public static final int   X   =     2 
 ;
}

public class 
ClassTest {
   
 public static void 
main(String[] args){
      System.out.println(ClassX.X);
   }
}  

输出结果:
2

结果是显而易见的,这里需要说明的是:
根据Java语言规范,对于java中的static final变量,如果用一个在编译期间(complie time)可以计算出结果的表达式进行初始化,则用到此变量的地方会被该表达式的结果所替代。本例中,在编译期间,ClassTest.main() 函数中 ClassX.X 将被2所替代。
此时,在类ClassTest main()中不再有指向ClassX的动态链接,告诉ClassTest在运行的时候从ClassX获得X的值,你可以通过使用javap反编译器帮助你理解。
1. 先编译ClassTest.java文件
            javac ClassTest.java
2. 使用javap
            javap -c ClassTest
屏幕输出: 

Complied from "ClassTest.java"
public class ClassTest extends java.lang.Object{
public ClassTest();
   Code:
      0: aload_0
      1: invokespecial     #1; //Method java/lang/Object."<init>
 
":()V
      4: return

public static void main(java.lang.String[]);
   Code:
      0: getstatic         #2; //Field java/lang/System.out:Ljava/io/PrintStream;
      3: iconst_2 
      4: invokevirtua      #3; //Method java/io/PrintStream.println:(I)V
      7: return

}

可以看出,在调用System.out.println()之前,整数2已经被放在JVM的堆栈中,不再有指向ClassX.X的链接。如果此时,改变ClassX.X的值为1,并且重新编译ClassX.X文件,但是并不重新编译ClassTest.java文件,运行ClassTest,输出结果仍然是2.
这么做(常量替换)的一个原因是为了在编译期间检查switch case语句。switch语句中的每一个case都需要一个常量值,而且每两个之间都不能相同,编译器在编译期间将会做检查。 
如果用来给static final变量进行初始化的表达式,只能在运行时刻才可以计算出值,那么常量替换就不会发生.例如:

public class  ClassX {
   public static final int X = new  
java.util.Random().nextInt();
}  


ClassX 改变了,我们再来看一下Main.main():

Complied from "ClassTest.java"
public class ClassTest extends java.lang.Object{
public ClassTest();
   Code:
      0: aload_0
      1: invokespecial      #1; //Method java/lang/Object."<init>
 
":()V
      4: return

public static void main(java.lang.String[]);
   Code:
      0: getstatic          #2; //Field java/lang/System.out:Ljava/io/PrintStream;
      3: getstatic          #3; //Field ClassX.X:I 
      6: invokevirtual      #4; //Method java/io/PrintStream.println:(I)V
      9: return

}

此时我们可以看见有个引用指向了Field X。
( 如果把类ClassX改成Interface,仍然会出现上面的结果 ) 
当然有方法可以使你避免出现"inconstant constants"问题。
第一种方法: 
当你要声明一个编译期间常量的时候,一定要保证此变量不会或者不太可能改变,或者尽量少使用声明为static final的变量。当然这只能治标不能治本,所以我推荐使用第二种方法。
第二种方法:
将变量声明为private,同时声明一个方法来获得此变量的值 

// ClassX.java修改如下:  
public class   ClassX {
   private static final int = 2
 
;
   public  static int 
getX(){
      return 
X;
   }
}

// ClassTest.java修改如下:  

public class   ClassTest{
   public static void  
main(String[] args){
      System.out.println(ClassX.getX());
   }
}

本文转自BlogJavaOo缘来是你oO的博客,原文链接:inconstant constants(变化无常的常量),如需转载请自行联系原博主。

相关文章
|
9月前
|
安全 PHP Apache
【ThinkPHP框架教程·Part-02】开发规范和目录结构
本章节介绍ThinkPHP6.0的编码开发规范及目录结构。开发规范遵循PSR-2和PSR-4标准,涵盖命名、文件结构等;目录结构支持单应用和多应用模式,默认仅public目录对外访问,确保安全性。单应用模式下,app目录包含控制器、模型等核心组件;多应用模式允许多个app_name共存,适应复杂项目需求。配置文件与运行时文件分离,确保高效与安全。
【ThinkPHP框架教程·Part-02】开发规范和目录结构
|
9月前
|
存储 安全 Java
JVM加载过程
JVM类加载过程是Java开发中的关键环节,主要包括五个阶段:加载、验证、准备、解析和初始化。加载阶段获取类的二进制字节流;验证确保字节码符合规范;准备为静态变量分配内存并默认初始化;解析将符号引用转为直接引用;初始化执行静态变量赋值和静态代码块。了解这一过程有助于深入理解Java程序运行机制,提升编程水平。
|
10月前
|
存储 监控 安全
如何保护Active Directory 的安全性?
Active Directory (AD) 是 Microsoft 的网络资源管理服务,用于存储和管理用户、文件等信息。保护 AD 至关重要,因为安全威胁者可能通过获取初始访问权限,提升权限并最终控制域管理员帐户,导致敏感数据被删除或修改。保护措施包括持续更新和打补丁、安全管理权限、实施坚不可摧的密码策略、多因素身份验证、持续审查和监控、使用安全协议、强防火墙规则、良好的备份和恢复计划、应用安全基线和基准、提高安全意识、删除不必要的帐户和标准化组名称。通过这些措施,可以有效保护 AD 环境,确保网络安全。
125 0
|
11月前
|
移动开发 C语言
C语言:&&和&、||和|有什么区别
在C语言中,&&和||是逻辑运算符,分别表示逻辑与(AND)和逻辑或(OR),它们用于连接两个布尔表达式,只有当两边都为真时&&返回真,||在至少一边为真时返回真;&和|是位运算符,对应地进行位级的与、或操作,它们对操作数的二进制位进行逐位处理。&&和||具有短路特性,而&和|没有。
11391 1
|
算法 程序员
Facebook面试官:如何在算法面试中游刃有余?|《算法面试通关40讲》
很多大公司在面试时都尤为看中候选人的算法能力,他们甚至会让候选人当场写代码。究其原因,其实是因为算法的基础能力也会直接决定一个程序员的好坏。用武侠小说来做比喻,算法是“内功”,而编程的各种框架,就犹如各种“招式”。
3229 0
|
Unix Linux C语言
|
人工智能 算法 大数据
阿里云、天津开启多项合作,区域经济大脑落地津南
5月15日,为了进一步推动双方合作,阿里巴巴集团和天津市政府再次签署了多项落地协议。其中,阿里云将把人工智能及大数据技术落地到区域经济发展、城市管理等多个领域。 当日,天津市津南区与阿里云举行了“区域经济大脑”示范项目上线仪式。
2025 0