亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Java-面向?qū)ο?final修飾符、不可變類

Original 2016-11-19 10:23:37 651
abstract:final關(guān)鍵字可以用于何處修飾類:該類不可被繼承修飾變量:該變量一經(jīng)初始化就不能被重新賦值,即使該值跟初始化的值相同或者指向同一個對象,也不可以類變量:實例變量:形參: 注意可以修飾形參局部變量修飾方法:該方法不可被重寫final修飾成員變量final修飾成員變量,必須顯式的指定初始值,系統(tǒng)不會為final成員進行隱式初始化,不能在初始化前訪問。因為,不管是類變量還是實例變量,都有個初始化的過程

final關(guān)鍵字可以用于何處

修飾類:該類不可被繼承

修飾變量:該變量一經(jīng)初始化就不能被重新賦值,即使該值跟初始化的值相同或者指向同一個對象,也不可以

類變量:

實例變量:

形參: 注意可以修飾形參

局部變量

修飾方法:該方法不可被重寫

final修飾成員變量

final修飾成員變量,必須顯式的指定初始值,系統(tǒng)不會為final成員進行隱式初始化,不能在初始化前訪問。

因為,不管是類變量還是實例變量,都有個初始化的過程,初始化賦值后便不能再賦值,如果不顯式的指定初始值,那么這些變量就沒有存在的意義

修飾類變量:

要么聲明時指定

要么在靜態(tài)塊中指定

二者互斥,只能是其一

修飾實例變量:

要么聲明時指定

要么非靜態(tài)塊中指定

要么構(gòu)造方法中指定

三者任意兩者互斥,只能是這三者之其一

final修飾局部變量

局部變量,不管有沒有final修飾,都是必須顯式初始化的

final修飾的形參,是不能賦值的

final修飾引用類型變量

final可以用來修飾一個引用類型變量,但只能保證這個變量始終指向同一地址

不能保證指向的對象本身發(fā)生改變

final與直接量

一個變量,不管是類變量、實例變量、局部變量,滿足下面三個條件,便是一個直接量

用final修飾

在定義該final變量時指定了初始值。注意是定義時,不能在代碼塊中或者構(gòu)造方法中

該初始值可以在編譯時就被確定下來

對于直接量,在編譯的時候,會用直接量把變量名替換掉,編譯后的文件中是不存在這個變量的

Java用常量池來管理使用過的字符串直接量

final修飾方法

final修飾的方法不能被重寫,比如作為根父類的Object就有一個.getClass()方法是用final修飾的

如果父類有一個private final修飾的方法,子類也有這個方法,private final修飾,方法簽名也相同,注意這不是重寫,這是兩個無關(guān)的方法,

final修飾類

final修飾的類不能被繼承,比如:

public final class Math extends Object {...}

不可變(immutable)類

不可變類:創(chuàng)建實例后,實例變量不可變,即實例的狀態(tài)不能發(fā)生改變

8個包裝類和String都是不可變類

如何定義一個不可變類:

用private和final修飾成員變量

提供帶參數(shù)的構(gòu)造器,用來初始化成員變量

只提供成員變量的get方法,不提供set方法

有必要的話重寫equals()和hashCode()方法

如果成員變量是引用類型

傳遞進來的引用類型對象不要直接用,而要根據(jù)其實例變量重新創(chuàng)建一個

外部訪問時,根據(jù)這個對象的實例變量的值,重新創(chuàng)建一個對象返回

這種情況要特別注意,上面的寫法只能用于基本類型

對引用類型不可變的寫法,基本原則就是隔絕外部對它的訪問,主要要做好兩點:

看下面的示例代碼:

示例一:該不可變類對引用類型變量無效

public class Test{  
    public static void main(String[] args) { 
        Name n=new Name("師兄","大");
        System.out.println(n);            //Name@15db9742
        Person p=new Person(n,100);
        System.out.println(p);            //輸出:[大師兄100歲]
        System.out.println(p.getName());  //Name@15db9742
        n.setFirstName("師兄");
        n.setLastName("二");
        System.out.println(p);            //輸出:[二師兄100歲],不可變對象還是變了,再看下面一段代碼
        System.out.println(p.getName());  //Name@15db9742
    }
}class Person{    private final Name name;    private final int age;    public Person(Name name,int age){        this.name=name;        this.age=age;
    }    public Name getName(){        return name;
    }    public String toString(){        return "["+name.getLastName()+name.getFirstName()+age+"歲]";
    }
}class Name{    private String firstName;    private String lastName;    public Name(){}    public Name(String first,String last){
        firstName=first;
        lastName=last;
    }    public String getFirstName(){        return firstName;
    }    public void setFirstName(String firstName){        this.firstName=firstName;
    }    public String getLastName(){        return lastName;
    }    public void setLastName(String lastName){        this.lastName=lastName;
    }
}

示例代碼二:改寫了兩行

public class Test{  
    public static void main(String[] args) { 
        Name n=new Name("師兄","大");
        System.out.println(n);            //Name@15db9742
        Person p=new Person(n,100);
        System.out.println(p);            //輸出:[大師兄100歲]
        System.out.println(p.getName());  //Name@6d06d69c
        n.setFirstName("師兄");
        n.setLastName("二");
        System.out.println(p);            //輸出:[大師兄100歲]。沒發(fā)生改變
        System.out.println(p.getName());  //Name@7852e922
    }
}class Person{    private final Name name;    private final int age;    public Person(Name name,int age){        this.name=new Name(name.getFirstName(),name.getLastName());  //此行改寫
        this.age=age;
    }    public Name getName(){        return new Name(name.getFirstName(),name.getLastName());     //此行改寫
    }    public String toString(){        return "["+name.getLastName()+name.getFirstName()+age+"歲]";
    }
}class Name{    private String firstName;    private String lastName;    public Name(){}    public Name(String first,String last){
        firstName=first;
        lastName=last;
    }    public String getFirstName(){        return firstName;
    }    public void setFirstName(String firstName){        this.firstName=firstName;
    }    public String getLastName(){        return lastName;
    }    public void setLastName(String lastName){        this.lastName=lastName;
    }
}

緩存實例的不可變類

如果一個不可變類的部分實例,需要被頻繁的訪問到,那么可以考慮把這部分實例緩存起來,以提高性能

Integer類就把[-128,127]的每個整數(shù)的Integer對象緩存了,見 0024 Java學習筆記-面向?qū)ο?包裝類、對象的比較、String常量池問題

示例:

public class T1{  
    public static void main(String[] args) { 
        CacheImmutable c1=CacheImmutable.valueOf("A");
        CacheImmutable c2=CacheImmutable.valueOf("A");
        System.out.println(c1==c2);                      //返回true
    }
}class CacheImmutable{    private static int MAX_SIZE = 10;                    //緩存的大小
    private static CacheImmutable[] cache=new CacheImmutable[MAX_SIZE]; //靜態(tài)變量
    private static int pos=0;                            //下一個要緩存的對象在cache中的索引號
    private final String name;                           //CacheImmutable就這一個實例變量,用private final修飾,name是String類型,也是不可變的
    private CacheImmutable(String name){                 //通過帶參數(shù)的構(gòu)造器初始化final的實例變量,但不允許外部通過它創(chuàng)建對象
        this.name=name;
    }    public String getName(){                             //提供了get方法,沒提供set方法,
        return name;
    }    public static CacheImmutable valueOf(String name){   //要獲得該類的對象,只能通過這個靜態(tài)方法
        for (int i=0;i<MAX_SIZE;i++){                    //先遍歷一遍,看緩存中是否已經(jīng)有了name對應的對象
            if (cache[i]!=null && cache[i].getName().equals(name)){  //?為何不直接訪問name,有何區(qū)別
                return cache[i];                         //如果已經(jīng)有了就將其返回,方法調(diào)用結(jié)束
            }
        }        if (pos==MAX_SIZE){
            cache[0]=new CacheImmutable(name);           //如果已經(jīng)緩存了10個(cache索引號9),那就從頭開始覆蓋
            pos=1;
        }else{
            cache[pos]=new CacheImmutable(name);          //如果還不到10個,那就創(chuàng)建個對象,放在pos位置
            pos++;
        }        return cache[pos-1];                              //返回新創(chuàng)建并緩存的對象,方法調(diào)用結(jié)束
    }    public boolean equals(Object obj){        if (this==obj) {            return true;
        }        if (obj!=null && obj.getClass()==CacheImmutable.class) {
            CacheImmutable ci=(CacheImmutable)obj;            return name.equals(ci.getName());
        }        return false;
    }    public int hashCode(){        return name.hashCode();
    }
}


Release Notes

Popular Entries