【问题标题】:Compile-time value-binding of Java constantsJava 常量的编译时值绑定
【发布时间】:2014-08-18 19:53:20
【问题描述】:

根据最后的注释here

"如果原始类型或字符串被定义为常量并且值在编译时已知,则编译器会用其值替换代码中各处的常量名称。这称为编译时常量. 如果外界常量的值发生变化(例如,如果规定 pi 实际上应该是 3.975),则需要重新编译任何使用该常量的类来获取当前值。"

假设我在class A 中定义了一个公共常量PI (public static final double PI=3.14),并且 在class B 中使用了这个常量PI

所以 - 根据上面的规范,如果我将 PI 的值从 3.14 更改为,比如 class A 中的 3.0,我必须重新编译 class B 以获得 class B 中更改的效果.

这里的问题是——上述规范中“常数”的确切定义是什么? 是final 关键字吗?在这种情况下,是否有任何static 字段成员“有资格”作为常量? 非静态字段成员在这里会脱离上下文——它们的值是在运行时分配的(?)

TIA。

//============================

编辑:

这里的问题是:是什么让编译器决定在编译时绑定值。 static 关键字本身是否可以完成这项工作。或者还有其他东西。

//=========================

参考下面不断获得投票的快速答案:

同一页的行:

static修饰符,与final修饰符结合,也用于定义常量。final修饰符表示该字段的值不能改变。”

1.) “...用于定义常量。...”:还有什么定义常量。

2.) “... 最终修饰符组合”:final 是在编译时绑定值所必需的——我怀疑它是。

【问题讨论】:

  • 我建议改用Math.PI
  • +1,不是因为问题本身,而是因为 TIL 更改 static final 类成员的值会破坏二进制兼容性!

标签: java static constants


【解决方案1】:

您甚至没有阅读您提到的链接?

常量

static 修饰符与final 修饰符结合使用,也用于定义常量。 final 修饰符表示该字段的值不能改变。

【讨论】:

    【解决方案2】:

    JLS $ 15.28. Constant Expressions

    编译时常量表达式是表示原始类型值或字符串的表达式,它不会突然完成并且仅使用以下内容组成:

    • 原始类型的文字和字符串类型的文字(§3.10.1、§3.10.2、§3.10.3、§3.10.4、§3.10.5)

    • 转换为基本类型和转换为字符串类型(第 15.16 节)

    • 一元运算符 +、-、~ 和 ! (但不是 ++ 或 --)(§15.15.3、§15.15.4、§15.15.5、§15.15.6)

    • 乘法运算符 *、/ 和 %(第 15.17 节)

    • 加法运算符 + 和 - (§15.18)

    • 移位运算符 > 和 >>>(第 15.19 节)

    • 关系运算符 和 >=(但不是 instanceof)(第 15.20 节)

    • 等式运算符 == 和 !=(第 15.21 节)

    • 按位和逻辑运算符 &、^ 和 | (§15.22)

    • 条件与运算符 && 和条件或运算符 || (§15.23, §15.24)

    • 三元条件运算符? : (§15.25)

    • 带括号的表达式(第 15.8.5 节),其包含的表达式是常量表达式。

    • 简单名称(§6.5.6.1)引用常量变量§4.12.4)。

    • TypeName 形式的限定名称 (§6.5.6.2)。引用常量变量的标识符(第 4.12.4 节)。

    • 使用 String.intern 方法,String 类型的编译时常量表达式始终是“内部”的,以便共享唯一的实例。

    • 编译时常量表达式始终被视为 FP-strict (§15.4),即使它出现在非常量表达式不会被视为 FP-strict 的上下文中。

    编译时常量表达式用于 switch 语句 (§14.11) 中的 case 标签,对于赋值转换 (§5.2) 和类或接口的初始化 (§12.4.2) 具有特殊意义。它们还可以控制 while、do 或 for 语句正常完成的能力(第 14.21 节),以及条件运算符的类型? : 带有数字操作数。

    【讨论】:

    • 这个 - 很好。然而,这个编译时值绑定发生在哪里——常量值出现在静态上下文中的哪里?当我问这个问题时,我只想到了字段成员声明——但现在越来越大了。
    • 常数值出现的地方,句号。
    【解决方案3】:

    上述规范中“常数”的具体定义是什么?

    它必须是最终的,并且编译器可以使用表达式而不使用方法进行计算。

    它是final关键字吗?

    这是必需的。

    在这种情况下,任何静态字段成员“有资格”作为常量吗?

    不,将其设为静态是一种优化,但不是必需的。

    这里的非静态字段成员会脱离上下文——它们的值是在运行时分配的(?)

    不一定。

    【讨论】:

      【解决方案4】:
      public
      

      使变量可以从任何地方访问。

      static
      

      仅实例化变量 1 次,并让您在每次变量调用时使用相同的地址。

      final
      

      使变量本身不可更改。

      这三个都使您的变量为常量,因为它无法更改并且仅实例化一次..

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-02
        • 1970-01-01
        • 2010-09-11
        • 1970-01-01
        • 2011-11-25
        • 2011-12-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多