The final Keyword
Sometimes you have a value that should never change. A crew member's max respect, the name of the city, the maximum wanted level: these are constants. In Java, the keyword final locks a variable so it can't be reassigned
final Variables
public class Main {
public static void main(String[] args) {
final int MAX_RESPECT = 100;
final String CITY = "Vice City";
System.out.println(CITY + " - Max respect: " + MAX_RESPECT);
}
}
Output
Vice City - Max respect: 100
Once a final variable is set, it's done. Try to change it and Java will refuse to compile:
public class Main {
public static void main(String[] args) {
final int MAX_RESPECT = 100;
MAX_RESPECT = 200; // ERROR: cannot assign a value to final variable
}
}
Naming Convention: ALL_CAPS
By convention, final constants use SCREAMING_SNAKE_CASE: all uppercase letters with underscores between words:
public class Main {
public static void main(String[] args) {
final int MAX_SPEED = 250;
final String PLAYER_NAME = "Tommy Vercetti";
final double COMMISSION = 0.15;
final int LIVES_AT_START = 3;
}
}
This makes constants instantly recognizable in your code. When you see MAX_SPEED, you know it's a constant without even looking at the declaration
final Fields in Classes
You can use final on class fields too. A common pattern is static final for class-wide constants:
class City {
static final String NAME = "Vice City";
static final int DISTRICTS = 6;
static final int YEAR = 1986;
}
public class Main {
public static void main(String[] args) {
System.out.println("City: " + City.NAME);
System.out.println("Districts: " + City.DISTRICTS);
System.out.println("Year: " + City.YEAR);
}
}
Output
City: Vice City
Districts: 6
Year: 1986
static final means "one copy for the whole class, and it never changes." This is the Java equivalent of a true constant. You'll see this pattern in real Java code everywhere
final Instance Fields
You can also make instance fields final: they get set once (in the constructor) and never change:
class Player {
final String name;
int respect;
Player(String name) {
this.name = name; // set once
this.respect = 0;
}
}
public class Main {
public static void main(String[] args) {
Player p = new Player("Lance Vance");
p.respect = 50; // fine, respect isn't final
// p.name = "Tommy"; // ERROR: name is final
System.out.println(p.name + ": " + p.respect);
}
}
Output
Lance Vance: 50
This is great for fields that should be set at creation and never modified, like a crew member's name
What final Does NOT Do
final stops reassignment of the variable, but it doesn't make objects immutable. If you have a final array, you can still change elements inside it:
public class Main {
public static void main(String[] args) {
final int[] earnings = {10, 20, 30};
earnings[0] = 99; // allowed! We changed the content, not the variable
// earnings = new int[]{1, 2, 3}; // ERROR! Can't reassign the variable
System.out.println(earnings[0]);
}
}
Output
99
final means the variable always points to the same object. What happens inside that object is a different story
Mission: Tommy's Constants
Some values in Tommy's empire must never change: the maximum respect a member can have and the name of the city. Define them as locked constants that no code can accidentally overwrite.
Create two final constants:
MAX_RESPECTset to100CITYset to"Vice City"
Print both constants on separate lines.
Example
100
Vice City