I dont know whether this question has been asked before or not .I searched but couldn't find any duplicate question. If you find any related question please mention the link.
public class Exp
{
Exp()
{
System.out.println("Hello"); //3
}
{ System.out.println("Hello")}; //1
{ static{System.out.print("x");} //2
}
The order of printing of messages is 2,1,3.
What are the significance of these lines 1 & 2 and why that exec order
Line "1" is an instance initializer, which runs when an object is first created, before any constructors are called.
Line "2" is a static initializer, which runs when a class is first loaded, before any objects are created.
Section 12.5 of the JLS specifies when instance initializers are run:
Just before a reference to the newly created object is returned as the
result, the indicated constructor is processed to initialize the new
object using the following procedure:
Assign the arguments for the constructor to newly created parameter
variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation
(§8.8.7.1) of another constructor in the same class (using this), then
evaluate the arguments and process that constructor invocation
recursively using these same five steps. If that constructor
invocation completes abruptly, then this procedure completes abruptly
for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor
invocation of another constructor in the same class (using this). If
this constructor is for a class other than Object, then this
constructor will begin with an explicit or implicit invocation of a
superclass constructor (using super). Evaluate the arguments and
process that superclass constructor invocation recursively using these
same five steps. If that constructor invocation completes abruptly,
then this procedure completes abruptly for the same reason. Otherwise,
continue with step 4.
Execute the instance initializers and instance variable initializers
for this class, assigning the values of instance variable initializers
to the corresponding instance variables, in the left-to-right order in
which they appear textually in the source code for the class. If
execution of any of these initializers results in an exception, then
no further initializers are processed and this procedure completes
abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution
completes abruptly, then this procedure completes abruptly for the
same reason. Otherwise, this procedure completes normally.
(emphasis mine)
The rest of the body of the constructor is executed after the instance initializer.
static blocks of a class are executed during class loading along with constants (static final members). 3 is invoked when the object is instantiated.
For you to understand better debug the code through your IDE to understand the sequence of execution.
See http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
A static initialization block is a normal block of code enclosed in braces, { }, and preceded by the static keyword. Here is an example:
static {
// whatever code is needed for initialization goes here
}
A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.
The reason for the execution order is, in non-static block you might want to use static members, but in static block you cannot use non-static members. So it makes sense to execute static block first.
non-static block allows you to abstract the code that every constructor needs to execute, therefore it gets executed before constructor.
More detailed order of execution:
1.static block of superclass
2.static block of this class
3.non-static block of superclass
4.constructor of superclass
5.non-static block of this class
6.constructor of this class
Related
I'm trying to extend the class A which is written in Java to class B in Scala.
class A {
private Pattern pattern;
private String regex= "folder1/folder2/folder3/.*";
A(...){
this.regex = regex;
this.pattern = Pattern.compile(getRegex());
}
public String getRegex() {
return regex;
}
}
class B(...) extends A(...) {
val regex: String= "folder4/.*";
override def getRegex(): String = {
return regex;
}
}
However it seems that the Pattern.compile(getRegex()) is getting null value from the B class. I'm also not allowed to pass the override regex through the constructor. Not sure how I can resolve this issue.
This has nothing to do with scala specifically.
The regex instance variable you create in class B is initialized at some point. Unfortunately, that point is after A's constructor runs.
In general, when a constuctor in Parent invokes an instance method that is overridden in Child, all heck breaks loose. Doesn't matter if it's all java, all scala, or a combination of the two.
There are a few solutions. The simplest is to simply get rid of that field. If the getRegex() method instead is written as return "folder4/.*" instead of return regex, this problem won't occur.
See Java order of Initialization and Instantiation
The constructor is executed at the step 3
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
And an instance field is initialized at the step 4
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
So at the step 3 in the line this.pattern = Pattern.compile(getRegex()) inside the constructor of A, getRegex() returns regex, which is null at the moment (regex will become "folder1/folder2/folder3/.*" later, at the step 4).
I have a case like
MyClass.invoke( anObject.setSystem() );
Is there a guarantee that anObject.setSystem() will be called before MyClass is loaded? As the initialization code of MyClass depends on the result of anObject.setSystem().
It is running with Java 8. Any suggestions/hints would be appreciated. Many thanks
MyClass will be loaded and all of its static fields and static initializers will be initialized before MyClass.invoke() is called.
See JLS 12.14.1
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. <------------ right here
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.
EDIT
Thanks to #Holger and #gigi's comments, there was still the question as to whether the invocation that triggers the loading of the class occurs before or after the evaluation of the argument expression passed into it. I think the answer to that is in JLS 15.12.4, which states,
At run time, method invocation requires five steps. First, a target reference may be computed. Second, the argument expressions are evaluated. Third, the accessibility of the method to be invoked is checked. Fourth, the actual code for the method to be executed is located. Fifth, a new activation frame is created, synchronization is performed if necessary, and control is transferred to the method code.
The evaluation of argument expressions (step 2) occurs before the code to execute the method is located, (step 4, which probably results in the class being loaded and statically initialized) and only then, in the final step, is the static method invoked.
Given Main.java:
public class Main{
public static void main(String[]args){
A a = new B();
a.print();
}
}
class A{
A() {print();}
void print() { System.out.println("A"); }
}
class B extends A{
int i = 4;
void print() { System.out.println(i); }
}
Results in:
0
4. But why doesn't a.print output "A" if it is referencing Class A? How do I know when one method will called be over another in cases like this? Why is A's constructor being called and still using B's method?
Calling a.print() prints 4 because of polymorphism. The method called depends on the runtime type of a, which is B. It doesn't matter when it's called; polymorphism applies always.
Both times, B's print method is called. Once is from A's constructor, which is called by the default constructor in B. The other time is your explicit call in main.
The reason that the first printing yields 0 and not 4 is because at the time that print is called, A is still being constructed. That is, the A constructor is still being executed. Before a superclass constructor returns, nothing is initialized in the subclass yet, not even variable initializers. The value 4 is assigned after the superclass constructor completes, but before the rest of the subclass constructor completes. Because the variable initializers haven't run yet, the default value of 0 (it would be false for booleans and null for objects) is the value of i in the first printing.
This order is listed by the JLS, Section 12.5:
Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.
(bold emphasis mine)
This is an example of why it's a bad idea to call a method that can be overridden from a constructor. The subclass state isn't initialized yet.
In case of Overridden methods (like print() in your example), object type decides which method to be invoked, not the reference type.
B doesn't have any constructor, so its default constructor won't do anything except calling A's constructor.
Now when B's default constructor is called, it calls A's constructor (keep in mind i is still not set, so default value 0). A's constructor calls print(), now as object is of actually B it calls B's print() and it prints 0 (remember i was not set).
Now once these constructor calls completes B's code gets executes which sets i to 0. Now calling print() will again get you to B's print() (as object is of B only) which will print 4.
"DEBUGGING IS THE KEY"
Given Main.java:
public class Main{
public static void main(String[]args){
A a = new B();
a.print();
}
}
class A{
A() {print();}
void print() { System.out.println("A"); }
}
class B extends A{
int i = 4;
void print() { System.out.println(i); }
}
Results in:
0
4. But why doesn't a.print output "A" if it is referencing Class A? How do I know when one method will called be over another in cases like this? Why is A's constructor being called and still using B's method?
Calling a.print() prints 4 because of polymorphism. The method called depends on the runtime type of a, which is B. It doesn't matter when it's called; polymorphism applies always.
Both times, B's print method is called. Once is from A's constructor, which is called by the default constructor in B. The other time is your explicit call in main.
The reason that the first printing yields 0 and not 4 is because at the time that print is called, A is still being constructed. That is, the A constructor is still being executed. Before a superclass constructor returns, nothing is initialized in the subclass yet, not even variable initializers. The value 4 is assigned after the superclass constructor completes, but before the rest of the subclass constructor completes. Because the variable initializers haven't run yet, the default value of 0 (it would be false for booleans and null for objects) is the value of i in the first printing.
This order is listed by the JLS, Section 12.5:
Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.
(bold emphasis mine)
This is an example of why it's a bad idea to call a method that can be overridden from a constructor. The subclass state isn't initialized yet.
In case of Overridden methods (like print() in your example), object type decides which method to be invoked, not the reference type.
B doesn't have any constructor, so its default constructor won't do anything except calling A's constructor.
Now when B's default constructor is called, it calls A's constructor (keep in mind i is still not set, so default value 0). A's constructor calls print(), now as object is of actually B it calls B's print() and it prints 0 (remember i was not set).
Now once these constructor calls completes B's code gets executes which sets i to 0. Now calling print() will again get you to B's print() (as object is of B only) which will print 4.
"DEBUGGING IS THE KEY"
This question already has answers here:
In what order do static/instance initializer blocks in Java run?
(8 answers)
Closed 9 years ago.
I'm trying to discover the order in which initialization occurs, or rather the reason behind why initialization occurs in this order. Given the code:
public class Main {
{
System.out.printf("NON-STATIC BLOCK\n");
}
static{
System.out.printf("STATIC BLOCK\n");
}
public static Main m = new Main();
public Main(){
System.out.printf("MAIN CONSTRUCTOR\n");
}
public static void main(String... args) {
//Main m = new Main();
System.out.printf("MAIN METHOD\n");
}
}
Output:
STATIC BLOCK
NON-STATIC BLOCK
MAIN CONSTRUCTOR
MAIN METHOD
However, moving m's declaration before the initialization block produces:
NON-STATIC BLOCK
MAIN CONSTRUCTOR
STATIC BLOCK
MAIN METHOD
and I have absolutely no idea why it occurs in this order. Furthermore, if I eliminate the static keyword in the declaration of m, neither the init block nor the constructor fire. Can anyone help me out with this?
I think you're just missing section 12.4.2 of the JLS, which includes:
Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
The "in textual order" part is the important bit.
If you change m from being static variable to an instance variable, then the field won't be initialized by class initialization - it'll only be initialized by instance initialization (i.e. when an instance is constructed). At the moment, that'll cause a stack overflow - creating one instance requires creating another instance, which requires creating another instance, etc.
EDIT: Similarly section 12.5 specifies instance initialization, including these steps:
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.
So that's why you're seeing "NON-STATIC BLOCK" before "MAIN CONSTRUCTOR".