Java學習筆記18---final關鍵字修飾變量、方法及類


英語里final這個單詞大家都知道是“最終的”意思,其實還有一個意思是“不可更改的”。在Java里,final關鍵字作“不可更改的”來解釋更合適,即由final修飾的東西是“不可更改的”。final可以修飾變量、成員方法和類,還可以修飾方法的參數,但參數歸根結底還是變量。下面是詳細解釋。


作者: 蟬蟬

請尊重作者勞動成果,轉載請在標題注明“轉載”字樣,並標明原文鏈接:

http://www.cnblogs.com/chanchan/p/7936388.html 

 

1.final可以修飾成員變量、局部變量

(1).final修飾的變量的值不能更改,即不能再次賦值,即使賦的新值與舊值一樣也不可以。

如:

      final int i = 1; //定義int型變量i,並賦初值為1

      //i = 2; //wrong

      //i = 1; //wrong

注釋掉的這兩行都不可以,都會出現“The final local variable i can not be assigned.It must be blank and not using a compound assignment.”的錯誤。

(2).final修飾的成員變量和局部變量需要在使用前賦值。

    1).對成員變量而言,可以在定義時直接賦初值;

    2).也可以先定義不賦初值,再在構造方法中對其賦值。

就是說,對象創建好后,該對象的final成員變量要保證是賦了初值的,早點(定義時賦值)、晚點(在構造方法里賦值)都沒關系。

注:第二種情況,如果有多個構造方法就比較麻煩了,每個構造方法都要有賦值語句,否則會出現“The blank final field height may not have been initialized.”的錯誤。

      3).如果靜態成員變量被修飾為final,那么該變量可看成是全局變量,即在類的整個加載期間,其值都不可變。

          如:

          static final String citizenship = "Chinese";

          citizenship既是static又是final的,static說明它是屬於整個類的,類加載時就分配內存了(參見筆記9),final說明其值不可變,即,位置固定內容也固定。

(3).把成員變量和局部變量從變量的類型上來分,

    1).當變量為基本數據類型時,變量的值不可更改,如上面的變量i;

    2).當變量為引用類型時,變量本身的值不可更改,即該變量不能指向其他的對象或數組;

        但該變量指向的對象或數組本身的內容是可以改變的

        如:

            final Person per = new Person(); //定義了一個Person類的對象引用per,並指向了new的對象

            //per = new Person(); //重新創建一個Person類對象,並讓per指向它,會出現與上面一樣的錯誤,即final修飾的引用類型變量不能重新賦值

            per.name = "me"; //per指向的對象本身的內容可以更改

 

為方便理解起見,請參考下面的內存圖:

 

2.final可以修飾成員方法

(1).final修飾的成員方法不能被子類重寫,即,當父類的方法為final時,子類不能與父類有方法名、參數類型、參數個數及參數順序都一樣的方法;父類方法為private時除外,詳見下面的(3);但子類可以調用父類的final方法。

見下面的代碼:

Person類的方法:
    final void finalMethod() {
        int i = 2;
        System.out.println("finalMethod: i = " + i);
    }

在TestMain中由Student類的對象引用調用:
public class TestMain {
    public static void main(String[] args) {
        Student stu = new Student();
        
        stu.finalMethod();
}

輸出結果為:finalMethod: i = 2

(2).訪問權限為private的方法默認為final的,但子類不可以調用private的方法,關於訪問權限修飾符的問題,詳見筆記10

(3).當父類某方法為private final,子類的成員方法與父類的該成員方法重名但僅由final修飾時,這時算不算重寫呢?

Person類的方法:
    private final void priFinalMethod() {
        System.out.println("Person:priFinalMethod");
    }

Student類的方法:
    final void priFinalMethod() {
        System.out.println("Student:priFinalMethod");
    }

TestMain類:
package human;

public class TestMain {
    public static void main(String[] args) {
        Person per = new Person();
        Student stu = new Student();
        Person per1 = stu;
        
//        per.priFinalMethod();
        stu.priFinalMethod();
//        per1.priFinalMethod();
}

Person類的main方法:
    public static void main(String[] args) {
        Person per = new Person();
        Student stu = new Student();
        Person per1 = stu;
        
        per.priFinalMethod();
        stu.priFinalMethod();
        per1.priFinalMethod();
}

TestMain類的輸出是:

Student:priFinalMethod

