4

I am trying to run this code, I but found out this behavior of final with static: the code runs without executing static block of A. Please provide me with the reason.

class A {
  final static int a=9;
    static { //this block is not executing ??
      System.out.println("static block of A");
     }
}

class Manager {
  static {
    System.out.println("manager sib");
  }

  public static void main(String ...arg) {
    System.out.println("main");
    System.out.println(A.a);
  }
}

Why doesn't the static block of Class A run?

Luca Geretti
  • 10,206
  • 7
  • 48
  • 58
Sandepp1
  • 63
  • 1
  • 6

3 Answers3

7

The problem is that A.a is a constant variable.

A variable of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28), is called a constant variable.

Therefore your Manager.main method is compiled exactly as if it were:

public static void main(String ...arg) {
    System.out.println("main");
    System.out.println(9);
}

There's no real reference to A.a any more, so the A class doesn't even need to exist, let alone be initialized. (You can delete A.class and still run Manager.)

If you're relying on using A.a to make sure the type is initialized, you shouldn't add a no-op method instead:

public static void ensureClassIsInitialized() {
} 

then just call that from your main method. It's very unusual to need to do this though.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks i was not doing it in my program but it was asked to me in an interview why static block of A will not run... – Sandepp1 Mar 19 '13 at 20:13
  • Yeah ,But if `Final` would have not been there with `int a=9` then static would have worked why its not executing with final...pls help me out!! – Sandepp1 Mar 19 '13 at 20:25
  • @Sandepp1: Without `final`, it wouldn't be a compile-time constant expression. – Jon Skeet Mar 19 '13 at 20:27
1

Specification http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf Section 4.12.1 Says,

A variable of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28), is called a constant variable. Whether a variable is a constant variable or not may have implications with respect to class initialization (§12.4.1), binary compatibility (§13.1, §13.4.9) and definite assignment (§16).

As you are only accessing the constant, class initialization is not required.
David Mathias
  • 296
  • 3
  • 12
0

You can force-load whatever class you need:

public final class ClassUtils {
  private ClassUtils() {}

  public static void forceLoad(Class<?>... classes) {
    for (Class<?> clazz : classes) {
      try {
        Class.forName(clazz.getName(), true, clazz.getClassLoader());
      } catch (ClassNotFoundException e) {
        throw new AssertionError(clazz.getName(), e);
      }
    }
  }
}

class Manager {
  static {
    ClassUtils.forceLoad(A.class);
// ...
  }

  public static void main(String ...arg) {
// ...
  }
}
Luchostein
  • 2,314
  • 20
  • 24