var and final
So far you have written a variable's type yourself: int age = 30;. But 30 stands on the right, and the compiler can see on its own that it is a whole number. So why repeat it?
Picture bringing an item to a warehouse and asking for a box to fit it. The clerk looks at the item, picks a suitable shape and labels the box. After that the shape does not change: an aquarium will not go into a box made for a book. This is how the word var works in Java:
public class Main {
public static void main(String[] args) {
var count = 10;
var price = 2.5;
var letter = 'J';
count = 20;
System.out.println(count); // 20
System.out.println(price); // 2.5
System.out.println(letter); // J
}
}var: the type from the value
The word var in place of a type asks the compiler to work out the type from the value on the right. This is called type inference, and Java got it in version 10. Let's walk through the three declarations:
- In
var count = 10;the right side is anintliteral, socounthas the typeint. - In
var price = 2.5;the right side is adoubleliteral, andpricegets the typedouble. - In
var letter = 'J';the right side is acharliteral, andlettergets the typechar.
The compiler fills in the type once, at compile time. The line var count = 10; means exactly the same as int count = 10;, only shorter. That is why count = 20; works: a new whole number goes into a box for whole numbers.
The type does not change
var does not turn a variable into a box "for anything". The type is chosen at the declaration and stays the same afterwards:
var count = 10;
count = 2.5; // ✗error: incompatible types: possible lossy conversion from double to intcount has the type int, and a fraction cannot go into it, as if you had written int count = 10;. Interviewers like to ask whether var makes Java a dynamically typed language, one where a variable's type is decided while the program runs and can change. It does not: the type is still known at compile time, only the compiler fills it in instead of you.
This is where the clerk picture falls short. A real clerk might pick a box with room to spare. The compiler takes exactly the literal's type: var n = 10; has the type int, even if later you want to put a bigger number there.
Where var works
- Only for variables declared inside a method, such as
main. - Only when the value is given right away: the compiler needs something to infer the type from.
final: a sealed box
The word final before a declaration forbids changing a variable once it holds a value. It is a sealed box: what was put in stays in. final appears on a variable inside main and on a variable declared right in the class:
public class Main {
static final int MAX_SPEED = 120;
public static void main(String[] args) {
final int limit = 90;
System.out.println(limit); // 90
System.out.println(MAX_SPEED); // 120
}
}final inside main
final int limit = 90; is an ordinary variable that can no longer be changed. If you write limit = 100; below it, the compiler answers:
error: cannot assign a value to final variable limitThe value can also be put in later, but only once: first final int limit;, then limit = 90;. Such a variable is named as usual: limit, maxPrice.
Constants
A value shared by the whole program, such as a speed limit, is declared not inside main but right in the class, next to it. Such a variable is called a constant. Let's take apart the line static final int MAX_SPEED = 120;:
staticworks as onmain: the variable belongs to the classMainitself, and the program holds one copy of it;finalforbids changing it;MAX_SPEEDis the constant's name: it is written in capital letters, with words separated by underscores.
Changing the constant inside main fails too: the program does not compile, as with limit.
Common mistake
var was written without a value:
var total; // ✗
total = 5;error: cannot infer type for local variable totalThe compiler has nothing to infer the type from: var total has no value on the right. Give it a value right away, var total = 5;, or write the type yourself: int total;.
Key points
varinfers the type from the value on the right once, at compile time:var count = 10;is the same asint count = 10;.- The type of a
varvariable does not change, socount = 2.5;does not compile. finalforbids changing a variable once it holds a value.- A constant is declared in the class as
static finaland named in capital letters:MAX_SPEED.