0

I am trying to understand the below behavior, all I am trying is to initialize the static variable of interface via enum method.

enum Hello {
    ProfileResolver();

    public Hello resolve() {
        System.out.println("resolve method called!!!!");
        return ProfileResolver;
    }
}
public interface Resolver{
  Hello hello = Hello.ProfileResolver.resolve(); // this should called when creating an instace of any implementation
}

Implentation class like below

public class Impl implements Resolver{
}

and now if

public static void main(String[] arg){
   Resolver resolver = new Impl();
}

Now at this point I was expecting just before object initialization of Impl object, hello variable of Interface must initialize and resolve method called, but it is not. And when I declare Resolver as class instead of inteface, it is working as expected. Can anyone help me try to understand ?

ernest_k
  • 39,584
  • 5
  • 45
  • 86
SBhogal
  • 27
  • 6
  • 2
    The variable `hello` in your interface is `static` and `final`. These modifiers are implicit for properties in an interface. – ernest_k Apr 05 '21 at 17:28
  • @ernest_k, i know static and final are implicit in interface, but i am trying to understand is when and how this constant "hello" gets initialized , as per my understanding as soon as class is loaded first static variables and static blocks run so in this case when i am trying to create object of Impl class , which implements Resolver interface. So did not "resolve" method should be called as this is called when initializing "hello" prior to creation of Impl object ?? – SBhogal Apr 05 '21 at 17:49
  • 1
    Because this is sensitive to your runtime, please tag your question with the compiler/IDE you're using as well as the actual Java version (if not Java 8) – ernest_k Apr 05 '21 at 18:11
  • @Sebastian, i tried to debug but resolve method is not called, but as per your suggestion it tried to reference hello variable in implementing class like `private Hello implHello = hello; and it worked. JVM version : openjdk version "1.8.0_282", Can you tell me what info i am missing here? and if it is specific to JIT optimization , did'nt it inappropriate as it is affecting end user code or logic . – SBhogal Apr 05 '21 at 18:12

1 Answers1

1

Here are the specified triggers for static initialization of types in Java. This is from the Java Language Specification

12.4.1. When Initialization Occurs
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.
  • 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).

When a class is initialized, its superclasses are initialized (if they have not been previously initialized), as well as any superinterfaces (§8.1.5) that declare any default methods (§9.4.3) (if they have not been previously initialized). Initialization of an interface does not, of itself, cause initialization of any of its superinterfaces.

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.

Invocation of certain reflective methods in class Class and in package java.lang.reflect also causes class or interface initialization.

A class or interface will not be initialized under any other circumstance.

A careful analysis indicates that your code does not meet any of the requirements for the Resolver interface's static initialization to be carried out...

  • new Impl() causes the initialization of Impl, but this does not cause the intialization of Resolver, because Resolver does not have any default methods (see my bold-italic text emphasis).

  • Nothing requires that a reference to the Resolver type should trigger initialization

  • The way to cause this code to trigger Resolver's initialization is to either add a default method to it (no point in this), or to read its static variables:

    public static void main(String[] args) throws Exception {
        Resolver resolver = new Impl();
        System.out.println(Resolver.hello); //causes initialization
    }
    

If you're using Hello hello = Hello.ProfileResolver.resolve(); to trigger some intended side-effects through the resolve() method, then please don't.

ernest_k
  • 39,584
  • 5
  • 45
  • 86