When do we say class is loaded in java? - java

What does it mean when we say a class is "loaded"?
For example it is said that Static init blocks are executed at the time of class loading. When exactly class is loaded?
Please see this code from Kathy Sierra's book:
class Bird {
{
System.out.print("b1 ");
}
public Bird() {
System.out.print("b2 ");
}
}
class Raptor extends Bird {
static {
System.out.print("r1 ");
}
public Raptor() {
System.out.print("r2 ");
}
{
System.out.print("r3 ");
}
static {
System.out.print("r4 ");
}
}
class Hawk extends Raptor {
public static void main(String[] args) {
System.out.print("pre "); //1
new Hawk();//2
System.out.println("hawk ");
}
}
The output of above code is: r1 r4 pre b1 b2 r3 r2 hawk
I cant not understand howcome pre is printed after r1. Which part of the code loaded Raptor class?
One of the answer says :
"the class is initialized at the last possible moment, but before any of its members is accessed".
But by that logic, shouldn't pre be printed BEFORE r1? Since line 2 accesses constructor of class Raptor AFTER execution of line1.

Don't confuse class loading, which is implementation-specific, and class initialization, which is very strictly specified. Unfortunately these two terms are often used as if they meant the same thing, but usually the phrase "the time of class loading" refers to the time of class initialization.
As an executive summary of the detailed case-by-case rules, the class is initialized at the last possible moment, but before any of its members is accessed.
With that part cleared up, in the code of your example you have a class Hawk extends Raptor extends Bird. Hawk is the class containing the entry point of your program, the method main. This is the init order:
Start initializing Hawk. Is its parent class Raptor initialized? no.
Start initializing Raptor. Is its parent Bird initialized? no.
Start initializing Bird.
Complete initializing Bird.
Execute Raptor's static init blocks. This prints r1 r4.
Complete initializing Raptor.
Complete initializing Hawk.
Start executing Hawk.main(). This prints pre.

Usually when you first attempt to use the class, e.g. try to create an instance, use one of its static methods or store reference to the class' Class<?> object.
Note that this may depend on the classloader implementation.

Different JVMs load classes in different ways, but the basic rule is only loading classes when they are needed. If there are some other classes that are required by the loaded class, they will also be loaded. The loading process is recursive.
Below code is simple example of class and static block,variable laoding.
public class Foo {
//instance variable initializer
String s = "abc";
//constructor
public Foo() {
System.out.println("constructor called");
}
//static initializer
static {
System.out.println("static initializer called");
}
//instance initializer
{
System.out.println("instance initializer called");
}
public static void main(String[] args) {
new Foo();
new Foo();
}
}
Output for above program :
static initializer called
instance initializer called
constructor called
instance initializer called
constructor called

Related

Unfamiliar Java Syntax [duplicate]

