There are three places that final can be used:
- data
- method
- class
final data
compile-time constant
In the case of compile-time constant, the compiler is allowed to "fold" the constant value into any calculations in which it is used. (That means the calculation can be completed during compile time)
In Java, these constants must be primitive and must be expressed with the final keyword. You also need to give it a value when it is defined.
A field that is final and static has only one piece of storage that cannot be changed.
When final is used for an object, that doesn't mean the object cannot be changed. It means that the reference is constant. This restriction also includes arrays, which are also objects.
Example
//: reusing/FinalData.java
// The effect of final on fields.import java.util.*;
import static net.mindview.util.Print.*;
class Value {
int i;
// Package access
public Value(int i) { this.i = i; }
}
public class FinalData {
private static Random rand = new Random(47);
private String id;
public FinalData(String id) { this.id = id; }
// Can be compile-time constants:
private final int valueOne = 9;
private static final int VALUE_TWO = 99;
// Typical public constant:
public static final int VALUE_THREE = 39;
// Cannot be compile-time constants:
private final int i4 = rand.nextInt(20);
static final int INT_5 = rand.nextInt(20);
private Value v1 = new Value(11);
private final Value v2 = new Value(22);
private static final Value VAL_3 = new Value(33);
// Arrays: private final int[] a = { 1, 2, 3, 4, 5, 6 };
public String toString() {
return id + ": " + "i4 = " + i4 + ", INT_5 = " + INT_5;
}
public static void main(String[] args) {
FinalData fd1 = new FinalData("fd1");
//! fd1.valueOne++; // Error: can’t change value
fd1.v2.i++; // Object isn’t constant!
fd1.v1 = new Value(9); // OK -- not final
for(int i = 0; i < fd1.a.length; i++)
fd1.a[i]++; // Object isn’t constant!
//! fd1.v2 = new Value(0); // Error: Can’t
//! fd1.VAL_3 = new Value(1); // change reference
//! fd1.a = new int[3];
print(fd1);
print("Creating new FinalData");
FinalData fd2 = new FinalData("fd2");
print(fd1);
print(fd2);
}
} /* Output:
fd1: i4 = 15, INT_5 = 18
Creating new FinalData
fd1: i4 = 15, INT_5 = 18
fd2: i4 = 13, INT_5 = 18
*///:~```
valueOne and VALUE_TWO are compile-time constants because they are primitives with compile-time values.
VALUE_THREE is more typical: **public** so it's usable outside the package, **static** to emphasize there is only one, and **final** to say that it's constant.
Note that something final doesn't mean its value is known at compile time, such as i4 and INT_5. i4 and INT_5 also shows the difference between making a final value **static** or **no-static**.
You can see that i4 can be different between different instances, while INT_5 won't change since all the instances share the same INT_5.
**final arguments**
You can make arguments final, this means inside the method you cannot change what the arguments reference to. This feature is primarily used to pass data to anonymous inner classes.
## final method
Put a “l(fā)ock” on the method to prevent any inheriting class from changing its meaning.
**private vs final**
All the private method is implicitly declared as "final".
If you try to override the private method, compiler won't say it's wrong. However, you just add a new method to your class, not overriding.
## final class
When you say that an entire class is final (by preceding its definition with the final keyword), you state that you don’t want to inherit from this class or allow anyone else to do so.