天天看點

有關Java中關鍵字final的了解

一、final資料

在java程式設計語言中,有時候需要告知編譯器一段資料是不變的編譯期常量。對于這種情況,編譯器可以将此常量值帶入需要用到它的計算式子當中,這種在編譯時執行計算式的方法減輕了運作時的開銷。通常,這類常量資料都是基本類型的資料,并賦予關鍵字final,同時在對此常量定義時需要進行指派。

值得注意的是:對于基本類型,使用final關鍵字将使數值恒定不變;而對于對象引用,final則是使引用恒定不變。一旦引用被初始化為指向一個對象時,它也就無法再指向另外一個對象,然而該對象本身是可以被修改的。通常,對于一個既是static又是final的域隻占一段不能改變的存儲空間。

下面的例子驗證了final資料的含義。

class Hank

{

       int i;

       public Hank(int i){this.i=i;}

}

public class FinalTest

{

       private String s;

       public FinalTest(String s){this.s=s;}

       private final int value=20;

       private static final int INT_1=50;

       public static final int  INT_2=60;

       static final int INT_3=70;

       private final Hank h1=new Hank(1);

       private static final Hank h2=new Hank(2);

       private Hank h3=new Hank(3);

       private final int[] a={1,2,3,4,5};

       public String toString()

       {

              return s+": "+"INT_2= "+INT_2;

       }

       public static void main(String[] args)

       {

              FinalTest ft1=new FinalTest("ft1");

              //ft1.value++;常量值不能被修改

              ft1.h1.i++;//對象引用不能改變,但是其對象本身是可以修改的

              ft1.h3=new Hank(2);

              //ft1.h1=new Hank(1);常量對象引用不能再指向另一個對象引用

              for(int i=0;i<ft1.a.length;i++)

              {

                     ft1.a[i]++; //對象引用不能改變,但是其對象本身是可以修改的

                     System.out.println(ft1.a[i]);

              }

              //ft1.a=new int[3]; 常量對象引用不能再指向另一個對象引用

       }

}

二、空白final

    被聲明為final但又沒有給定初值的域即為空白final,編譯器確定使用前必須初始化空白final。比如:

class Blank

{

    private int i;

    Blank(int i){this.i=i;System.out.println("Blank.i="+this.i);}

}

public class BlankFinal

{

    private final int i;//blank final

    private final Blank b;//blank final reference

    BlankFinal()

{

i=1;b=new Blank(1);//使用前必須初始化

System.out.println("BlankFinal.i="+this.i);

}

    BlankFinal(int i)

{

this.i=i;b=new Blank(i); //使用前必須初始化

System.out.println("BlankFinal.i="+this.i);

}

    public static void main(String[] args)

    {

           new BlankFinal();//Blank.i=1;BlankFinal.i=1;

           new BlankFinal(2); //Blank.i=2;BlankFinal.i=2;

    }     

三、final參數

       Java允許在函數參數清單中以聲明的方式将參數指明為final,這使得在函數體當中修改參數引用所指向的對象變得不合法。比如說:

class Args

{

       public void f(String s){System.out.println(s);}

}

public class ArgsFinal

{

       void has(final Args arg)

       {

              //arg=new Args();不能修改final參數

              arg.f("with final");

       }

       void dnthas(Args arg)

       {

              arg=new Args();//能修改final參數

              arg.f("without final");

       }

       public static void main(String[] args)

       {

              ArgsFinal af=new ArgsFinal();

              Args ar=new Args();

              af.has(ar);//with final

              af.dnthas(ar);//without final

       }

}

四、final類

       如果不想繼承某個類,則可以考慮将此類設定成final的形式。即是說,程式員對該類不能做任何改動,同時也意味着它不會有子類。比如:

       Class Base{ …}

       Final Class SubClass{…}

       //! Class Derived extends SubClass{…}不能由final類SubClass導出新類

需要注意的是,所有final類中的方法都隐式的final,他們是無法被覆寫或修改的,是以在其中的方法顯示指明為final就顯得有些多此一舉了。

Reference:

       Bruce Eckel.<<Thinking in Java>>.Fourth Edition