We can put code in a constructor or a method or an initialization block. What is the use of initialization block? Is it necessary that every java program must have it?
First of all, there are two types of initialization blocks:
instance initialization blocks, and
static initialization blocks.
This code should illustrate the use of them and in which order they are executed:
public class Test {
static int staticVariable;
int nonStaticVariable;
// Static initialization block:
// Runs once (when the class is initialized)
static {
System.out.println("Static initalization.");
staticVariable = 5;
}
// Instance initialization block:
// Runs each time you instantiate an object
{
System.out.println("Instance initialization.");
nonStaticVariable = 7;
}
public Test() {
System.out.println("Constructor.");
}
public static void main(String[] args) {
new Test();
new Test();
}
}
Prints:
Static initalization.
Instance initialization.
Constructor.
Instance initialization.
Constructor.
Instance initialization blocks are useful if you want to have some code run regardless of which constructor is used or if you want to do some instance initialization for anonymous classes.
would like to add to #aioobe's answer
Order of execution:
static initialization blocks of super classes
static initialization blocks of the class
instance initialization blocks of super classes
constructors of super classes
instance initialization blocks of the class
constructor of the class.
A couple of additional points to keep in mind (point 1 is reiteration of #aioobe's answer):
The code in static initialization block will be executed at class load time (and yes, that means only once per class load), before any instances of the class are constructed and before any static methods are called.
The instance initialization block is actually copied by the Java compiler into every constructor the class has. So every time the code in instance initialization block is executed exactly before the code in constructor.
nice answer by aioobe
adding few more points
public class StaticTest extends parent {
static {
System.out.println("inside satic block");
}
StaticTest() {
System.out.println("inside constructor of child");
}
{
System.out.println("inside initialization block");
}
public static void main(String[] args) {
new StaticTest();
new StaticTest();
System.out.println("inside main");
}
}
class parent {
static {
System.out.println("inside parent Static block");
}
{
System.out.println("inside parent initialisation block");
}
parent() {
System.out.println("inside parent constructor");
}
}
this gives
inside parent Static block
inside satic block
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside main
its like stating the obvious but seems a little more clear.
The sample code, which is approved as an answer here is correct, but I disagree with it. It does not shows what is happening and I'm going to show you a good example to understand how actually the JVM works:
package test;
class A {
A() {
print();
}
void print() {
System.out.println("A");
}
}
class B extends A {
static int staticVariable2 = 123456;
static int staticVariable;
static
{
System.out.println(staticVariable2);
System.out.println("Static Initialization block");
staticVariable = Math.round(3.5f);
}
int instanceVariable;
{
System.out.println("Initialization block");
instanceVariable = Math.round(3.5f);
staticVariable = Math.round(3.5f);
}
B() {
System.out.println("Constructor");
}
public static void main(String[] args) {
A a = new B();
a.print();
System.out.println("main");
}
void print() {
System.out.println(instanceVariable);
}
static void somethingElse() {
System.out.println("Static method");
}
}
Before to start commenting on the source code, I'll give you a short explanation of static variables of a class:
First thing is that they are called class variables, they belong to the class not to particular instance of the class. All instances of the class share this static(class) variable. Each and every variable has a default value, depending on primitive or reference type. Another thing is when you reassign the static variable in some of the members of the class (initialization blocks, constructors, methods, properties) and doing so you are changing the value of the static variable not for particular instance, you are changing it for all instances. To conclude static part I will say that the static variables of a class are created not when you instantiate for first time the class, they are created when you define your class, they exist in JVM without the need of any instances. Therefor the correct access of static members from external class (class in which they are not defined) is by using the class name following by dot and then the static member, which you want to access (template: <CLASS_NAME>.<STATIC_VARIABLE_NAME>).
Now let's look at the code above:
The entry point is the main method - there are just three lines of code. I want to refer to the example which is currently approved. According to it the first thing which must be printed after printing "Static Initialization block" is "Initialization block" and here is my disagreement, the non-static initialization block is not called before the constructor, it is called before any initializations of the constructors of the class in which the initialization block is defined. The constructor of the class is the first thing involved when you create an object (instance of the class) and then when you enter the constructor the first part called is either implicit (default) super constructor or explicit super constructor or explicit call to another overloaded constructor (but at some point if there is a chain of overloaded constructors, the last one calls a super constructor, implicitly or explicitly).
There is polymorphic creation of an object, but before to enter the class B and its main method, the JVM initializes all class(static) variables, then goes through the static initialization blocks if any exist and then enters the class B and starts with the execution of the main method. It goes to the constructor of class B then immediately (implicitly) calls constructor of class A, using polymorphism the method(overridden method) called in the body of the constructor of class A is the one which is defined in class B and in this case the variable named instanceVariable is used before reinitialization. After closing the constructor of class B the thread is returned to constructor of class B but it goes first to the non-static initialization block before printing "Constructor". For better understanding debug it with some IDE, I prefer Eclipse.
Initializer block contains the code that is always executed whenever
an instance is created. It is used to declare/initialise the common
part of various constructors of a class.
The order of initialization constructors and initializer block doesn’t matter, initializer block is always executed before constructor.
What if we want to execute some code once for all objects of a class?
We use Static Block in Java.
In addition to what was said in previous answers, blocks can be synchronized .. never felt I need to use it, however,it's there
Initialization blocks are executed whenever the class is initialized and before constructors are invoked. They are typically placed above the constructors within braces. It is not at all necessary to include them in your classes.
They are typically used to initialize reference variables. This page gives a good explanation
The question is not entirely clear, but here's a brief description of ways you can initialise data in an object. Let's suppose you have a class A that holds a list of objects.
1) Put initial values in the field declaration:
class A {
private List<Object> data = new ArrayList<Object>();
}
2) Assign initial values in the constructor:
class A {
private List<Object> data;
public A() {
data = new ArrayList<Object>();
}
}
These both assume that you do not want to pass "data" as a constructor argument.
Things get a little tricky if you mix overloaded constructors with internal data like above. Consider:
class B {
private List<Object> data;
private String name;
private String userFriendlyName;
public B() {
data = new ArrayList<Object>();
name = "Default name";
userFriendlyName = "Default user friendly name";
}
public B(String name) {
data = new ArrayList<Object>();
this.name = name;
userFriendlyName = name;
}
public B(String name, String userFriendlyName) {
data = new ArrayList<Object>();
this.name = name;
this.userFriendlyName = userFriendlyName;
}
}
Notice that there is a lot of repeated code. You can fix this by making constructors call each other, or you can have a private initialisation method that each constructor calls:
class B {
private List<Object> data;
private String name;
private String userFriendlyName;
public B() {
this("Default name", "Default user friendly name");
}
public B(String name) {
this(name, name);
}
public B(String name, String userFriendlyName) {
data = new ArrayList<Object>();
this.name = name;
this.userFriendlyName = userFriendlyName;
}
}
or
class B {
private List<Object> data;
private String name;
private String userFriendlyName;
public B() {
init("Default name", "Default user friendly name");
}
public B(String name) {
init(name, name);
}
public B(String name, String userFriendlyName) {
init(name, userFriendlyName);
}
private void init(String _name, String _userFriendlyName) {
data = new ArrayList<Object>();
this.name = name;
this.userFriendlyName = userFriendlyName;
}
}
The two are (more or less) equivalent.
I hope that gives you some hints on how to initialise data in your objects. I won't talk about static initialisation blocks as that's probably a bit advanced at the moment.
EDIT: I've interpreted your question as "how do I initialise my instance variables", not "how do initialiser blocks work" as initialiser blocks are a relatively advanced concept, and from the tone of the question it seems you're asking about the simpler concept. I could be wrong.
public class StaticInitializationBlock {
static int staticVariable;
int instanceVariable;
// Static Initialization Block
static {
System.out.println("Static block");
staticVariable = 5;
}
// Instance Initialization Block
{
instanceVariable = 7;
System.out.println("Instance Block");
System.out.println(staticVariable);
System.out.println(instanceVariable);
staticVariable = 10;
}
public StaticInitializationBlock() {
System.out.println("Constructor");
}
public static void main(String[] args) {
new StaticInitializationBlock();
new StaticInitializationBlock();
}
}
Output:
Static block
Instance Block
5
7
Constructor
Instance Block
10
7
Constructor
Just to add to the excellent answers from #aioobe and #Biman Tripathy.
A static initializer is the equivalent of a constructor in the static context. which is needed to setup the static environment.
A instance initializer is best for anonymous inner classes.
It is also possible to have multiple initializer blocks in class
When we have multiple initializer blocks they are executed (actually copied to constructors by JVM) in the order they appear
Order of initializer blocks matters, but order of initializer blocks mixed with Constructors doesn't
Abstract classes can also have both static and instance initializer blocks.
Code Demo -
abstract class Aircraft {
protected Integer seatCapacity;
{ // Initial block 1, Before Constructor
System.out.println("Executing: Initial Block 1");
}
Aircraft() {
System.out.println("Executing: Aircraft constructor");
}
{ // Initial block 2, After Constructor
System.out.println("Executing: Initial Block 2");
}
}
class SupersonicAircraft extends Aircraft {
{ // Initial block 3, Internalizing a instance variable
seatCapacity = 300;
System.out.println("Executing: Initial Block 3");
}
{ // Initial block 4
System.out.println("Executing: Initial Block 4");
}
SupersonicAircraft() {
System.out.println("Executing: SupersonicAircraft constructor");
}
}
An instance creation of SupersonicAircraft will produce logs in below order
Executing: Initial Block 1
Executing: Initial Block 2
Executing: Aircraft constructor
Executing: Initial Block 3
Executing: Initial Block 4
Executing: SupersonicAircraft constructor
Seat Capacity - 300

