介紹
final關鍵字的作用有如下幾種
- final修飾類時,表明這個類不能被繼承
- final修飾方法,表明方法不能被重寫
- final修飾變量,如果是基本資料類型的變量,則其數值一旦在初始化之後便不能改變;如果是對象類型的變量,隻能保證它的引用不變,但對象的内容是可以改變的
修飾類
final修飾類時,表明這個類不能被繼承
// 編譯錯誤,提示
// Cannot inherit from final 'java.lang.String'
public class ClassDemo extends String{
}
盡量不要用final修飾類,除非這個類真的不可能被繼承,或者出于安全方面的考慮
修飾方法
final修飾方法,表明方法不能被重寫
在早期的版本,final修飾方法可以提高性能。不過在最新的版本中JVM做了優化,即使使用了final修飾也不會提高性能。
是以目前final的作用隻是不想讓子類重寫
修飾變量
final修飾變量,如果是基本資料類型的變量,則其數值一旦在初始化之後便不能改變;如果是對象類型的變量,隻能保證它的引用不變,但對象的内容是可以改變的
先來回顧一下8種基本資料類型
整數類型:byte(1位元組) short(2位元組) int(4位元組) long(8位元組)
浮點類型:float(4位元組) double(8位元組)
字元類型:char(2位元組)可以存儲一個漢字
布爾類型:boolean
JVM規範指出boolean當做int處理,也就是4位元組,boolean數組當做byte數組處理,這樣我們可以得出boolean類型占了單獨使用是4個位元組,在數組中是确定的1個位元組
public class VarDemo {
public final int var = 0;
public static void main(String[] args) {
VarDemo varDemo = new VarDemo();
// 編譯錯誤,提示
// Cannot assign a value to final variable 'var'
varDemo.var = 10;
}
}
從例子中可以看到,當想給final變量再次指派的時候,報編譯錯誤。
public class VarDemo {
public final Map<String, String> map = new HashMap<>();
public static void main(String[] args) {
VarDemo varDemo = new VarDemo();
varDemo.map.put("10", "10");
varDemo.map.put("20", "20");
// {20=20, 10=10}
System.out.println(varDemo.map);
}
}
map雖然被final修飾了,裡面的值還是可以改變的,因為對象類型的變量隻能保證對象的引用不變,對象的内容是可以改變的
public class VarDemo {
public final Map<String, String> map = new HashMap<>();
public static void main(String[] args) {
VarDemo varDemo = new VarDemo();
// 編譯錯誤,提示
// Cannot assign a value to final variable 'map'
varDemo.map = new HashMap<>();
}
}
如果想讓map中的資料也不能變該怎麼辦呢?有很多三方的類庫,如Google Guava
// 不可變集合的建立
ImmutableList<String> list = ImmutableList.of("a", "b", "c");
ImmutableSet<String> set = ImmutableSet.of("a", "b");
不可變集合是線程安全的,并且中途不可改變,因為add等方法是被聲明為過期,并且會抛出異常
public final void add(int index, E element) {
throw new UnsupportedOperationException();
}
還有需要注意的一點是在Java中數組也是對象,對象數組即使被final修飾,内容還是可以改變的
public class ArrayDemo {
public static void main(String[] args) {
final int array[] = {1, 2, 3};
for (int i = 0; i < array.length; i++) {
array[i] += 10;
// 11
// 12
// 13
System.out.println(array[i]);
}
}
}
public class VarDemo {
public static void invoke(final int a) {
// 可以讀,但不可以修改
System.out.println(a);
// 編譯錯誤,提示
// Cannot assign a value to final variable 'a'
a = 100;
}
}