    1).其中,TestMain類中注釋掉的兩行都提示該方法不可見;

    2).對於per來說,private的方法僅本類可見,在TestMain類中是不可見的,所以per是不能調用priFinalMethod方法的;

    3).對於per1來說,per1是指向Student對象的引用,per1只能調用Student中重寫過的方法及Person類中的方法,由於這里仍然提示該方法不可見,結合2)可知,priFinalMethod方法是沒被子類重寫的,否則就可以調用了;

 

Person類的輸出是:

Person:priFinalMethod
Student:priFinalMethod
Person:priFinalMethod

前兩行好理解,最后一行,per1調用的是Person類中的priFinalMethod,進一步說明該方法未被子類重寫;

否則,會優先調用子類的priFinalMethod方法的。

 

3.final可以修飾成員方法的參數

由final修飾的成員方法的參數也是不能更改的,其實參數就是變量,具體參見1即可。

這里還涉及到形參與實參的概念,具體大家自己了解吧。

 

4.final可以修飾類

由final修飾的類不能被子類繼承,其成員方法也默認為final的,但成員變量是可以改變的,見下面代碼:

package human;

public final class FinalClass {

    int i = 1;
    
    void test() {
        System.out.println("FinalClass:test");
    }
    
    public static void main( String[] args ) {
        FinalClass ficl = new FinalClass();
        
        System.out.println("ficl.i = " + ficl.i);
        ficl.i = 2;
        System.out.println("ficl.i = " + ficl.i);
    }
}

輸出結果為:

ficl.i = 1
ficl.i = 2

可見可以修改i的值。

 

附測試源碼:

Person類:

package human;

public class Person {
//class Person{
    String name;
    int age;
    String gender;
    
    //筆記18:final修飾成員變量,及成員變量為類引用時的情況
    final int height = 160;
//    final int height;
    final EduBackground edu = new EduBackground();
    
    public Person() {
//  final height = 160;
    }
    
//筆記18:final修飾局部變量、修飾成員方法、修飾方法的參數
    //修飾局部變量時,局部變量的值不能改變
    void finalLocal() {
//        final int i = 1;
        final int i;
        
//        i = 3;
        final EduBackground edu = new EduBackground();
//        edu = new EduBackground();
        i = 1;
        System.out.println("finalLocal: i = " + i);
    }
    
    //修飾方法的參數時,參數不能被修改
    void finalArgs(final int i) {
//        i = 3;
        System.out.println("finalArgs: i = " + i);
    }
    void finalArgs(final EduBackground edu) {
//        edu = new EduBackground();
        System.out.println("finalArgs: edu");
    }
    
    //修飾成員方法時,成員方法不能被子類重寫
    final void finalMethod() {
        int i = 2;
        System.out.println("finalMethod: i = " + i);
    }
    private final void priFinalMethod() {
        System.out.println("Person:priFinalMethod");
    }

    public static void main(String[] args) {
        Person per = new Person();
        Student stu = new Student();
        Person per1 = stu;
        
        per.priFinalMethod();
        stu.priFinalMethod();
        per1.priFinalMethod();
    }
}

 

Student類:

package human;

public class Student extends Person {
    String stuNumber;
    int score;
    
    public Student() {
        
    }
        
//筆記18:子類不能重寫父類被final修飾的方法
//    final void finalMethod() {
//        int i = 2;
//        System.out.println("finalMethod: i = " + i);
//    }
    final void priFinalMethod() {
        System.out.println("Student:priFinalMethod");
    }

}

EduBackground類:
package human;

//public class EduBackground extends FinalClass {
public class EduBackground {

    String primarySchool;
    String secondarySchool;
    String juniorHSchool;
    String seniorHSchool;
    String university;
    
    public EduBackground() {
        
    }
}

 


免責聲明!

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



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