java中final的意義

來源:互聯網
上載者:User

final變數的定義本身並不複雜,就是變數一經初始化就不能再指向其它對象.在c++中它是一個const指標,而
不是指向const變數的指標,const指標的意思是說它只能一直指向初始化時的那個地址.但那個地址中對象本身
是可以修改的.而指向const變數的指標是說所指對象本身是不能修改的.

如:final StringBuffer sb = new StringBuffer("Axman");
sb = new StringBuffer("Sager");//錯誤,sb不能再指向其它對象.
sb.append(" was changed!"); //sb指向的地象本身可以修改.

先說final變數初始化:

很多文章都這麼說:其初始化可以在兩個地方,一是其定義處,二是在建構函式中,兩者只能選其一。
胡說八道!
final變數可以在任何可以被始化的地方被始化,但只能被初始化一次.一旦被初始化後就不能再次賦
值(重新指向其它對象),作為成員變數一定要顯式初始化,而作為臨時變數則可以只定義不初始化(當然也不能引用)
即使是作為一個類中的成員變數,也還可以在初始化塊中初始化,所以"其初始化可以在兩個地方,一是其定義處,
二是在建構函式中,兩者只能選其一"是錯誤的.

作為成員變數時,final欄位可以設計不變類,是不變類的一個必要條件但不是一個充要條件.至少可以保證欄位不
會以setXXX()這樣的方式來改變.但無法保證欄位本身不被修改(除非欄位本身也是不變類);

對於方法參數的final變數:
對於方法參數的變數定義為final,90%以上的文章都說"當你在方法中不需要改變作為參數的物件變數時,明確使
用final進行聲明,會防止你無意的修改而影響到調用方法外的變數。"
胡說八道!

我不知道這個修改是說重新賦值還是修改對象本身,但無論是哪種情況,上面的說法都是錯誤的.
如果是說重新賦值,那麼:
 public static void test(int[] x){
  x = new int[]{1,2,3};
 }

    int[] out = new int[]{4,5,6};
    test(out);
    System.out.println(out[0]);
    System.out.println(out[1]);
    System.out.println(out[2]);
    調用test(out);無論如何也不會影響到外面變數out.你加不加final根本沒有意義.final只會強迫方法內
多聲明一個變數名而已,即把x = new int[]{1,2,3};改成int y = new int[]{1,2,3}; 其它沒有任何實際意義.
    如果說是修改對象本身:
 public static void test(final int[] x){
  x[0] = 100;
 }
    int[] out = new int[]{4,5,6};
    test(out);
    System.out.println(out[0]);
難道你用final修飾就不可以修改了?所以說對於方法參數中final是為了不影響調用方法外的變數那是胡說八道的.

那我們到底為什麼要對參數加上final?其實對方法參數加final和方法內變數加上final的作用是相同的,即為了將它們
傳給內部類時保證調用的一致性:

abstract class ABSClass{
 public abstract void m();
}

現在我們來看,如果我要實現一個在一個方法中匿名調用ABSClass.應該:
 public static void test(final String s){
     //或final String s = "axman";
  ABSClass c = new ABSClass(){
   public void m(){
      int x = s.hashCode();

      System.out.println(x);

   }
  };
  //其它代碼.
 }
 實際上這段代碼被編譯成:
  public static void test(final String s){
     //或final String s = "axman";
  ABSClass c = new ABSClass(s){
   private final String s;
   public ABSClass(String s){
 this.s = s;   
   }
   public void m(){
      int x = s.hashCode();

      System.out.println(x);

   }
  };
  //其它代碼.
 }
即外部類的變數被作為構造方法的參數傳給了內部類的私人成員.
假如沒有final,那麼:
 public static void test(String s){
     //或String s = "axman";
  ABSClass c = new ABSClass(){
   public void m(){
     s = "other";
   }
  };
  System.out.println(s);
 }
 就會編譯成:
  public static void test(String s){
     //或String s = "axman";
  ABSClass c = new ABSClass(s){
   private final String s;
   public ABSClass(String s){
 this.s = s;   
   }
   public void m(){
  s = "other";
   }
  };
  System.out.println(s);
 }
 內部類的s重新指向"other"並不影響test的參數或外部定義的那個s.而你看到的
  public static void test(String s){
     //或String s = "axman";
  ABSClass c = new ABSClass(){
   public void m(){
     s = "other";
   }
  };
  System.out.println(s);
 }
 在文法上是一個s,在內部類中被改變了,但結果列印的出來的你認為是同一的s卻還是原來的"axman",
 你能接收這樣的結果嗎?
 所以final從文法上約束了兩個不同變數的一致性

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.