【问题标题】:why are java constants declared static?为什么java常量声明为静态的?
【发布时间】:2011-12-26 22:51:21
【问题描述】:

为什么java常量声明为静态的?

class Foo{
    static final int FII = 2 ;
}

在这我明白final的用法了吗?购买为什么它必须是静态的?为什么它应该是类变量,而不是实例变量?

【问题讨论】:

  • 您为什么希望多个实例拥有自己的FII 副本?
  • 我可以声明final int FII = 2;就好了。
  • @JonLin:可以,但不应该这样做,因为它不会增加价值,只会增加内存使用量。例外是在构造函数调用中初始化常量 - 然后每个实例都可以有它自己的常量值(构造函数运行后的常量)并且可以有一个类似“constructionTime”或类似的值。

标签: java static constants final class-variables


【解决方案1】:

如果常量不是静态的,Java 将在类的每个对象中为该常量分配内存(即每个对象有一个常量副本)。

如果常量是静态的,则该类将只有一个常量副本(即每个类一个副本)。

因此,如果常量只有一个值,就应该声明为静态的。

如果常量可能对每个对象有不同的值,例如对象的创建时间,则不应将其声明为静态。

【讨论】:

  • “如果常数可能对每个对象有不同的值”,那么根据定义它不是常数。
  • @Jezor 不,这是一个常数。同一类的对象可以具有具有不同值的相同常量。 “例如对象的创建时间”。
  • 我明白了。将其称为“常数”可能在技术上是正确的,但听起来很奇怪。有了这个,每个声明为final 的不可变对象都是一个常量,无论范围如何。
  • @Rain 实际上,根据 java 规范,原始类型或 String 类型的变量,它是 final 并使用编译时常量表达式(第 15.28 节)初始化,称为常量变量。创建对象期间的常量超出了编译时间的目的
  • @SameerSinha 在编译时或运行时定义常量值都没有关系,这不会改变它是常量的事实(初始化后无法更改的值)。例如,在 PHP 语言中,我们有 constdefine 一个将在编译时评估,另一个在运行时评估,但最重要的是它们都创建了一个常量。
【解决方案2】:

如果它可能因类的实例而异,那么它显然不是一个常量。为Math 的每个实例获取不同的 pi 值意味着什么(不是Math 甚至允许构造实例)?还是为String 的每个实例使用不同的不区分大小写的顺序?

【讨论】:

    【解决方案3】:

    这只是为了让您无需该类的实例即可访问它们。

    要求创建实例只是为了访问常量字段有点浪费资源。

    【讨论】:

      【解决方案4】:

      为什么java常量声明为静态的?

      技术上它们不是,JLS 将常量定义为最终常量表达式(在 java 中称为 compile time constant expression,但不是正式的)。表示声明为 final 的变量,它使用常量表达式初始化,表示没有静态 - https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.12.4

      常量变量是原始类型或字符串类型的最终变量,使用常量表达式初始化。

      但是该规范没有解决任何关于 Constant Types java 的全部内容,类和对象 - 所以 Jon Skeet 关于 Math 示例的答案缺少一部分,Math 类被认为是常量,因为你不能通过将其构造函数设为私有来实例化它。

      http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/Math.java-

      public final class Math {
      
      
          /**
      
           * Don't let anyone instantiate this class.
      
           */
      
          private Math() {}
      
          public static final double PI = 3.14159265358979323846;
      
      }
      

      要支持类型本身保持不变,您需要确保它的状态也是不变的,但仅限于其成员是可变的并且暴露于来自类型外部的更改。

      例如,文字 PI 是公开的,因此可以从类型外部使用。因此,为了确保不会从外部对其进行更改,它是最终的,也是静态的,因此它将成为 Class Class<Math> 实例的一部分,并且可以在没有(显式)实例化类的情况下公开以供在 Math 外部使用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-23
        • 2013-03-05
        • 1970-01-01
        • 1970-01-01
        • 2011-04-04
        • 1970-01-01
        • 2016-11-22
        • 1970-01-01
        相关资源
        最近更新 更多