Java 静态最终变量和静态初始值设定项块

Java 静态最终变量和静态初始值设定项块,java,Java,我创建了一个包含以下内容的类: static final变量 static带有System.out.println()语句的初始值设定项块 如果我从另一个类调用static final变量,则不会执行static块 据我所知,静态初始化程序块在类加载到内存中时执行 在这种情况下,内存级别发生了什么 类是否未加载到内存中?如果不是,其他类从哪里获取最终静态变量的地址 情况1:静态块不执行 class Test2 { static final int a = 20; static

我创建了一个包含以下内容的类:

  • static final
    变量
  • static
    带有
    System.out.println()语句的初始值设定项块
  • 如果我从另一个类调用
    static final
    变量,则不会执行
    static

    据我所知,
    静态
    初始化程序块在类加载到内存中时执行

    在这种情况下,内存级别发生了什么

    类是否未加载到内存中?如果不是,其他类从哪里获取
    最终静态变量的地址


    情况1:
    静态
    块不执行

    class Test2 {
        static final int a = 20;
    
        static {
            System.out.println("one");
        }
    }
    
    情况2:
    静态
    块不执行

    输出

    class Test {
        public static void main(String[] args) {
            System.out.println(Test2.a);
        }
    }
    
    • 案例1:

      20
      
    • 案例2:

      one
      20
      
    那么,在这两个层面都发生了什么

  • 静态final字段是编译时常量,其值为 硬编码到目标类中,不引用其 起源

  • 因此,主类不会触发类的加载 包含字段

  • 因此,不会执行该类中的静态初始值设定项


  • 请参见从定义中删除
    final
    的魔术。您将看到静态初始化器正在执行

    我猜您的字段是基元类型或
    字符串
    ,并使用编译时常量表达式初始化

    对于使用常量表达式初始化的静态final字段(并且只有这样的字段)——任何引用该字段的代码都将在其中烘焙常量值,而不是通过静态字段进行初始化,这将导致类初始化。“常量表达式”部分很重要。我们可以通过一个小测试应用程序看到这一点:

    class Fields {
        
        public static final String CONSTANT = "Constant";
        public static final String NON_CONSTANT = new String("Non-constant");
        
        static {
            System.out.println("Initializing");
        }
    }
    
    public class Test {
        public static void main(String arg[]) {
            System.out.println(Fields.CONSTANT);
            System.out.println(Fields.NON_CONSTANT);
        }
    }
    
    输出为:

    Constant
    Initializing
    Non-constant
    
    访问常量字段不需要初始化,但访问非常量字段需要初始化。使用非final字段也会产生同样的效果:它基本上不再作为常量计算

    关于“thisaconstant”的信息被烘焙到声明字段的类中。例如,使用
    javap-c字段
    我们可以看到两个字段:

    public static final java.lang.String CONSTANT;
      flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
      ConstantValue: String Constant
    
    public static final java.lang.String NON_CONSTANT;
      flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    
    请注意
    常量
    字段元数据的
    常量值
    部分,该部分在
    非常量
    字段元数据中缺失

    有关什么构成常量表达式的详细信息,请参见

    指定初始化类的时间:

    类或接口类型T将在第一次出现以下任一情况之前立即初始化:

    • T是一个类,并且创建了T的一个实例

    • T是一个类,调用由T声明的静态方法

    • 分配了一个由T声明的静态字段

    • 使用由T声明的静态字段,该字段不是常量变量(§4.12.4)

    • T是一个顶级类(§7.6),执行嵌套在T(§8.1.3)中的assert语句(§14.10)


    (我的重点。)

    发布您的代码!不知道你的问题是什么。您能提供一个示例代码吗?描述代码几乎总是不如仅仅显示它—理想情况下是一个简短但完整的程序来演示问题。您也可以发布输出吗?这实际上不是全部内容—它不适用于所有静态最终字段,正如您的第一点所暗示的那样。请参阅我的答案了解更多详细信息。实际上,我是在代码中第一次出现类名时阅读的。该时间类加载到内存中。是这样吗?如果加载类时出错?@deepak:这是错误的,正如您所看到的-有关初始化类的详细信息,请参阅我的编辑。第12.4.1节中的项目符号3可能会让人相信
    常量
    被赋值为“常量”,从而导致类初始化,但该字段被初始化,因此项目符号3不适用。可以帮助区分字段初始化和赋值。顺便说一句,同一部分中的项目符号5已经不正常了。@Ichiro:修复了项目符号。我会留下你的评论来为自己说话。
    public static final java.lang.String CONSTANT;
      flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
      ConstantValue: String Constant
    
    public static final java.lang.String NON_CONSTANT;
      flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL