I'm studying for Oracle's OCA 8 certification. In my studies, I came across an issue that left me with some doubts about the order of initialization of a Java object (static blocks, constructors, initialization of variables, ...). The question is as follows:
public class InitTest{
static String s1 = sM1("a");{
s1 = sM1("b");
}
static{
s1 = sM1("c");
}
public static void main(String args[]){
InitTest it = new InitTest();
}
private static String sM1(String s){
System.out.println(s); return s;
}
}
My question is the order in which each part of the object is started:
1) {...}
2) static {...}
3) InitTest {...}
4) static String s1 = sM1("a");
Can you explain me, please?
Order of initalization is always as follows:
initialize superclasses recursively (not relevant for the example in question since it doesn't have a superclass)
static fields and static initializers
instance fields and instance initializers
constructors
Hence, the order of initialization in your example will be:
1) static String s1 = sM1("a"); - static initialization blocks and static field members are the first to be processed, this happens just after the classloader loads the class (before you start using the class or create an object). If there are more initializers or static member declarations, they are executed in the order in which they are written. That's why this static field will get initialized before the static initializer block.
2) static {...} - explained in point 1. The static initializater comes before the declaration of static variable s1 so that's why it it is processed in this order (both have the same priority but here the order inside of the class wins if both have the same prio).
3) {...} - after the static initializers and static fields, the instance initializers and instance fields are initialized, so the instance initializer is next after the static initializer and static field s1. They are the first to be processed when creating a new object using a constructor and this happens before the constructor actually gets executed.
4.) InitTest {...} - The constructor gets called after everything else is initalized (all initialization blocks and field initializations).
More details about the class and object initialization order you can find in the Java Language Specification: https://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.4.1, https://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.4.2,
https://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.5
First: The part of s1 = sM1("b") is formatted like it is part of s1 definition, but it's completely separate.
static { ... } and static String s1 =sM1("a") are both static, which means they run when the JVM loads the class, before any of the code in your Main. they are executed in the order they are written.
{...} and InitTest{...} aren't static and they run only when you create the instance of InitTest.
{...} is initialization block and run before the constructors.
Anything that's static is first taken care of as there is no reason for an object availability, The possible static contents in a class are,
a) static instance variable
b) static code block
c) static methods
and are evaluated in the same order (although order for a static method doesn't matter). So in your case the s1 = SM1("a") is evaluated first which results in the call to the sM1("a") method. Next the static code block is executed which results in sM1("c") and finally the instance code block is executed with sM1("b"). If you happen to have a no arg constructor in this class, then it would have got called as the last step before the object is available.
Related
I was reading the question here : Java : in what order are static final fields initialized?
According to the answer
"except that final class variables and fields of interfaces whose
values are compile-time constants are initialized first ..."
I think this is not correct because the following will fail :
static {
String y = x;
}
public static final String x = "test";
In the static block, x is not recognized. Can anyone please comment if that answer is correct ?
The order of initialization doesn't change the fact that the JLS doesn't let you refer to variables before they're declared in various cases. This is described in JLS§8.3.3:
Use of class variables whose declarations appear textually after the use is sometimes restricted, even though these class variables are in scope (§6.3). Specifically, it is a compile-time error if all of the following are true:
The declaration of a class variable in a class or interface C appears textually after a use of the class variable;
The use is a simple name in either a class variable initializer of C or a static initializer of C;
The use is not on the left hand side of an assignment;
C is the innermost class or interface enclosing the use.
That's why your code gets this compilation erorr:
error: illegal forward reference
The statement that static fields that are constant variables are initialized first is indeed defined in JLS§12.4.2:
Otherwise, record the fact that initialization of the Class object for C is in progress by the current thread, and release LC.
Then, initialize the static fields of C which are constant variables (§4.12.4, §8.3.2, §9.3.1).
...
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.
As you can see, constant variables are initialized in step 6, but others in step 9.
This demonstrates the behavior:
public class Example {
static String y;
static {
y = foo();
}
static String foo() {
return x.toUpperCase();
}
public static final String x = "test";
public static void main(String[] args) throws Exception {
System.out.println(x);
System.out.println(y);
}
}
That compiles, and outputs:
test
TEST
In contast, if you change the x line so it's not constant anymore:
public static final String x = Math.random() < 0.5 ? "test" : "ing";
It compiles, but then fails because x is null as of y = foo();.
For the avoidance of doubt: I don't recommend using methods to initialize fields like that. :-)
As this answer states:
... they are initialized in the order in which they appear in the source.
You are absolutely right, your example fails, because you are trying to use a variable that is declared after the usage. Since static block are executed in order of the source code, you are absolutely correct and should suggest and edit for that answer, because this statement is invalid:
except that final class variables ... are initialized first.
i am trying to follow the JVM specs http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.4.2.
Is frustrating for me to read the unclear specs. So:
What are the differences between:
class variable initializers
static initializers of the class
field initializers
/*
Initalizers
*/
class A {
private static String x = "sfi"; //static field initializer
private String ifi = "ifi"; //instance field initializer
static { //static (block) initalizer ?!
String y = "sbi";
}
{ //instance (block) initalizer ?!
String z = "ibi";
}
}
Static members
First you need to understand the difference between static and non-static fields of a class. A static field is not bound to any instance of the class, it is a property of the class (that is the reason why we access them through the class) so in your example you can access x from whithin A like this: A.x. A common example for this is counting the number of objects a class has:
private static int counter = 0;
public A()
{
counter++;
}
// get the instance count
public static int getCounter()
{
return counter;
}
This method we would call from somewhere else like this: A.getCounter() and we will retrieve the number of objects that have the type A.
Non-static members
These are variables that are specific to each object (instance) of the class. In your example this is sfi. The runtime system guarantees that sfi will be available whenever an object of type A is created and that it will have a default value of ifi, but the difference here is that each object you create will have a member called sfi with a default value of ifi so each object can later modify it of course.
Initializing blocks
They are a feature designed to be used when initialization cannot be done inline (initialization requires more complex logic like a for loop or error-checking). Here again we have:
static { /* init code ... /* }
which is a static initialization block that "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" - from here
If, on the other hand, we want to initialize instance members but we cannot do it in one line then we can use a block but without the static keyword:
{
// init code for instance members
}
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
I am getting confused with below code I expected that it will give an error or answer will be 10 but it is giving 20 how?
public class test {
public static void main(String[] args) {
System.out.println(x);
}
static{
x=10;
}
static int x=20;
}
It's specified in section 12.4.2 of the JLS, which gives details of class initialization:
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 variable initializer (x = 20) occurs after the static initializer (the block containing x = 10) in the program text. The value at the end of initialization is therefore 20.
If you swap the order round so that the variable initializer comes first, you'll see 10 instead.
I'd strongly advise you to avoid writing code which relies on textual ordering if possible though.
EDIT: The variable can still be used in the static initializer because it's in scope - just like you can use an instance variable in a method declared earlier than the variable. However, section 8.3.2.3 gives some restrictions on this:
The declaration of a member needs to appear textually before it is used only if the member is an instance (respectively static) field of a class or interface C and all of the following conditions hold:
The usage occurs in an instance (respectively static) variable initializer of C or in an instance (respectively static) initializer of C.
The usage is not on the left hand side of an assignment.
The usage is via a simple name.
C is the innermost class or interface enclosing the usage.
It is a compile-time error if any of the four requirements above are not met.
So if you change your static initializer to:
static {
System.out.println(x);
}
then you'll get an error.
Your existing static initializer uses x in a way which does comply with all of the restrictions, however.
in static if a value is changed once then it will be effected through out.
So you are getting 20.
if you write this way
public class test {
static int x=20;
public static void main(String[] args) {
System.out.println(x);
}
static{
x=10;
}
}
then it will print 10.
This question already has answers here:
Java : in what order are static final fields initialized?
(5 answers)
Closed 9 years ago.
One of my friends asked me that which will load first static variable or static block.
My answer points to static variable.
So he gave me two equations and said to differentiate between them
First Equation
public class Some {
public static void main(String args[])
{
System.out.println(Some.x);
}
static {
System.out.println(Some.x);
}
static int x=90;
}
O/P: 0 90
Second Equation
public class Some {
public static void main(String args[])
{
System.out.println(Some.x);
}
static int x=90;
static {
System.out.println(Some.x);
}
}
O/P: 90 90
I tried to decompile the byte code and found it's same for both the above equation.
Please help me to differentiate between them.
I am confused when the static variable will initialised.
Static blocks are initialised in the order they appear in the source file.
There are several questions relating to this on stack overflow already...
This one has a good answer for you: Java : in what order are static final fields initialized?
static variables and static blocks are executed in an order in which they appear.
Here first O/P: 0 90 as in the System.out.println(Some.x); statement of the static block executed after the static variable initialization statement static int x=90;
static Variables are executed when the JVM loads the Class, and the Class gets loaded when either its been instantiated or its static method is being called.
static Initializer Block gets Initialized before the Class gets instantiated or before its static method is called, and Even before its static variable is used.
I am giving a simple example for control flow of static and instance stuffs:
Suppose you have 2 clases A and B.
class A extends to class B. and class B has a main method. After successful compilation of both your command on cmd is like:
java B
Now what will happen see step by step:
classes A and B will be loaded
static members and blocks of class A will be identified and will be
executed sequentially(one by one)(But only once at the time of class loading)
static members and blocks of class B will be identified and executed(one by one)(But only once at the time of class loading)
main method of class B will be invoked(In case class B don't have a main method then class A's main method will be invoked)
As soon as you will create an object of class A : all instance
members initialization and instance block execution will be done in
class A
the constructor of class A(which you used for creating object) will
be executed
If you create an object of class B: all instance
members initialization and instance block execution will be done in
class A.
the constructor of class A(default constructor or any other if you called it from B's constructor) will
be executed
then all instance
members initialization and instance block execution will be done in
class B
and after that the constructor of class B(which you used for
creating object) will be executed
Note: static members and blocks execution is done only one time while loading class for first time, while instance members and instance blocks are executed each time as we create an object of the class.
Please let me know if I am not correct.
Can someone explain me what the following is?
public class Stuff
{
static
{
try
{
Class.forName("com.mysql.jdbc.Driver");
}
catch ( ClassNotFoundException exception )
{
log.error( "ClassNotFoundException " + exception.getMessage( ) );
}
...
}
What does this static { ...} do?
I know about static variables from C++, but is that a static block or something?
When is this stuff going to get executed?
The static block is called a class static initializer - it gets run the first time the class is loaded (and it's the only time it's run [footnote]).
The purpose of that particular block is to check if the MySQL driver is on the classpath (and throw/log error if it's not).
[footnote] The static block run once per classloader that loads the class (so if you had multiple class loaders that are distinct from each other (e.g. doesn't delegate for example), it will be executed once each.
The primary use of static initializers blocks are to do various bits of initialization that may not be appropriate inside a constructor such that taken together the constructor and initializers put the newly created object into a state that is completely consistent for use.
In contrast to constructors, for example, static initializers aren't inherited and are only executed once when the class is loaded and initialized by the JRE. In the example above, the class variable foo will have the value 998877 once initialization is complete.
Note also that static initializers are executed in the order in which they appear textually in the source file. Also, there are a number of restrictions on what you can't do inside one of these blocks such as no use of checked exceptions, no use of the return statement or the this and super keywords.
I want to add that static variables and static initializers are executed in order of appearance at the time of class loading. So, if your static initializer relies on some static variable, it must be initialized before the particular static block, e.g.
final static String JDBC_DRIVER = getJdbcDriver( );
static
{
try
{
Class.forName(JDBC_DRIVER);
}
catch ( ClassNotFoundException exception )
{
log.error( "ClassNotFoundException " + exception.getMessage( ) );
}
}
In this example getJdbcDriver will get executed before static initializer. Also, there may be more than 1 static initializer in the class. Once again they are executed in order of appearance.
I also want to mention the existence of instance initializers here, as they do come as surprise when seen for the first time. They look like a code block inside the class body, like this.
class MyClass
{
final int intVar;
{
intVar = 1;
}
}
In general case their use is somewhat unnecessary, because of the constructor, but they are useful in implementing Java's version of closures.
The static initializer block get executed whenever the class is to be loaded for the first time. That can happen if something at higher level is doing a Class#forName("yourpackage.YourClass") or a new YourClass() on the class in question for the first time.
By a coincidence, the decent JDBC drivers also have something similar inside. They namely registers themselves in the DriverManager using a static initializer block:
static {
DriverManager.registerDriver(new ThisDriver());
}
so that whenever you do a Class.forName("somepackage.ThisDriver"), you will effectively register the driver in the DriverManager so that you can get a connection from it afterwards.
In addition to all above , there is a minute difference in using class constructor and class initializer. Constructor as we know that will be usually used to initialized the objects and if we have static variables then static block is usually used in order to initialize them when the class will be loaded.
When we have static variables and static block then static variables initialized first and then the block.
When class is first loaded, static block initializes before the class constructor.
static initialization block
is a normal block of code
it is enclosed in braces { }
it is preceded by the static keyword
class Foo {
static {
// initialization code goes here:
doSomething();
}
}
class can have any number of static initialization blocks
they can appear anywhere in the class body
they are called in the order of apperence in the code
There is an alternative to static initialization blocks:
write a private static method
and assign it to the static class variable
The advantage of this approach is that the static method can be invoked later to reinitialize the class variable.
class Foo {
public static int myVar = initializeClassVariable();
private static int initializeClassVariable() {
// initialization code goes here:
int v = 255;
return v;
}
}