Why below code compiles fine and prints "init"? [duplicate]

We can put code in a constructor or a method or an initialization block. What is the use of initialization block? Is it necessary that every java program must have it?
First of all, there are two types of initialization blocks:
instance initialization blocks, and
static initialization blocks.
This code should illustrate the use of them and in which order they are executed:
public class Test {
static int staticVariable;
int nonStaticVariable;
// Static initialization block:
// Runs once (when the class is initialized)
static {
System.out.println("Static initalization.");
staticVariable = 5;
}
// Instance initialization block:
// Runs each time you instantiate an object
{
System.out.println("Instance initialization.");
nonStaticVariable = 7;
}
public Test() {
System.out.println("Constructor.");
}
public static void main(String[] args) {
new Test();
new Test();
}
}
Prints:
Static initalization.
Instance initialization.
Constructor.
Instance initialization.
Constructor.
Instance initialization blocks are useful if you want to have some code run regardless of which constructor is used or if you want to do some instance initialization for anonymous classes.
would like to add to #aioobe's answer
Order of execution:
static initialization blocks of super classes
static initialization blocks of the class
instance initialization blocks of super classes
constructors of super classes
instance initialization blocks of the class
constructor of the class.
A couple of additional points to keep in mind (point 1 is reiteration of #aioobe's answer):
The code in static initialization block will be executed at class load time (and yes, that means only once per class load), before any instances of the class are constructed and before any static methods are called.
The instance initialization block is actually copied by the Java compiler into every constructor the class has. So every time the code in instance initialization block is executed exactly before the code in constructor.
nice answer by aioobe
adding few more points
public class StaticTest extends parent {
static {
System.out.println("inside satic block");
}
StaticTest() {
System.out.println("inside constructor of child");
}
{
System.out.println("inside initialization block");
}
public static void main(String[] args) {
new StaticTest();
new StaticTest();
System.out.println("inside main");
}
}
class parent {
static {
System.out.println("inside parent Static block");
}
{
System.out.println("inside parent initialisation block");
}
parent() {
System.out.println("inside parent constructor");
}
}
this gives
inside parent Static block
inside satic block
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside main
its like stating the obvious but seems a little more clear.
The sample code, which is approved as an answer here is correct, but I disagree with it. It does not shows what is happening and I'm going to show you a good example to understand how actually the JVM works:
package test;
class A {
A() {
print();
}
void print() {
System.out.println("A");
}
}
class B extends A {
static int staticVariable2 = 123456;
static int staticVariable;
static
{
System.out.println(staticVariable2);
System.out.println("Static Initialization block");
staticVariable = Math.round(3.5f);
}
int instanceVariable;
{
System.out.println("Initialization block");
instanceVariable = Math.round(3.5f);
staticVariable = Math.round(3.5f);
}
B() {
System.out.println("Constructor");
}
public static void main(String[] args) {
A a = new B();
a.print();
System.out.println("main");
}
void print() {
System.out.println(instanceVariable);
}
static void somethingElse() {
System.out.println("Static method");
}
}
Before to start commenting on the source code, I'll give you a short explanation of static variables of a class:
First thing is that they are called class variables, they belong to the class not to particular instance of the class. All instances of the class share this static(class) variable. Each and every variable has a default value, depending on primitive or reference type. Another thing is when you reassign the static variable in some of the members of the class (initialization blocks, constructors, methods, properties) and doing so you are changing the value of the static variable not for particular instance, you are changing it for all instances. To conclude static part I will say that the static variables of a class are created not when you instantiate for first time the class, they are created when you define your class, they exist in JVM without the need of any instances. Therefor the correct access of static members from external class (class in which they are not defined) is by using the class name following by dot and then the static member, which you want to access (template: <CLASS_NAME>.<STATIC_VARIABLE_NAME>).
Now let's look at the code above:
The entry point is the main method - there are just three lines of code. I want to refer to the example which is currently approved. According to it the first thing which must be printed after printing "Static Initialization block" is "Initialization block" and here is my disagreement, the non-static initialization block is not called before the constructor, it is called before any initializations of the constructors of the class in which the initialization block is defined. The constructor of the class is the first thing involved when you create an object (instance of the class) and then when you enter the constructor the first part called is either implicit (default) super constructor or explicit super constructor or explicit call to another overloaded constructor (but at some point if there is a chain of overloaded constructors, the last one calls a super constructor, implicitly or explicitly).
There is polymorphic creation of an object, but before to enter the class B and its main method, the JVM initializes all class(static) variables, then goes through the static initialization blocks if any exist and then enters the class B and starts with the execution of the main method. It goes to the constructor of class B then immediately (implicitly) calls constructor of class A, using polymorphism the method(overridden method) called in the body of the constructor of class A is the one which is defined in class B and in this case the variable named instanceVariable is used before reinitialization. After closing the constructor of class B the thread is returned to constructor of class B but it goes first to the non-static initialization block before printing "Constructor". For better understanding debug it with some IDE, I prefer Eclipse.
Initializer block contains the code that is always executed whenever
an instance is created. It is used to declare/initialise the common
part of various constructors of a class.
The order of initialization constructors and initializer block doesn’t matter, initializer block is always executed before constructor.
What if we want to execute some code once for all objects of a class?
We use Static Block in Java.
In addition to what was said in previous answers, blocks can be synchronized .. never felt I need to use it, however,it's there
Initialization blocks are executed whenever the class is initialized and before constructors are invoked. They are typically placed above the constructors within braces. It is not at all necessary to include them in your classes.
They are typically used to initialize reference variables. This page gives a good explanation
The question is not entirely clear, but here's a brief description of ways you can initialise data in an object. Let's suppose you have a class A that holds a list of objects.
1) Put initial values in the field declaration:
class A {
private List<Object> data = new ArrayList<Object>();
}
2) Assign initial values in the constructor:
class A {
private List<Object> data;
public A() {
data = new ArrayList<Object>();
}
}
These both assume that you do not want to pass "data" as a constructor argument.
Things get a little tricky if you mix overloaded constructors with internal data like above. Consider:
class B {
private List<Object> data;
private String name;
private String userFriendlyName;
public B() {
data = new ArrayList<Object>();
name = "Default name";
userFriendlyName = "Default user friendly name";
}
public B(String name) {
data = new ArrayList<Object>();
this.name = name;
userFriendlyName = name;
}
public B(String name, String userFriendlyName) {
data = new ArrayList<Object>();
this.name = name;
this.userFriendlyName = userFriendlyName;
}
}
Notice that there is a lot of repeated code. You can fix this by making constructors call each other, or you can have a private initialisation method that each constructor calls:
class B {
private List<Object> data;
private String name;
private String userFriendlyName;
public B() {
this("Default name", "Default user friendly name");
}
public B(String name) {
this(name, name);
}
public B(String name, String userFriendlyName) {
data = new ArrayList<Object>();
this.name = name;
this.userFriendlyName = userFriendlyName;
}
}
or
class B {
private List<Object> data;
private String name;
private String userFriendlyName;
public B() {
init("Default name", "Default user friendly name");
}
public B(String name) {
init(name, name);
}
public B(String name, String userFriendlyName) {
init(name, userFriendlyName);
}
private void init(String _name, String _userFriendlyName) {
data = new ArrayList<Object>();
this.name = name;
this.userFriendlyName = userFriendlyName;
}
}
The two are (more or less) equivalent.
I hope that gives you some hints on how to initialise data in your objects. I won't talk about static initialisation blocks as that's probably a bit advanced at the moment.
EDIT: I've interpreted your question as "how do I initialise my instance variables", not "how do initialiser blocks work" as initialiser blocks are a relatively advanced concept, and from the tone of the question it seems you're asking about the simpler concept. I could be wrong.
public class StaticInitializationBlock {
static int staticVariable;
int instanceVariable;
// Static Initialization Block
static {
System.out.println("Static block");
staticVariable = 5;
}
// Instance Initialization Block
{
instanceVariable = 7;
System.out.println("Instance Block");
System.out.println(staticVariable);
System.out.println(instanceVariable);
staticVariable = 10;
}
public StaticInitializationBlock() {
System.out.println("Constructor");
}
public static void main(String[] args) {
new StaticInitializationBlock();
new StaticInitializationBlock();
}
}
Output:
Static block
Instance Block
5
7
Constructor
Instance Block
10
7
Constructor
Just to add to the excellent answers from #aioobe and #Biman Tripathy.
A static initializer is the equivalent of a constructor in the static context. which is needed to setup the static environment.
A instance initializer is best for anonymous inner classes.
It is also possible to have multiple initializer blocks in class
When we have multiple initializer blocks they are executed (actually copied to constructors by JVM) in the order they appear
Order of initializer blocks matters, but order of initializer blocks mixed with Constructors doesn't
Abstract classes can also have both static and instance initializer blocks.
Code Demo -
abstract class Aircraft {
protected Integer seatCapacity;
{ // Initial block 1, Before Constructor
System.out.println("Executing: Initial Block 1");
}
Aircraft() {
System.out.println("Executing: Aircraft constructor");
}
{ // Initial block 2, After Constructor
System.out.println("Executing: Initial Block 2");
}
}
class SupersonicAircraft extends Aircraft {
{ // Initial block 3, Internalizing a instance variable
seatCapacity = 300;
System.out.println("Executing: Initial Block 3");
}
{ // Initial block 4
System.out.println("Executing: Initial Block 4");
}
SupersonicAircraft() {
System.out.println("Executing: SupersonicAircraft constructor");
}
}
An instance creation of SupersonicAircraft will produce logs in below order
Executing: Initial Block 1
Executing: Initial Block 2
Executing: Aircraft constructor
Executing: Initial Block 3
Executing: Initial Block 4
Executing: SupersonicAircraft constructor
Seat Capacity - 300

