i've been taught that in java static init block will be called before any instance of object will be created, but I faced a situation while playing with old singleton pattern (not to discuss why it's good or bad pattern). In the example below i have two implementations of lazy singleton and second breaks order in which ctor & static init blocks are called.
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SingletonDemo {
static class demo1 {
static class SingletonHolder {
static final Singleton INSTANCE = new Singleton();
}
static class Singleton {
public static Singleton instance() {
return SingletonHolder.INSTANCE;
}
static {
log.info("Singleton1$static");
}
public Singleton() {
log.info("Singleton1$init");
}
}
}
static class demo2 {
static class SingletonHolder {
public static Singleton instance() {
return Singleton.INSTANCE;
}
}
static class Singleton {
static final Singleton INSTANCE = new Singleton();
static {
log.info("Singleton2$static");
}
public Singleton() {
log.info("Singleton2$init");
}
}
}
public static void main(String[] args) {
demo1.Singleton.instance();
demo2.SingletonHolder.instance();
}
}
and output is as follows:
04:50:36.815 [main] INFO SingletonDemo - Singleton1$static
04:50:36.831 [main] INFO SingletonDemo - Singleton1$init
04:50:36.831 [main] INFO SingletonDemo - Singleton2$init
04:50:36.831 [main] INFO SingletonDemo - Singleton2$static
so the question is why ?
CodePudding user response:
Static fields with initializers and static blocks are executed in their textual order (see JLS, §12.1.3). Hence, the c'tor call
static final Singleton INSTANCE = new Singleton();
is executed before the static initializer block.
CodePudding user response:
really not, -- this is supposed to be comment on previous answer but message size limit :(
I am beginning slowly understand why (of course java spec is absolutely right - static block is called before ctor) and order of initialization is not fields and then static init block, problem here is that log messages give wrong impressions on what happens, let's change order of second example a bit
static class Singleton {
static {
log.info("Singleton2$static#1");
}
static final Singleton INSTANCE = new Singleton();
static {
log.info("Singleton2$static#2");
}
public Singleton() {
log.info("Singleton2$init");
}
}
}
then it works as expected
05:16:18.130 [main] INFO SingletonDemo - Singleton2$static#1
05:16:18.130 [main] INFO SingletonDemo - Singleton2$init
05:16:18.130 [main] INFO SingletonDemo - Singleton2$static#2
i think java combined all static blocks and field init into one giant static block which is really being executed before anything else - but in the middle of it i need to create instance of object and i do it - even though static init block is not completed yet