java static initialization with inheritance

▼魔方 西西 提交于 2020-01-21 06:13:29

问题


public class Main {

    public static void main(String[] args) {
        System.out.println(B.x);
    }

}
class A {
    public static String x = "x";
}
class B extends A {
    static {
        System.out.print("Inside B.");
    }
}

Question: Why output will be: x. But not: Inside B.x


回答1:


The reference to B.x issues the following bytecode:

getstatic       #3   <Field int B.x>

According to Java Virtual Machine Spec

The Java virtual machine instructions anewarray, checkcast, getfield, getstatic, instanceof, invokedynamic, invokeinterface, invokespecial, invokestatic, invokevirtual, ldc, ldc_w, multianewarray, new, putfield, and putstatic make symbolic references to the runtime constant pool. Execution of any of these instructions requires resolution of its symbolic reference.

So the JVM should resolve the symbolic reference to B.x. The field resolution is specified like this:

To resolve an unresolved symbolic reference from D to a field in a class or interface C, the symbolic reference to C given by the field reference must first be resolved (§5.4.3.1).

...

When resolving a field reference, field resolution first attempts to look up the referenced field in C and its superclasses:

If C declares a field with the name and descriptor specified by the field reference, field lookup succeeds. The declared field is the result of the field lookup.

Otherwise, field lookup is applied recursively to the direct superinterfaces of the specified class or interface C.

Otherwise, if C has a superclass S, field lookup is applied recursively to S.

Otherwise, field lookup fails.

In other words the JVM will resolve B.x into A.x. This is why only A class needs to be loaded.




回答2:


Because B.x is actually A.x so only the A class needs to be loaded.




回答3:


§12.4 "Initialization of Classes and Interfaces" of The Java Language Specification, Java SE 7 Edition specifies that:

Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class.

[…]

A reference to a static field (§8.3.1.1) causes initialization of only the class or interface that actually declares it, even though it might be referred to through the name of a subclass, a subinterface, or a class that implements an interface.

So although — contrary to claims in some of the answers above — class B does have to be loaded, in order to determine that B.x is declared in A, class B is not initialized (i.e., its static initializers are not actually run) until you do something more specific to B.




回答4:


It doesn't actually need to load B until it accesses a static member of B directly. Note that this code:

public class TestMain {
    public static void main(String[] args) {
        System.out.println(B.x);
        System.out.println(B.y);
    }

    static class A {
        public static String x = "x";
    }

    static class B extends A {
        public static String y = "y";
        static {
            System.out.print("Inside B.");
        }
    }
}

Will output:

x
Inside B.y

Because it doesn't need to load B until something in B is accessed.

Here's a good link on the subject. From the article, "And dont forget, this code will be executed when JVM loads the class. JVM combines all these blocks into one single static block and then executes. Here are a couple of points I like to mention: "




回答5:


Class B extends A which has an public static variable x which you are accessing when you call B.x

If you expect Inside B. as out put you have to create an Object of that class. All the static code blocks are executed. or move that static code block to class A :-)

When JVM loads class it groups all the static blocks and execute them in the sequence they are declared.

EDIT (Source): The short answer is that statics are NOT inherited in Java. Rather, the static members declared in a class are (subject to "access" restrictions) directly visible in the namespace of derived classes, unless they "hidden" by declarations in the derived class.

So if the Static belongs to the Class only why does it trickle down to the derived class ? Shouldn't it just stay with the Class in which it was defined ?



来源:https://stackoverflow.com/questions/13475172/java-static-initialization-with-inheritance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!