文章目錄
- 一、 final的意義
- 二、 final的使用
- (1) final修飾類
- (2) final修飾方法
- (3) final修飾變量
- 1. 修飾成員變量
- 1.1 舉例1
- 1.2 舉例2
- 2. 修飾局部變量
- 2.1 舉例1
- 2.2 舉例2
- (4)final搭配static
- (5)總結
- 三、 筆試題
- (1)題1
- (2)題2
一、 final的意義
final
:最終的,不可更改的
final
可以用來修飾的結構:類、方法、變量(成員變量、局部變量)
二、 final的使用
(1) final修飾類
表示這個類不能被繼承,沒有子類。提高安全性,提高程序的可讀性。
例如:String類、System類、StringBuffer類
final class Eunuch{//太監類}
class Son extends Eunuch{//錯誤}
【舉例】
正常情況下:
class A{}class B extends A{}
若此時類A前面有final修飾,則B無法繼承于A。如下:
💬什么樣的類需要用final去修飾呢?
功能不需要再被擴展了,比如String
類、StringBuffer
類、StringBuilder
類。
會發現String加了一個final修飾:
public final class String...
這就意味著不能去聲明一個類去繼承于String。
Stirng類用final修飾,沒有必要再進行功能的擴展。
(2) final修飾方法
表示這個方法不能被子類重寫。
例如:Object類中的getClass()
class Father{public final void method(){System.out.println("father");}
}
class Son extends Father{public void method(){//錯誤System.out.println("son");}
}
【舉例】
正常情況下:
class C{public void method(){}
}class D extends C{//此時可以public void method(){}
}
若是method()方法前面有final
修飾,就不能重寫了。如下:
💬什么樣的方法需要用final去修飾呢?
當這個方法已經設計的很完備了,也沒有擴展的必要性,就可以用final修飾。
比如Object類中的getClass()
。
可以看一下,首先Ctrl+N
調出搜索框,輸入“Object”:
然后Ctrl+F12
,搜索”getClass“:
然后可以看到getClass被final修飾,表示這個方法不能被重寫了。這個方法的作用就是獲取當前對象所屬的類,不需要重寫。
native
表示調用的是本地的方法,會調用底層C、C++相關的代碼。
native修飾的getClass()方法若是調用的時候,這個方法的棧幀會進入棧中,此時它入的棧叫做本地方法棧。
這個本地方法,就是指native修飾的方法。
為啥getClass()方法沒有方法體?因為它調用的是底層的C、C++,不是用java代碼寫的,所以沒有方法體。它會鏈接到相關dll文件中的C、C++代碼。
在早期,Java發展不成熟的時候,會用到native。
(3) final修飾變量
final修飾某個變量(成員變量或局部變量),一旦賦值,它的值就不能被修改,即常量
,常量名建議使用大寫字母。
例如:final double MY_PI = 3.14;
如果某個成員變量用final修飾后,沒有set方法,并且必須初始化(可以顯式賦值、或在初始化塊賦值、實例變量還可以在構造器中賦值)
1. 修飾成員變量
1.1 舉例1
public class FinalTest {public static void main(String[] args) {E e=new E();System.out.println(e.MIN_SCORE); //可以調用}
}class E{//成員變量final int MIN_SCORE=0;
}
常量MIN_SCORE可以被調用,但是不能更改:
若此時將常量的顯示賦值刪掉,發現不可以:
沒有默認值嗎?
對于final
修飾的成員變量,這時候默認值就不好使了。即使想用默認值0,也需要寫出來。
若用方法賦值,不可以:
方法需要用對象去調用,而調用對象的時候,這個值該有就應該得有了。
之前說過給類的實例變量賦值的位置,其中默認初始化、顯示初始化、代碼塊中初始化、構造器中初始化,它們在造對象過程中實現;而通過“對象.屬性”或“對象.方法”進行賦值的時候,對象已經有了。
現在我們給常量賦值,意思就是當創建完對象的時候,這些屬性的值就應該要有了。
后續調用方法(比如setRight()方法),體現為修改這個值。
而在聲明它的時候沒有賦值,而在有了對象之后,方法里面又不能修改這個值。
當對象創建完,屬性的值就應該確定下來了。
💬有哪些位置可以給成員變量賦值?
- 顯式賦值
- 代碼塊中賦值
- 構造器中賦值
class E{//成員變量//1.默認賦值--NO//final int MIN_SCORE;//2.顯示賦值--YESfinal int MIN_SCORE=0;//3.代碼塊中賦值--YESfinal int MAX_SCORE;{MAX_SCORE=100; //一旦賦值就不可以再次賦值}//4.構造器中賦值--YESfinal int LEFT;public E(){ //用此構造器造完對象LEFT就賦完值了LEFT=2;}public E(int left){ //不同構造器都需要對常量LEFT賦值,每造一個對象就會擁有一份LEFT,所以每個對象的LEFT可以不同,但是一旦賦值不可更改LEFT=left;}//5.方法賦值--NO/*final int RIGHT; //沒有在允許的位置賦值public void setRIGHT(int right){RIGHT=right; //有了對象之后,不能在方法里面修改常量的值}*/}
1.2 舉例2
public final class Test {public static int totalNumber = 5;public final int ID;public Test() {ID = ++totalNumber; // 可在構造器中給final修飾的“變量”賦值}public static void main(String[] args) {Test t = new Test();System.out.println(t.ID);}
}
2. 修飾局部變量
final修飾局部變量:一旦賦值就不能修改
2.1 舉例1
- 方法內聲明的局部變量:在調用局部變量前,一定需要賦值。而且一旦賦值,就不可更改。
【舉例】
一般情況下:
class F{public void method(){int num=10;num++;System.out.println(num);}
}
若此時給num加上final,就不可以對num更改了:
如下:
class F{public void method(){final int num=10; //寫兩行也沒事,只要在調用它之前賦上值就行,一旦賦值不可更改//num++;System.out.println(num);}
}
- 方法的形參:在調用此方法時,給形參進行賦值。而且一旦賦值,就不可更改。
【舉例】
一般情況下:
class F{public void method(int num){num++;System.out.println(num);}
}
若是給num加上final
,num就是一個常量,這個常量還是在調用的時候賦的,那么賦完值之后就不要更改了。
如下:
class F{public void method(final int num){//num++; //賦完值之后就不要更改了System.out.println(num);}
}
2.2 舉例2
public class TestFinal {public static void main(String[] args){final int MIN_SCORE ;MIN_SCORE = 0;final int MAX_SCORE = 100;MAX_SCORE = 200; //非法}
}
- 錯誤演示:
class A {private final String INFO = "atyuyi"; //聲明常量public void print() {//The final field A.INFO cannot be assigned//INFO = "雨翼輕塵"; }
}
(4)final搭配static
final
與static
搭配:修飾成員變量時(不能是局部變量,static不能修飾局部變量),此成員變量稱為:全局常量
。(只有一個且不能改變)
這個變量兼具final和static的特點。
比如:Math的PI (直接通過類來調用且不能變)
在實際寫代碼的時候,若是在修飾類、修飾方法的時候忘記使用不礙事,但是修飾變量的時候記得加上,而且變量名要大寫。
(5)總結
1、 final
的理解:最終的
2、final
可以用來修飾的結構:類、方法、變量(成員變量、局部變量)
3、具體說明:
-
final修飾類:表示此類不能被繼承。
比如:String、StringBuffer、StringBuilder類 -
final修飾方法:表示此方法不能被重寫
比如:Object類中的getClass() -
final修飾變量:既可以修飾成員變量,也可以修飾局部變量。
此時的"變量"其實就變成了"常量",意味著一旦賦值,就不可更改。-
final修飾成員變量: 有哪些位置可以給成員變量賦值?
> 顯式賦值
> 代碼塊中賦值
> 構造器中賦值 -
final修飾局部變量:一旦賦值就不能修改
> 方法內聲明的局部變量:在調用局部變量前,一定需要賦值。而且一旦賦值,就不可更改
> 方法的形參:在調用此方法時,給形參進行賦值。而且一旦賦值,就不可更改
-
4、 final
與static
搭配:修飾成員變量時,此成員變量稱為:全局常量。
比如:Math的PI
三、 筆試題
(1)題1
排錯
public class Something {public int addOne(final int x) {//return ++x; //不可以return x + 1; //可以,x值沒有變}
}
(2)題2
排錯
public class Something {public static void main(String[] args) {Other o = new Other();new Something().addOne(o);}public void addOne(final Other o) {// o = new Other();o.i++; //讓i++可以,因為i是變量,o不能變}
}
class Other {public int i;
}
局部變量o指向一個Other對象,Other對象里面有一個i,i沒有用final修飾,表示它是一個變量。
將o加了一個final,意味著它的地址不能變了,而o指向的對象的屬性可以變化。
如下: