鍍金池/ 教程/ Java/ 關(guān)鍵字 final
Java 集合細(xì)節(jié)(四):保持 compareTo 和 equals 同步
Iterator
使用序列化實(shí)現(xiàn)對象的拷貝
fail-fast 機(jī)制
關(guān)鍵字 final
Vector
HashTable
Java 集合細(xì)節(jié)(一):請為集合指定初始容量
強(qiáng)制類型轉(zhuǎn)換
數(shù)組之一:認(rèn)識 JAVA 數(shù)組
Java 集合細(xì)節(jié)(三):subList 的缺陷
hashCode
ArrayList
數(shù)組之二
List 總結(jié)
LinkedList
Java 提高篇(九)—–實(shí)現(xiàn)多重繼承
Java 的四舍五入
關(guān)鍵字 static
理解 Java 的三大特性之多態(tài)
抽象類與接口
集合大家族
異常(二)
Java 集合細(xì)節(jié)(二):asList 的缺陷
Map 總結(jié)
TreeSet
equals() 方法總結(jié)
Java 提高篇(十)—–詳解匿名內(nèi)部類
HashMap
Stack
詳解內(nèi)部類
TreeMap
異常(一)
詳解 Java 定時任務(wù)
HashSet
字符串
理解 Java 的三大特性之繼承
理解 Java 的三大特性之封裝
代碼塊

關(guān)鍵字 final

在程序設(shè)計中,我們有時可能希望某些數(shù)據(jù)是不能夠改變的,這個時候 final 就有用武之地了。final 是 Java 的關(guān)鍵字,它所表示的是“這部分是無法修改的”。不想被改變的原因有兩個:效率、設(shè)計。使用到 final 的有三種情況:數(shù)據(jù)、方法、類。

一、final 數(shù)據(jù)

有時候數(shù)據(jù)的恒定不變是很有用的,它能夠減輕系統(tǒng)運(yùn)行時的負(fù)擔(dān)。對于這些恒定不變的數(shù)據(jù)我可以叫做“常量”。“常量”主要應(yīng)用與以下兩個地方:

1、編譯期常量,永遠(yuǎn)不可改變。

2、運(yùn)行期初始化時,我們希望它不會被改變。

對于編譯期常量,它在類加載的過程就已經(jīng)完成了初始化,所以當(dāng)類加載完成后是不可更改的,編譯期可以將它代入到任何用到它的計算式中,也就是說可以在編譯期執(zhí)行計算式。當(dāng)然對于編譯期常量,只能使用基本類型,而且必須要在定義時進(jìn)行初始化。

