I am still on a learning curve in Java. To understand a bit more of initializer blocks I created a small test class:
public class Script {
{
Gadgets.log("anonymous 1");
}
public Script() {
Gadgets.log("constructor");
}
{
Gadgets.log("anonymous 2");
}
}
When I create an instance, I get this log:
Script: anonymous 1
Script: anonymous 2
Script: constructor
This tells me, both initializer blocks run BEFORE the constructor, in the order they appear in the source code (same as static initializers).
What I want to know is: Do I have a little more control over this behavior?
Because Java Documentation says (source):
Initializer blocks for instance variables look just like static
initializer blocks, but without the static keyword:
{
// whatever code is needed for initialization goes here
}
The Java compiler copies initializer blocks into every constructor. Therefore,
this approach can be used to share a block of code between multiple
constructors.
So what exactly does "copies initializer blocks into every constructor" mean? According to my log, it seems, they are copied at the beginning of each constructor. Is this right?
Sharing such blocks between multiple constructors would also make perfectly sense, if they were copied to the END of each constructor (that's what I expected in my anonymous 2).
Is there a way to control those blocks a bit more or is my only option the "classic" way of writing a named method that gets called in every constructor if I want to do common tasks at the end of each constructor?
A constructor executes in the following order:
super() call, implicit or explicit.
Variable initializers and initializer blocks, in the order they appear in the source code.
Remainder of the constructor.
This is specified in the JLS and cannot be altered.
If a this() call is present it replaces (1) and (2).
Related
If I try to assign a value to a variable in a class, but outside a method I get an error.
class one{
Integer b;
b=Integer.valueOf(2);
}
but, if I initialize it during the creation, it works.
class one{
Integer b=Integer.valueOf(2);
}
Inside a method, it works in both cases.
you need to do
class one{
Integer b;
{
b=Integer.valueOf(2);
}
}
as statements have to appear in a block of code.
In this case, the block is an initailiser block which is added to every constructor (or the default constructor in this case) It is run after any call to super() and before the main block of code in any constructor.
BTW: You can have a static initialiser block with static { } which is called when the class is initialised.
e.g.
class one{
static final Integer b;
static {
b=Integer.valueOf(2);
}
}
Because the assignments are statements and statements are allowed only inside blocks of code(methods, constructors, static initializers, etc.)
Outside of these only declarations are allowed.
This :
class one{
Integer b=Integer.valueOf(2);
}
is a declaration with an initializer. That's why is accepted
A more general answer would be that the class body is about declarations, not statements. There is special provision for statements occuring in class body, but they have to be marked explicitly as either class initializers or instance initializers.
In Java, when defining a class, you can define variables with default values and add methods. Any executable code (such as assignments) MUST be contained in a method.
This is the way java works, you cannot add non-declaration code (sorry i don't know the correct term) inside the class, that code should be inside methods.
I think terminology-wise, couple of other answers are slightly off. Declarations are also statements. In fact, they are called "declaration statements", which are one of the three kinds of statements. An assignment statement is one form of "expression statement" and can be used only in constructs such as methods, constructors, and initializers. Check out the Statements section in this Oracle's tutorial link.
Methods have the responsibility to perform mutations on the member variables. If the member variable needs to be initialized, java provides a way to do it during construction, class definition (latter case). But the mutation cannot be performed during definition.(former case). It is usually done at the method level.
Objects are meant to hold the state, while methods are meant to operate on that state.
I found a lot of posts on static initialization blocks, however I'm trying to get a little better picture about the execution order and the reason for it. The code below prints out the text in both the static blocks and "then" prints out the text in the main static block.
I understand the way the compiler calls this is to do all the static blocks in order when the class is loaded and then access the main method. But since the main method itself is static, why not execute that in order of the other static blocks (Not even sure if its useful, just trying to understand a concept and if there's a pressing reason for it being done this way). What if there's static block we want to run after the main block?
class Cat {
static
{
System.out.println("This block welcomes you first");
}
public static void main(String[] args)
{
System.out.println("Meow world ");
}
static
{
System.out.println("This block welcomes you after");
}
}
Actual Output
This block welcomes you first
This block welcomes you after
Meow world
Why not?
This block welcomes you first
Meow world
This block welcomes you after
Static initializers are executed as soon as the class is loaded. The main method is called after the class has been loaded.
This section of the JLS discusses the sequence of events (12.1.3-4):
12.1.3. Initialize Test: Execute Initializers
In our continuing example, the Java Virtual Machine is still trying to execute the method main of class Test. This is permitted only if the class has been initialized (§12.4.1).
Initialization consists of execution of any class variable initializers and static initializers of the class Test, in textual order. But before Test can be initialized, its direct superclass must be initialized, as well as the direct superclass of its direct superclass, and so on, recursively. In the simplest case, Test has Object as its implicit direct superclass; if class Object has not yet been initialized, then it must be initialized before Test is initialized. Class Object has no superclass, so the recursion terminates here.
12.1.4. Invoke Test.main
Finally, after completion of the initialization for class Test (during which other consequential loading, linking, and initializing may have occurred), the method main of Test is invoked.
The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code. And dont forget, this code will be executed when JVM loads the class. JVM combines all these blocks into one single static block and then executes. Here are a couple of points I like to mention:
If you have executable statements in the static block, JVM will automatically execute these statements when the class is loaded into JVM.
If you’re referring some static variables/methods from the static blocks, these statements will be executed after the class is loaded into JVM same as above i.e., now the static variables/methods referred and the static block both will be executed.
After that the main method will execute.
Thanks
Static initializers are executed as soon as the class is initialized (a class can be loaded and initialized at a later point of time. check Class.forName()). The main() method is called after the static initializers are executed. So the output is like that.
I was looking at some code examples and found this
Game game = new Game("Gladiator", null, 10);
{
game.setState(GameState.STARTING);
game.setJoinable(true);
}
{
game.setState(GameState.LOBBY);
game.setJoinable(true);
}
{
game.setState(GameState.IN_GAME);
game.setJoinable(false);
}
I was wondering what does the
{ }
initializer means
It does nothing in the context. It is just the coding style of the person - in this case, visually shows the group of lines.
In something like below, those {} would actually do something, which defines locally separated scope (the sample code is not meaningful but shows the idea):
{
int a = 1;
}
{
int a = 2;
}
Is this code inside a method or is it at class level?
If it is inside a method, the braces don't really do anything, they just delimit the scope of local variables defined inside the block, but since no variables are being declared inside the blocks you posted, they are not useful at all.
If these blocks are at class level, then they are instance initializers. Instance initializers are rarely used in Java, it's better to put object initialization code in a constructor.
As Peter Pei Guo says, the curly brackets are not doing anything here. But it is worth noting some other things:
They are not an initializer blocks in this context. The code shown only makes sense inside a method or constructor body. In that context, curly brackets are simply a block statement ... not an initializer block.
A block statement can mean something. For example:
public void method() {
{
Game game = new Game("Gladiator", null, 10);
game.setState(GameState.STARTING);
game.setJoinable(true);
}
{
Game game = new Game("Fashion Model", null, 10);
game.setState(GameState.STARTING);
game.setJoinable(true);
}
}
The blocks in this case is providing a scope that allows us to declare the second games variable without a compilation error.
But the code in your question is not using this. It looks like the author has "a thing" about the visual appearance of his code.
So which block gets executed when?
Block statements are executed in normal statement order as the enclosing block (or method body) is executed. They are just statements, and they behave like other statements.
Instance initializer blocks are executed in order with any other field declarations / instance initializers each time an instance is created. They are executed after the explicit or implicit super constructor chain, but before the rest of the current classes constructor(s).
You haven't shown us enough context to be absolutely sure what kinds of blocks these are ... but we think you are showing us block statements.
This question already has answers here:
Why is this Java code in curly braces ({}) outside of a method?
(3 answers)
Java empty block scope
(3 answers)
Closed 9 years ago.
I accidently made a pair of {} outside of all method and worked.
public static void main(String[] args) {
System.out.println("ddd");
}
{
System.out.println("ttt");
}
Of course if you run this code the result is "ddd" and it writes "ttt" only if I create a new instance of it.
And if I make it static {System.out.println("ttt");} it works as designed and the result is "ttt" then "ddd"
Is there any practical use of this? Why would anyone use it with contructor or without a written constructor?
My impressions are: it seems working, but smells like bad and strange practice. Am I right?
{} define the scope of a module or block of code (like a method, static block, class, etc.)
And every module should have a name of something to identify it from other modules.
In your case, simply putting {} means you are creating a block of code but not naming, hence it gives error. But putting {} inside a method will work fine.
But when you put static keyword before it, you are making a static block that has got special meaning in java. it means that everything inside static block will be executed when your class gets loaded first time.
See this link for initializer blocks from Java Tutorials website
Is there any practical use of this?
There is one "idiom" that makes use of instance initializer blocks:
Map mymap = new HashMap() {{put("a", 1); put("b", 2);}};
This is a concise way to create a map that is initialized with a given set of entries. And when you break it down, it is declaring and instantiating an anonymous subclass of HashMap which uses an instance initializer block to populate the new map.
My impressions are: it seems working, but smells like bad and strange practice.
That's a subjective statement. The only rational argument I can think of for initializer blocks being bad / strange is that people don't use them. And that argument smells of circular logic.
Its all about Initializer blocks
Initializer blocks for instance variables look just like static initializer blocks, but without the static keyword:
{
// will execute when intialization
}
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
These are called initializer blocks. They are called along with all constructor. So any constructor call will invoke this code.
A static block is called only when class is loaded.
Normally, you have to put the code to initialize an instance variable in a constructor. There are two alternatives to using a constructor to initialize instance variables: initializer blocks and final methods.
Initializer blocks for instance variables look just like static initializer blocks, but without the static keyword:
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
Source: here
It may be unfamiliar, but it is not bad per se. It's an initializer block that is executed on construction. See here for a more detailed explanation that includes static initialization blocks also.
If I try to assign a value to a variable in a class, but outside a method I get an error.
class one{
Integer b;
b=Integer.valueOf(2);
}
but, if I initialize it during the creation, it works.
class one{
Integer b=Integer.valueOf(2);
}
Inside a method, it works in both cases.
you need to do
class one{
Integer b;
{
b=Integer.valueOf(2);
}
}
as statements have to appear in a block of code.
In this case, the block is an initailiser block which is added to every constructor (or the default constructor in this case) It is run after any call to super() and before the main block of code in any constructor.
BTW: You can have a static initialiser block with static { } which is called when the class is initialised.
e.g.
class one{
static final Integer b;
static {
b=Integer.valueOf(2);
}
}
Because the assignments are statements and statements are allowed only inside blocks of code(methods, constructors, static initializers, etc.)
Outside of these only declarations are allowed.
This :
class one{
Integer b=Integer.valueOf(2);
}
is a declaration with an initializer. That's why is accepted
A more general answer would be that the class body is about declarations, not statements. There is a special provision for statements occuring in class body, but they have to be marked explicitly as either class initializers or instance initializers.
In Java, when defining a class, you can define variables with default values and add methods. Any executable code (such as assignments) MUST be contained in a method.
This is the way java works, you cannot add non-declaration code (sorry i don't know the correct term) inside the class, that code should be inside methods.
I think terminology-wise, couple of other answers are slightly off. Declarations are also statements. In fact, they are called "declaration statements", which are one of the three kinds of statements. An assignment statement is one form of "expression statement" and can be used only in constructs such as methods, constructors, and initializers. Check out the Statements section in this Oracle's tutorial link.
Methods have the responsibility to perform mutations on the member variables. If the member variable needs to be initialized, java provides a way to do it during construction, class definition (latter case). But the mutation cannot be performed during definition.(former case). It is usually done at the method level.
Objects are meant to hold the state, while methods are meant to operate on that state.