Objectos Weekly #010: Blocks are statements in Java
Welcome to Objectos Weekly issue #010.
You may have noticed I have been reading the Java Language Specification. I am learning a bunch of details about the language that are new to me. And I have been sharing these findings with you.
Lately, I have focused on blocks; that curly brackets thingy where you can write statements. Or not... blocks can be empty as well.
In this issue, I will tell you about the fact that blocks are statements in Java.
In the next (or a future) issue, I will talk about instance and static initializers, which are also blocks.
Let's begin.
Block is a statement
Blocks are statements in the Java programming language. If you are curious, you can look at the grammar. This means we can write the following over the top hello-world-like program:
public class Blocks {
public static void main(String[] args) {
{
{
{
System.out.println(
"I'm inside 4 nested blocks!");
}
}
}
}
}
When executed, it prints:
I'm inside 4 nested blocks!
Wait, did you say four blocks?
Blocks and body methods
Syntactically speaking, the body of a method is also a block.
Method declarations are defined in section 8.4 of the Java Language Specification (JLS):
MethodDeclaration:
{MethodModifier} MethodHeader MethodBody
The MethodBody
production is defined a little later in section 8.4.7:
MethodBody:
Block
;
So the body of a method can be either:
-
a
Block
if the method is non-abstract; or -
a semicolon, if the method is abstract.
That's why, in the previous section, the example prints "4 nested blocks".
Blocks and local variables
Blocks are explained in chapter 14 of the JLS. The introduction of the chapter has the following to say about blocks:
Blocks are explained first (§14.2), both because they can appear in certain places where statements are not allowed and because one kind of statement, a local variable declaration statement (§14.4.2), must be immediately contained by a block.
So it seems blocks and local variables share a special relationship. I assume this relationship has to do with the lexical scope of the latter.
Local variables with the same name
The following Java code does not compile:
public class LocalVar1 {
public static void main(String[] args) {
var message = "First!";
System.out.println(message);
// does not compile!
var message = "Second!";
System.out.println(message);
// does not compile!
var message = "Third!";
System.out.println(message);
}
}
It tries to define three different variables with the same name. This is not allowed. So compilation fails with the following message:
$ javac -d /tmp src/main/java/post/LocalVar1.java
src/main/java/post/LocalVar1.java:13: error:
variable message is already defined in method main(String[])
var message = "Second!";
^
src/main/java/post/LocalVar1.java:16: error:
variable message is already defined in method main(String[])
var message = "Third!";
^
2 errors
Let's try to fix the compilation errors.
Local variables with the same name (redux?)
On the other hand, the following compiles without errors:
public class LocalVar2 {
public static void main(String[] args) {
{
var message = "First!";
System.out.println(message);
}
{
var message = "Second!";
System.out.println(message);
}
var message = "Third!";
System.out.println(message);
}
}
We have enclosed the first and the second variables in two distinct and separate blocks. In doing so, we restricted the scope of both variables to their respective enclosing blocks.
When executed, it prints:
First!
Second!
Third!
So we could say that the enclosing block of a local variable defines what local means. In other words, a variable is local to its immediately enclosing block.
But blocks can be nested inside other blocks.
Nested block
Let's nest the second block inside the first one. Like so:
public class LocalVar3 {
public static void main(String[] args) {
{
var message = "First!";
System.out.println(message);
{
// does not compile!
var message = "Second!";
System.out.println(message);
}
}
var message = "Third!";
System.out.println(message);
}
}
After this change our code to does not compile anymore:
$ javac -d /tmp src/main/java/post/LocalVar3.java
src/main/java/post/LocalVar3.java:15: error:
variable message is already defined in method main(String[])
var message = "Second!";
^
1 error
The message
variable declared in the first block is visible to the second block.
So, in the second block, we are not allowed to create a local variable with the same name.
Why?
So, why is block a statement? I don't know the answer.
But I assume that statements which contain other statements might be one of the reasons.
The if
statement
The if-then
statement is defined in Section 14.9 of the JLS:
IfThenStatement:
if ( Expression ) Statement
Notice how it is a statement that contains another statement.
So we can combine an if
statement with a return
statement for example:
if (isEmpty()) return "[]";
But, since block is a statement, we can also write:
if (condition()) {
foo();
bar();
}
So it is quite convenient to the if
statement that block is also a statement.
In other words, if block was not a statement,
the if
statement grammar production would need to be changed;
it would require additional rules to represent the second form.
Other statements
It works the same with other statements.
Let's see the while
statement for example:
WhileStatement:
while ( Expression ) Statement
It is also a statement that contains another statement.
So you can combine the while
statement with the break
statement:
while (true) break;
Though one could argue this is not very useful...
And, as block is a statement, you can also write:
while (keepGoing()) {
stepA();
stepB();
}
Of course, there are more examples of statements which contain other statements. But I think this is enough for now.
Take these with a grain of salt
As mentioned, I don't know if the statements in the previous section are the reason why block itself is a statement. It is only my assumption.
Additionally, while the syntax allows you to write code in the form:
void method() {
{
var foo = foo();
bar(foo);
}
}
This is hardly an example of "idiomatic" Java. Granted, different teams or individuals will have different views on what is "idiomatic". But still, it might confuse readers for no good reason.
Let's work together
Do you feel that adding features to your Java applications is taking longer as time goes by? Perhaps I can help. Let's get in touch.
You can find my contacts on this page. All work will be provided via Objectos Software LTDA based in São Paulo, Brazil.
Until the next issue of Objectos Weekly
So that's it for today. I hope you enjoyed reading.
The source code of all of the examples are in this GitHub repository.
Please send me an e-mail if you have comments, questions or corrections regarding this post.