Why are static blocks/static variables in super class initialized before main?

public class sup {
static {
System.out.print("In Sup ");
}
}
public class sub extends sup {
static {
System.out.print("In Sub");
}
}
final public class test extends sub {
static int a = 10;
static {
System.out.print(" In test" + a);
}
{
System.out.print(" In test" + a);
}
public static void main(String[] args) {
}
}
Output:
In Sup In Sub In test10
But here I am not creating object. The JVM should call the main method which is static and initialize the main class only. So it should give output In test10.
Could anyone please explain why I'm getting different output?
static initializer blocks are called when the class loader loads a class. In a nutshell, the order of execution here is as follows:
Attempt to load test, see it depends on sub
Attempt to load sub, see it depends on sup
Attempt to load sup
sup is loaded, and its static block prints "In Sup"
sub's loading is resumed, and its static block prints "In Sub"
test's loading is resumed, and a is initialized to 10.
test's static block is executed and prints " In test10"
test's main function is executed, and does nothing, since it's empty.
Static blocks are executed before main method. Since test extends sub and sub extends sup, the static block of sup will be executed, then the static block of sub and finally the static block of test.
See the JLS - 12.4.1. When Initialization Occurs for detailed explanation:
class Super {
static { System.out.print("Super "); }
}
class One {
static { System.out.print("One "); }
}
class Two extends Super {
static { System.out.print("Two "); }
}
class Test {
public static void main(String[] args) {
One o = null;
Two t = new Two();
System.out.println((Object)o == (Object)t);
}
}
This example demonstrates the order of execution, the output would be
Super Two false
here i am not creating object.. It is not about creation of objects. Even before you create an object, the class and its related dependencies have to be loaded / initialized. Classes can get loaded when you access static methods present in them (main is static). Since your test class depends on sub and sub depends on sup, the JVM loads them in the order sup --> sub --> test so that the dependencies for the class 'test' are resolved. Unless this is done, your 'test' cannot use fields / methods of its super classes.
static block/variable/methods are not inheritable as they belong to class not object.
The reason why you are getting this output is, JVM needs to load the main class's complete hierarchy to execute the main method (parent class then child).
If you remove the inheritance from test class, you would get only 'In test10'.
The JVM will load a class when the class is run regardless of whether you create an instance of the class or not.
This is clearly specified in Section 12.1.1 of the Java language specification.
java Test reboot Bob Dot Enzo
The initial attempt to execute the method main of class Test discovers that the class Test is not loaded - that is, that the Java Virtual Machine does not currently contain a binary representation for this class. The Java Virtual Machine then uses a class loader to attempt to find such a binary representation

