Is final ill-defined?

前端 未结 6 1732
野的像风
野的像风 2021-01-30 02:39

First, a puzzle: What does the following code print?

public class RecursiveStatic {
    public static void main(String[] args) {
        System.out.println(scale         


        
6条回答
  •  南方客
    南方客 (楼主)
    2021-01-30 03:17

    Class level members can be initialized in code within the class definition. The compiled bytecode cannot initialize the class members inline. (Instance members are handled similarly, but this is not relevant for the question provided.)

    When one writes something like the following:

    public class Demo1 {
        private static final long DemoLong1 = 1000;
    }
    

    The bytecode generated would be similar to the following:

    public class Demo2 {
        private static final long DemoLong2;
    
        static {
            DemoLong2 = 1000;
        }
    }
    

    The initialization code is placed within a static initializer which is run when the class loader first loads the class. With this knowledge, your original sample would be similar to the following:

    public class RecursiveStatic {
        private static final long X;
    
        private static long scale(long value) {
            return X * value;
        }
    
        static {
            X = scale(10);
        }
    
        public static void main(String[] args) {
            System.out.println(scale(5));
        }
    }
    
    1. The JVM loads the RecursiveStatic as the jar's entry point.
    2. The class loader runs the static initializer when the class definition is loaded.
    3. The initializer calls the function scale(10) to assign the static final field X.
    4. The scale(long) function runs while the class is partially initialized reading the uninitialized value of X which is the default of long or 0.
    5. The value of 0 * 10 is assigned to X and the class loader completes.
    6. The JVM runs the public static void main method calling scale(5) which multiplies 5 by the now initialized X value of 0 returning 0.

    The static final field X is only assigned once, preserving the guarantee held by the final keyword. For the subsequent query of adding 3 in the assignment, step 5 above becomes the evaluation of 0 * 10 + 3 which is the value 3 and the main method will print the result of 3 * 5 which is the value 15.

提交回复
热议问题