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.
Related
I'm learning Java and I can't understand the difference between a block and a method.
Block is a series of statements enclosed in curly braces.
Uses of blocks include, but not limited to:
Methods (A block is required since it is the method's body)
If/Else statements
For/While/Do-While Loops
Lambdas
A method is a block in the class scope that might accept a set of parameters and might produce a result through the return statement.
Code blocks GENERALLY live inside methods (but not always, there are exceptions).
Methods are also (generally) named and can be called from elsewhere in your code by that name. Blocks cannot, they can only be reached by following the flow of the code in your class (so generally through calling the method they're contained in and reaching the proper conditions for their execution).
Apart from above answers there is one more block, that is static block like the below one.
public class Block {
static {
System.out.println("Test");
}
public static void main(String[] args) {
}
}
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).
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.
I recently read some code that uses a special syntax regarding {}, I've asked a more experienced Java developer, but he also can't answer.
public void doSomething() {
someWorks();
{
someVariables;
someMoreWorks();
}
someEvenWorks();
{
...
}
}
Why does the code author put these lines inside {}? I guess that the variables declared within the {} will be released right after execution exits {}, right, because I can't access these outside the {} anymore?
Yes, the only difference is for scoping.
Occasionally this can be useful for throwaway code such as micro-benchmarks where you want to be able to cut and paste a block and make a minor change, then potentially reorder the blocks.
I would rarely (if ever) have something like this in "real" code though.
This gives him a nested scope to declare "more local" variables.
I guess that the variables declared within the {} will be released right after exit {}, right, because I can't access these outside the {} anymore?
Depends on your definition of "release" (they will most likely not be garbage collected until the method ends, so if this is important, you might want to null them out), but yes.
Other rarely seen uses of curly brackets include class and instance initializers:
class A {
static {
// some class initialization code
}
{
// some instance initialization code
}
}
The fact that the author put those variables in {} indicates the scope of those variables will only be that of the method defined by the {}; in turn, those variables will be up for garbage collection once method finishes execution.