Static initializer runs after the constructor, why?

I have 2 classes:
Class A:
public class A {
static B b = new B();
static {
System.out.println("A static block");
}
public A() {
System.out.println("A constructor");
}
}
Class B:
public class B {
static {
System.out.println("B static block");
new A();
}
public B() {
System.out.println("B constructor");
}
}
I create a Main class which just creates new A:
public class Main {
public static void main(String[] args) {
new A();
}
}
The output I get is:
B static block
A constructor
B constructor
A static block
A constructor
As you can see, the constructor of A is invoked before its static initializer.
I understand it got something to do with the cyclic dependency I created but I was under the impression the static initializer should always run before the constructor.
What is the reason for this to happen (technically in the java implementation) ?
Is it recommended to avoid static initializers all together ?
static B b = new B();
is before
static {
System.out.println("A static block");
}
So you require that the B instance be initialized before you print "A static block".
And initializing the B class means you need to create a A instance. So there's no way for "A static block" to be printed before the A instance is constructed.
Yes, the static initialization of A is launched before the constructor is launched but, apart deadlocking, there would be no other solution to the sequence you require.
Note the warning in the specification :
Because the Java programming language is multithreaded, initialization
of a class or interface requires careful synchronization, since some
other thread may be trying to initialize the same class or interface
at the same time. There is also the possibility that initialization of
a class or interface may be requested recursively as part of the
initialization of that class or interface; for example, a variable
initializer in class A might invoke a method of an unrelated class B,
which might in turn invoke a method of class A. The implementation of
the Java virtual machine is responsible for taking care of
synchronization and recursive initialization by using the following
procedure [the doc goes on with the complete procedure]
A best practice, in Java as in other languages, is basically to avoid cyclic dependencies as their resolution may be very hard to predict.

