Java基礎知識詳解:final修飾符


@author:Tobin
水平有限,如有錯誤,望請斧正。
參考《Java核心技術卷-基礎知識第10版》
https://blog.csdn.net/sinat_38899160/article/details/72650686


本節討論final修飾符的使用。
final顧名思義有最終的含義,通過幾個問答解釋final的奧義。

Q1:final修飾基本類型域

回顧下基本類型。

A:被final修飾的實例域,構建對象時必須初始化這樣的實例域,也就是說,必須確保在每一個構造器執行之后,這個域的值被設置,並且在后面的操作中,不能夠再對它進行修改。下面代碼中的E變量就是被final修飾的而必須初始化的實例。
除了實例類型,final還被用來修飾局部變量和靜態變量。關於final修飾static變量,放到static中講解。
放到static中詳解。
修飾static變量即靜態變量時,此時這樣的變量又被稱為靜態常量,靜態常量是屬於類的,而不是屬於對象,即可以直接利用類名訪問靜態常量,它被所有對象共有,即1000個對象可以有1000個S(下面代碼中的字符串)拷貝,但是只會有1個C,即使沒有聲明任何對象,C也是存在的。比如Math類中的Math.PI。

package test;

public class Employee { 
    private final String S="final實例變量S"; 
    private final int A=100; 
    public final int B=90; 
    public static final int C=80; 
    private static final int D=70; 
    public final int E; //final空白,必須在初始化對象的時候賦初值 
    public Employee(int x){ 
    E=x; 
    } 
    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
        Employee t=new Employee(2); 
        //t.A=101; //出錯,final變量的值一旦給定就無法改變 
        //t.B=91; //出錯,final變量的值一旦給定就無法改變 
        //t.C=81; //出錯,final變量的值一旦給定就無法改變 
        //t.D=71; //出錯,final變量的值一旦給定就無法改變 
        System.out.println(t.A); 
        System.out.println(t.B); 
        System.out.println(t.C); //不推薦用對象方式訪問靜態字段 
        System.out.println(t.D); //不推薦用對象方式訪問靜態字段 
        System.out.println(Employee.C); 
        System.out.println(Employee.D); 
        //System.out.println(Employee.E); //出錯,因為E為final空白,依據不同對象值有所不同. 
        System.out.println(t.E); 
        Employee t1=new Employee(3); 
        System.out.println(t1.E); //final空白變量E依據對象的不同而不同 
        } 
        private void test(){ 
        System.out.println(new Employee(1).A); 
        System.out.println(Employee.C); 
        System.out.println(Employee.D); 
        } 
        public void test2(){ 
        final int a; //final空白,在需要的時候才賦值 
        final int b=4; //局部常量--final用於局部變量的情形 
        final int c; //final空白,一直沒有給賦值. 
        a=3; 
        //a=4; 出錯,已經給賦過值了. 
        //b=2; 出錯,已經給賦過值了. 
        } 
}

在構造Employee對象時,需要初始化。如果不寫構造函數,編譯器會直接報錯,如果在構建對象時,不傳入參數,一樣會報錯。

Q2:final修飾方法

A:被final修飾的方法不能夠被繼承。如下,當我們要改寫f2函數的時候會報錯。final修飾方法的一個好處是可以提高運行效率,編譯器遇到final方法會轉入內嵌機制(推薦博文https://blog.csdn.net/Java_I_ove/article/details/76946598),具體是如何提高的,放到以后學習JVM再研究。

// Test1.java
package test;
public class Test1 {
    public void f1()
    {
        System.out.println("this is f1 from Test1");
    }
    
    public final void f2()
    {
        System.out.println("this is f2 from Test1");
    }
}

// Test2.java
package test;

public class Test2 extends Test1{

    public void f1()
    {
        System.out.println("this is f1 from Test1");
    }
    
    public void f2() //這里會報錯
    {
        System.out.println("this is f2 from Test1");
    }

}

我們會很自然地聯想到,Java中的構造函數可以被final修飾嗎?在構造函數前面加final修飾符,編譯器會直接報錯。結論是不可以的。首先父類的構造函數不是成員函數,是不能夠被繼承的,但是可以被子類調用,既然不能被繼承,也就不可以被重寫。那么final修飾構造函數也就沒有任何意義。至於構造函數在繼承中是如何運行的,留到其它章節去研究(推薦博文https://blog.csdn.net/yuxiaohui78/article/details/43887373,https://blog.csdn.net/qiumengchen12/article/details/44829907)。

A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.
來源: https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

Q3:final修飾類

final修飾的類是不可以被繼承的。比如常見的string類。當給類加上final修飾后,類內的方法加不加final都是不可以被重寫的。

Q4:final修飾參數

final修飾傳入方法的參數時,該參數只讀,不可以修改。

Q5:final修飾對象

final修飾對象時,不可以再指向其它的對象,但是對象的內容是可以修改的。

        final Employee a = new Employee(2);
        Employee b = new Employee(3);
        a.temp = 2;//可以執行,final指向的對象不允許改變,但是可以修改對象的內容
        b = a;//可以執行,b並未聲明final
        a = b;//出錯,final指向的對象不允許更換


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM