10
class A { static { System.out.println("A-SIB"); } static void test(){ System.out.println("A-test"); } } class B extends A { static { System.out.println("B-SIB"); } } class C { public static void main(String args []){ B.test(); } } 

When I ran class C, I thought A-SIB, B-SIB and A-test will be printed, but B-SIB was not there in the output. Can somebody explain why?

15
  • 3
    Before you continue posting, take the time to learn how to format your code in questions. Commented Mar 4, 2014 at 17:39
  • 2
    static methods are not inherited nor can they be overridden. Commented Mar 4, 2014 at 17:41
  • 1
    @SotiriosDelimanolis I didn't learn how to properly format code in question until having a week in SO. For voter to close, this question isn't too broad, it has an specific answer. Commented Mar 4, 2014 at 17:42
  • 2
    I think that when B "inherits" test(), that just tells the compiler that when it sees B.test, it will treat it the same as A.test (since it's a static method). Therefore, there is no need to load class B when B.test() is called, because it's just really calling A.test(), and no object of type B is involved. However, I don't know the exact rules. Commented Mar 4, 2014 at 17:46
  • 4
    Why the downvotes? This is actually a good question, with example code and the expected outputs. And I don't even know the answer, I'd have to dig into the JLS. Commented Mar 4, 2014 at 17:47

2 Answers 2

13

Here's what the JLS says about class initialization:

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

Initialization of an interface consists of executing the initializers for fields (constants) declared in the interface.

Before a class is initialized, its direct superclass must be initialized, but interfaces implemented by the class are not initialized. Similarly, the superinterfaces of an interface are not initialized before the interface is initialized.

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.
  • T is a class and a static method declared by T is invoked.
  • A static field declared by T is assigned.
  • A static field declared by T is used and the field is not a constant variable (§4.12.4).
  • T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.

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.

In this case, All you do in C with the class B is call the static method test(). But this method is declared in A, not in B. Thus, the JVM doesn't initialize the class B and thus doesn't invoke its static initializer block.

Note that the class B is referenced in C's byte-code and is loaded by the JVM. But it's not initialized. If you delete B.class and try to run C, you'll get an exception.

Sign up to request clarification or add additional context in comments.

Comments

1

Class B does not implement (aka "hide") the static test method, so initial execution begins within Class A (hence A-SIB); and then with the test method in A (hence "A-test"). If you override test in Class B, you will get A-SIB B-SIB B-test

2 Comments

You can't override a static method. You can hide it, but it's quite different.
Sorry .. was using the generic English word "override". I have adjusted the answer to refer to the Java-specific term.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.