Order of execution in Java

I am trying to understand this example from Thinking in Java:
package c07;
import com.bruceeckel.simpletest.*;
class Meal {
Meal() { System.out.println("Meal()"); }
}
class Bread {
Bread() { System.out.println("Bread()"); }
}
class Cheese {
Cheese() { System.out.println("Cheese()"); }
}
class Lettuce {
Lettuce() { System.out.println("Lettuce()"); }
}
class Lunch extends Meal {
Lunch() { System.out.println("Lunch()"); }
}
class PortableLunch extends Lunch {
PortableLunch() { System.out.println("PortableLunch()");}
}
public class Sandwich extends PortableLunch {
private static Test monitor = new Test();
private Bread b = new Bread();
private Cheese c = new Cheese();
private Lettuce l = new Lettuce();
public Sandwich() {
System.out.println("Sandwich()");
}
public static void main(String[] args) {
new Sandwich();
monitor.expect(new String[] {
"Meal()",
"Lunch()",
"PortableLunch()",
"Bread()",
"Cheese()",
"Lettuce()",
"Sandwich()"
});
}
}
As I understand from Java Language Specification, the order of execution begins by loading the class containing the main method. Then all the statics and member variables of this class must be initialized (before which all the member variables of the superclasses must be intialized, although there are none of those in this case).
So I thought b, c, l would be initialized before main starts executing. That does not seem to be the case from the output though. Am I missing something?
No, b and c are instance variables.
There's no automatic instantiation of the class containing main. Only static variables are initialized. It's just as if some outside caller wrote:
Sandwich.main(args);
So when you wrote:
Then all the statics and member variables of this class must be initialized
... that was wrong. Only the static variables are initialized - just as normal.
The example output is correct. Here are the important rules:
when the class is created, the constructor of the super class has to be called first. This bubbles up to Object class
before the constructor is called, member variable initialization is called.
No statics are involved in this example, except the technical monitor.
JLS # 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.
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.
JLS # 12.5. Creation of New Class Instances
Whenever a new class instance is created, memory space is allocated for it with room for all the instance variables declared in the class type and all the instance variables declared in each superclass of the class type, including all the instance variables that may be hidden (§8.3).

Categories

Resources