Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么枚举中的静态和实例init块的行为与类中的不同_Java_Enums_Initialization_Scjp_Open Closed Principle - Fatal编程技术网

Java 为什么枚举中的静态和实例init块的行为与类中的不同

Java 为什么枚举中的静态和实例init块的行为与类中的不同,java,enums,initialization,scjp,open-closed-principle,Java,Enums,Initialization,Scjp,Open Closed Principle,在学习Java认证测试时,我了解到,静态初始化块在加载类时运行一次,按照在源代码中出现的顺序,实例初始化块在每次创建实例时运行,构造函数中的代码在每次创建实例之后运行。为了测试这一点,我创建了一个包含一些静态和实例init块的类,以及一个包含打印内容的构造函数。一切都按预期工作——除了我认为“loaded”只是指在运行时,但我猜它发生在创建第一个实例时,因为除非创建至少一个类实例,否则我根本不会得到任何输出。然后我用枚举尝试了同样的方法,结果顺序都被取消了。首先,在代码中首次引用枚举时,初始化块

在学习Java认证测试时,我了解到,静态初始化块在加载类时运行一次,按照在源代码中出现的顺序,实例初始化块在每次创建实例时运行,构造函数中的代码在每次创建实例之后运行。为了测试这一点,我创建了一个包含一些静态和实例init块的类,以及一个包含打印内容的构造函数。一切都按预期工作——除了我认为“loaded”只是指在运行时,但我猜它发生在创建第一个实例时,因为除非创建至少一个类实例,否则我根本不会得到任何输出。然后我用枚举尝试了同样的方法,结果顺序都被取消了。首先,在代码中首次引用枚举时,初始化块为枚举的每个值运行一次,其次——标记为static的init块在我假设的实例init块之后运行!这与我的预期相反。下面是我的问题的分类

  • 为什么标记为static的init块在枚举中最后运行
  • 枚举是否可以具有实例初始化块
  • 为什么我认为是instance init块的块在加载枚举时只运行一次,而不是每次引用新的枚举值时都运行一次
  • 类静态初始化块在类“加载”时运行。加载是什么意思?当一个对象在类中实例化时,它是否只发生一次
  • 谢谢!这让我很困惑

    public class EnumInit {
    public static void main(String[] args) {
        System.out.println(Color.RED.toString() + " Main");
        MyInit myInit = new MyInit();
        System.out.println(Color.BLUE.toString() + " Main");
        MyInit mySecondInit = new MyInit();
    
    }
    }
    
    enum Color {    
    RED, BLUE, GREEN;
    String instanceVar = "Enum Instance Variable Text";
    static { System.out.println("Enum Static init block 1"); }
    { System.out.println("Enum Instance init block 1"); }
    static { System.out.println("Enum Static static init block 2"); }
    Color() { 
        System.out.println(instanceVar);
        System.out.println("Enum String Literal"); 
    }
    { System.out.println("Enum Instance init block 2"); }   
    }
    
    class MyInit {
    String instanceVar = "Class Instance Variable Text";
    static { System.out.println("Class Static init block 1"); }
    { System.out.println("Class Instance init block 1"); }
    static { System.out.println("Class Static static init block 2"); }
    MyInit() { 
        System.out.println(instanceVar);
        System.out.println("Class String Literal"); 
    }
    { System.out.println("Class Instance init block 2"); }  
    }
    

    除了枚举类型E从枚举继承的成员之外, 对于每个名为n的已声明枚举常量,枚举类型都有一个 隐式声明的公共静态final字段名为n,类型为E 字段的声明顺序与 对应的枚举常量,显式位于任何静态字段之前 在枚举类型中声明。每个这样的字段都初始化为枚举 与之对应的常数

    所以

    实际上是

    public static final Color RED = new Color();
    public static final Color BLUE = new Color();
    public static final Color GREEN = new Color();
    
    它将在您拥有的
    静态
    块之前得到评估

    为什么标记为static的init块在枚举中最后运行

    见上文

    枚举是否可以具有实例初始化块

    是的,编译您的代码,您将看到

    为什么我认为是instance init块的块在加载枚举时只运行一次,而不是每次引用新的枚举值时都运行一次

    初始化枚举类型后,将创建(实例化)枚举常量。您不会在任何时候创建新的
    enum

    Color color = Color.RED;
    
    您只是引用了一个已经创建的现有对象

    类静态初始化块在类“加载”时运行。加载是什么意思?当一个对象在类中实例化时,它是否只发生一次


    当类第一次在JVM中被引用时,它将由
    类加载器加载并初始化

    对于#4:类只有在得到有意义的使用后才会加载。这可能是在类上调用静态方法,或者创建实例,或者调用class.forName()或其他什么。我认为这是为了将当前加载到perma gen中的类的数量保持在最小值。因此,当每个隐式构造函数运行时,没有标记为静态的init块是否会运行,然后静态块最后运行?@paniclater是的,这些实例初始值设定项块是在
    new Color()时运行的被隐式调用。由于
    enum
    常量是您在
    enum
    主体中声明的第一件事,因此这些常量总是发生在
    enum
    中声明的任何
    静态
    块之前。谢谢,这实际上使此过程非常清楚。@paniclater欢迎您。除非有什么不清楚的事情,你可以考虑接受答案。
    Color color = Color.RED;