1. Syntactic sugar
Programmers love when some complex code or logic can be written in a couple of lines, making code compact and readable. And the creators of programming languages sometimes help with this.
A slick language feature that lets you take a shortcut (write less code) is called syntactic sugar. But, to be honest, there is very little of it in Java.
Java's creators did everything they could to eliminate any redundancy in Java. If C++ lets you do something 20 ways, then Java lets you do it only one way.
But neither Java programmers nor Java's creators liked the lack of freedom. And sometimes sugar makes life easier for ordinary folks like you and me.
By the way, you've already encountered some syntactic sugar: autoboxing and unboxing. Let's compare:
Long code | Compact code |
---|---|
|
|
|
|
|
|
Instead of the long code like on the left, you can write the more compact code on the right. And intelligent Java compiler will generate the verbose version of the code based on the short version of the code. This is exactly what syntactic sugar is.
2. Inference of a variable's type: the var
keyword
In Java 11, the compiler became even smarter and can now determine the type of a declared variable based on the type of the value assigned to it. In code, it looks like this:
var name = value;
Where name
is the name of a new variable, value is its initial value, and var
is a keyword used to declare the variable. The type of the name variable will be the same as the type of the value assigned to it.
Examples:
How we see the code | What the compiler sees |
---|---|
|
|
|
|
|
|
|
|
|
|
The compiler itself determines, or infers, the variable's type based on the value assigned to it.
Programmers debated hotly over whether to add such a feature to the language. Many people feared that var
would be abused and that code readability would suffer as a result.
There is a grain of truth to this, so it is best to use var
where it increases the readability of the code. For example, these in two cases:
Case 1: Looking at the value assigned to the variable, the variable's type is immediately clear
Code | Explanation |
---|---|
|
The variable is an InputStream |
|
The variable is a String |
In these cases, you shouldn't use var
. Well, what is the variable's type?
Code | Explanation |
---|---|
|
It's difficult to determine the variable's type |
|
It's difficult to determine the variable's type |
Case 2: The variable's type is not important for understanding the code
Code often has no need to call methods on a variable, e.g. when a variable is simply used to temporarily store something. In this case, using var
definitely does not reduce the readability of the code:
Long code | Compact code |
---|---|
|
We got metadata from the stream stream and saved it in the storage repository. The data variable's specific type is not important. |
The golden mean
Now I'll give three ways to write the same code. Using var
would be the best option.
Code | Note |
---|---|
|
Too compact |
|
Just right |
|
Too detailed |
Moving from the version with 1 line to the version on 2 lines, we made the code a little more readable by using a variable name (headerInfo
). Now it's clear that the method returns not just meta information, but header information.
The third version is overly verbose. The fact that headerInfo
is a FileMetaInfo
is already fairly clear from the getFileMetaInfo()
method. The purpose of the meta information is much more interesting.
3. Omitting the type with the diamond operator: <>
Even before the var
operator appeared, there were attempts to teach the compiler how to infer collection types. You'll agree that this notation looks a little redundant:
ArrayList<String> list = new ArrayList<String>();
Starting from the seventh version of Java, when writing a collection type, you could omit the type of the collection elements if it was specified when declaring a variable. In other words, the code above can be written in a slightly abbreviated form:
ArrayList<String> list = new ArrayList<>();
As you can see, you no longer need to write String a second time. Not as cool as with the var operator, but it seemed like progress at the time.
The empty angle brackets in the collection type were called the diamond operator, since the two angle brackets vaguely resemble a diamond.
It's undesirable to use the var
keyword and the diamond operator at the same time:
var list = new ArrayList<>();
There is no information at all about the type of the elements stored in the collection, and the collection type will be ArrayList<Object>.
4. Double curly braces
Remember quick array initialization?
We just listed values in curly braces, like this:
Examples |
---|
|
|
Java's creators loved the idea of using curly braces to simplify writing elements of an array. But what about collections?
Java's creators had enough creative thinking for collections as well, allowing them to use a trick with double curly braces.
With sugar | Without sugar |
---|---|
|
|
If the compiler encounters code like in the example on the left, then it converts it to the code on the right.
The code doesn't become a lot more compact. The savings here are fairly insignificant: you don't have to write list
every time. This can be helpful if the variable name is very long.
But if you come across code like this in a project, don't be surprised 🙂
GO TO FULL VERSION