有些變量,我們希望它可以根據(jù)對象的不同而表現(xiàn)不同,但同時又不希望它被改變,這個時候我們就可以使用運(yùn)行期常量。對于運(yùn)行期常量,它既可是基本數(shù)據(jù)類型,也可是引用數(shù)據(jù)類型?;緮?shù)據(jù)類型不可變的是其內(nèi)容,而引用數(shù)據(jù)類型不可變的是其引用,引用所指定的對象內(nèi)容是可變的。


    public class Person {
        private String name;

        Person(String name){
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public class FinalTest {
        private final String final_01 = "chenssy";    //編 譯期常量,必須要進(jìn)行初始化,且不可更改
        private final String final_02;                //構(gòu)造器常量,在實(shí)例化一個對象時被初始化

        private static Random random = new Random();
        private final int final_03 = random.nextInt(50);    //使用隨機(jī)數(shù)來進(jìn)行初始化

        //引用
        public final Person final_04 = new Person("chen_ssy");    //final指向引用數(shù)據(jù)類型

        FinalTest(String final_02){
            this.final_02 = final_02;
        }

        public String toString(){
            return "final_01 = " + final_01 +"   final_02  = " + final_02 + "   final_03 = " + final_03 +
                   "   final_04 = " + final_04.getName();
        }

        public static void main(String[] args) {
            System.out.println("------------第一次創(chuàng)建對象------------");
            FinalTest final1 = new FinalTest("cm");
            System.out.println(final1);
            System.out.println("------------第二次創(chuàng)建對 象------------");
            FinalTest final2 = new FinalTest("zj");
            System.out.println(final2);
            System.out.println("------------修改引用對 象--------------");
            final2.final_04.setName("chenssy");
            System.out.println(final2);
        }
    }

    ------------------
    Output:
    ------------第一次創(chuàng)建對象------------
    final_01 = chenssy   final_02 = cm   final_03 = 34    final_04 = chen_ssy
    ------------第二次創(chuàng)建對象------------
    final_01 = chenssy   final_02 = zj   final_03 = 46   final_04 = chen_ssy
    ------------修改引用對象--------------
    final_01 = chenssy   final_02 = zj   final_03 = 46   final_04 = chenssy

這里只闡述一點(diǎn)就是:不要以為某些數(shù)據(jù)是 final 就可以在編譯期知道其值,通過 final_03 我們就知道了,在這里是使用隨機(jī)數(shù)其進(jìn)行初始化,他要在運(yùn)行期才能知道其值。

二、final 方法

所有被 final 標(biāo)注的方法都是不能被繼承、更改的,所以對于 final 方法使用的第一個原因就是方法鎖定,以防止任何子類來對它的修改。至于第二個原因就是效率問題,鄙人對這個效率問題理解的不是很清楚,在網(wǎng)上摘抄這段話:

在 Java 的早期實(shí)現(xiàn)中,如果將一個方法指明為 final,就是同意編譯器將針對該方法的所有調(diào)用都轉(zhuǎn)為內(nèi)嵌調(diào)用。當(dāng)編譯器發(fā)現(xiàn)一個 final 方法調(diào)用命令時,它會根據(jù)自己的謹(jǐn)慎判斷,跳過插入程序代碼這種正常的調(diào)用方式而執(zhí)行方法調(diào)用機(jī)制(將參數(shù)壓入棧,跳至方法代碼處執(zhí)行,然后跳回并清理棧中的參數(shù),處理返回值),并且以方法體中的實(shí)際代碼的副本來代替方法調(diào)用。這將消除方法調(diào)用的開銷。當(dāng)然,如果一個方法很大,你的程序代碼會膨脹,因而可能看不到內(nèi)嵌所帶來的性能上的提高,因?yàn)樗鶐淼男阅軙ㄙM(fèi)于方法內(nèi)的時間量而被縮減。

對這段話理解我不是很懂就照搬了,那位 Java 牛人可以解釋解釋下??!

父類的 final 方法是不能被子類所覆蓋的,也就是說子類是不能夠存在和父類一模一樣的方法的。


    public class Custom extends Person{
        public void method1(){
            System.out.println("Person's  method1....");
        }

    //    Cannot override the final method from person:子類不能覆蓋父類的final方法
    //    public void method2(){
    //        System.out.println("Person's method2...");
    //    }
    }

三、final 類

如果某個類用 final 修改,表明該類是最終類,它不希望也不允許其他來繼承它。在程序設(shè)計中處于安全或者其他原因,我們不允許該類存在任何變化,也不希望它有子類,這個時候就可以使用 final 來修飾該類了。

對于 final 修飾的類來說,它的成員變量可以為 final,也可以為非 final。如果定義為 final,那么 final 數(shù)據(jù)的規(guī)則同樣適合它。而它的方法則會自動的加上 final,因?yàn)?final 類是無法被繼承,所以這個是默認(rèn)的。

四、final 參數(shù)

在實(shí)際應(yīng)用中,我們除了可以用 final 修飾成員變量、成員方法、類,還可以修飾參數(shù)、若某個參數(shù)被 final 修飾了,則代表了該參數(shù)是不可改變的。

如果在方法中我們修改了該參數(shù),則編譯器會提示你:The final local variable i cannot be assigned. It must be blank and not using a compound assignment。


    public class Custom {
        public void test(final int i){
            //i++;     ---final參數(shù)不可改變
            System.out.println(i);
        }

        public void test(final Person p){
         //p = new Person();    --final參數(shù)不可變
         p.setName("chenssy");
        }
    }

同 final 修飾參數(shù)在內(nèi)部類中是非常有用的,在匿名內(nèi)部類中,為了保持參數(shù)的一致性,若所在的方法的形參需要被內(nèi)部類里面使用時,該形參必須為 final。詳情參看:http://www.cnblogs.com/chenssy/p/3390871.html 。

六、final 與 static

final 和 static 在一起使用就會發(fā)生神奇的化學(xué)反應(yīng),他們同時使用時即可修飾成員變量,也可修飾成員方法。

對于成員變量,該變量一旦賦值就不能改變,我們稱它為“全局常量”??梢酝ㄟ^類名直接訪問。

對于成員方法,則是不可繼承和改變??梢酝ㄟ^類名直接訪問。

更多:

Java 提高篇——關(guān)鍵字static:http://www.cnblogs.com/chenssy/p/3386721.html

鞏固基礎(chǔ),提高技術(shù),不懼困難,攀登高峰?。。。。?!