在 Java 中,有三種情況可能使用到 final:數據、方法和類。
1. final 數據
對於基本類型,final 使數值恆定不變;對於對象引用,final 使其引用不變,但是引用指向的對象本身可以被修改,數組也是對象。
public class finalData {
private static final int VAL_1 = 1;
private final Value value_1 = new Value(2);
private final int a[] = {1, 2, 3, 4};
public static void main(String[] args) {
finalData finalData = new finalData();
// finalData.VAL_1 = 2; // error:Cannot assign a value to final variable 'VAL_1'
// finalData.value_1 = new Value(3); // error:Cannot assign a value to final variable 'value_1'
finalData.value_1.i++;
// finalData.a = new int[3]; //error:Cannot assign a value to final variable 'a'
for (int i = 0; i < finalData.a.length; i++) {
finalData.a[i]++;
}
}
}
class Value {
int i;
public Value(int i) {
this.i = i;
}
}
可以看到,雖然引用 value_1 不能改變,但是其成員 i 是可以改變的,數組 a 同理。
空白 final
空白 final 是指被聲明爲 final 但又未給定初值的域。但是無論什麼情況,編譯器都會確保空白 final 在使用前被初始化,否則會提示未初始化變量。
final 參數
將參數指明爲 final 時,意味着無法在方法中更改參數引用所指向的對象。
public class FinalArguments {
void without(Gizmo g){
g = new Gizmo();
g.spin();
}
void with(final Gizmo g){
// g = new Gizmo(); // Error,g 被定義爲 final
}
void g(final int i){
// i++; // Error,i 被定義爲 final
}
int f(final int i){
return i+1;
}
public static void main(String[] args) {
FinalArguments fa = new FinalArguments();
Gizmo gizmo = new Gizmo();
fa.with(gizmo);
fa.without(gizmo);
}
}
class Gizmo{
public void spin(){}
}
2. final 方法
使用 final 方法可以把方法鎖定,防止任何繼承類修改它的定義。
類中所有的 private 方法都隱式地指定爲 final 的,繼承類無法取到 private 方法,當然也無法覆蓋它,所以爲 private 方法添加 final 修飾詞毫無意義。
class WithFinals {
private final void f(){
System.out.println("WithFinals.f()");
}
private void g(){
System.out.println("WithFinals.g()");
}
}
class OverridingPrivate extends WithFinals{
// 雖然此時 OverridingPrivate 繼承了 WithFinals 類,但是這並不是重寫的父類方法,只是名字相同而已
private final void f(){
System.out.println("OverridingPrivate.f()");
}
private void g(){
System.out.println("OverridingPrivate.g()");
}
public static void main(String[] args) {
OverridingPrivate op = new OverridingPrivate();
op.f();
op.g();
WithFinals wf = op;
// wf.f(); 子類對象無法調用父類對象的私有方法
// wf.g(); 子類對象無法調用父類對象的私有方法
}
}
3. final 類
當使用 final 修飾類時,表明該類無法被繼承。
由於 final 類禁止繼承,所以 final 類中所有方法隱式指定爲 final 的,因爲無法覆蓋它們。
final class Dinosaur {
int i = 1;
}
// class Further extends Dinosaur{} // Error:Cannot inherit from final 'Dinosaur'
總結
被 final 修飾的數據/方法/類無法被改變
- final 修飾基本類型時,該數據被初始化一次後無法改變,當 final 修飾引用類型時,該引用不可變,但是引用指向的對象本身可變。
- final 修飾方法時,該方法無法被重寫
- final 修飾類時,該類無法被繼承