final fields and "might not have been initialized"¶
โ Java 17 ยท Giving Variables Their First Value ยท 2/3
Fields get default values, locals don't. final adds one more rule on top.
final locals¶
A final local variable follows the local rule (assign before use), and can be assigned only once:
public void launch() {
final String platformName = "NetStream";
platformName = "Other"; // โ doesn't compile
System.out.println(platformName);
}
final fields get no default¶
A final field is not auto-initialized. You must assign it exactly once, in one of three places:
- on its declaration,
- in an instance initializer block,
- in every constructor.
public class StreamingPlatform {
final int maxStreams;
public StreamingPlatform(int max) {
this.maxStreams = max; // โ
assigned in the constructor
}
}
Forget all three and the class doesn't compile. The compiler reports it on the field itself:
public class Subscription {
final int maxScreens; // โ not initialized in the default constructor
}
Once assigned, the field can never change: a reliable value for the object's whole life.
Every path must assign it¶
The compiler checks that a local variable is assigned on every possible path before it's read. This is called definite assignment:
public void show(boolean premium) {
int views;
if (premium) {
views = 5;
}
System.out.println(views); // โ might not have been initialized
}
When premium is false, views has no value. Assign it on every branch, or give it a starting value:
int views;
if (premium) {
views = 5;
} else {
views = 0;
}
System.out.println(views); // โ
assigned on both paths
The compiler doesn't run your code: it only looks at the possible paths. If one path could skip the assignment, it refuses.
Time to see the defaults with your own eyes.