程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 深刻淺析Java中的final症結字

深刻淺析Java中的final症結字

編輯:關於JAVA

深刻淺析Java中的final症結字。本站提示廣大學習愛好者:(深刻淺析Java中的final症結字)文章只能為提供參考,不一定能成為您想要的結果。以下是深刻淺析Java中的final症結字正文


談到final症結字,想必許多人都不生疏,在應用匿名外部類的時刻能夠會常常用到final症結字。別的,Java中的String類就是一個final類,那末明天我們就來懂得final這個症結字的用法。上面是本文的目次年夜綱:

  一.final症結字的根本用法

  二.深刻懂得final症結字

  如有不正的地方,請多多原諒並迎接斧正。

final 關於常量來講,意味著值不克不及轉變,例如 final int i=100。這個i的值永久都是100。然則關於變量來講又紛歧樣,只是標識這個援用弗成被轉變,例如 final File f=new File("c:\\test.txt");那末這個f必定是不克不及被轉變的,假如f自己無方法修正個中的成員變量,例如能否可讀,是許可修正的。抽象的比方:一個男子界說了一個final的老公,這個老公的職業和支出都是許可轉變的,只是這個女人不會換老公罷了。

一.final症結字的根本用法

  在Java中,final症結字可以用來潤飾類、辦法和變量(包含成員變量和部分變量)。上面就從這三個方面來懂得一下final症結字的根本用法。

  1.潤飾類

   當用final潤飾一個類時,注解這個類不克不及被繼續。也就是說,假如一個類你永久不會讓他被繼續,便可以用final停止潤飾。final類中的成員變量可以依據須要設為final,然則要留意final類中的一切成員辦法都邑被隱式地指定為final辦法。

  在應用final潤飾類的時刻,要留意謹嚴選擇,除非這個類真的在今後不會用來繼續或許出於平安的斟酌,盡可能不要將類設計為final類。

  2.潤飾辦法

  上面這段話摘自《Java編程思惟》第四版第143頁:

  “應用final辦法的緣由有兩個。第一個緣由是把辦法鎖定,以防任何繼續類修正它的寄義;第二個緣由是效力。在晚期的Java完成版本中,會將final辦法轉為內嵌挪用。然則假如辦法過於宏大,能夠看不到內嵌挪用帶來的任何機能晉升。在比來的Java版本中,不須要應用final辦法停止這些優化了。“

  是以,假如只要在想明白制止 該辦法在子類中被籠罩的情形下才將辦法設置為final的。

  注:類的private辦法會隱式地被指定為final辦法。

  3.潤飾變量

  潤飾變量是final用得最多的處所,也是本文接上去要重點論述的內容。起首懂得一下final變量的根本語法:

  關於一個final變量,假如是根本數據類型的變量,則其數值一旦在初始化以後便不克不及更改;假如是援用類型的變量,則在對其初始化以後便不克不及再讓其指向另外一個對象。

  舉個例子:

  下面的一段代碼中,對變量i和obj的從新賦值都報錯了。

二.深刻懂得final症結字

  在懂得了final症結字的根本用法以後,這一節我們來看一下final症結字輕易混雜的處所。

1.類的final變量和通俗變量有甚麼差別?

  當用final感化於類的成員變量時,成員變量(留意是類的成員變量,部分變量只須要包管在應用之前被初始化賦值便可)必需在界說時或許結構器中停止初始化賦值,並且final變量一旦被初始化賦值以後,就不克不及再被賦值了。

  那末final變量和通俗變量究竟有何差別呢?上面請看一個例子:

public class Test {
  public static void main(String[] args) {
    String a = "hello2"; 
    final String b = "hello";
    String d = "hello";
    String c = b + 2; 
    String e = d + 2;
    System.out.println((a == c));
    System.out.println((a == e));
  }
} 
true
false 

  年夜家可以先想一下這道題的輸入成果。為何第一個比擬成果為true,而第二個比擬成果為fasle。這外面就是final變量和通俗變量的差別了,當final變量是根本數據類型和String類型時,假如在編譯時代能曉得它切實其實切值,則編譯器會把它當作編譯期常量應用。也就是說在用到該final變量的處所,相當於直接拜訪的這個常量,不須要在運轉時肯定。這類和C說話中的宏調換有點像。是以在下面的一段代碼中,因為變量b被final潤飾,是以會被當作編譯器常量,所以在應用到b的處所會直接將變量b 調換為它的  值。而關於變量d的拜訪卻須要在運轉時經由過程鏈接來停止。想必個中的差別年夜家應當明確了,不外要留意,只要在編譯時代能確實曉得final變量值的情形下,編譯器才會停止如許的優化,好比上面的這段代碼就不會停止優化:

public class Test {
  public static void main(String[] args) {
    String a = "hello2"; 
    final String b = getHello();
    String c = b + 2; 
    System.out.println((a == c));
  }
  public static String getHello() {
    return "hello";
  }
} 

  這段代碼的輸入成果為false。

2.被final潤飾的援用變量指向的對象內容可變嗎?

  在下面提到被final潤飾的援用變量一旦初始化賦值以後就不克不及再指向其他的對象,那末該援用變量指向的對象的內容可變嗎?看上面這個例子:

public class Test {
  public static void main(String[] args) {
    final MyClass myClass = new MyClass();
    System.out.println(++myClass.i);
  }
}
class MyClass {
  public int i = 0;
} 

  這段代碼可以順遂編譯經由過程而且有輸入成果,輸入成果為1。這解釋援用變量被final潤飾以後,固然不克不及再指向其他對象,然則它指向的對象的內容是可變的。

3.final和static

  許多時刻會輕易把static和final症結字混雜,static感化於成員變量用來表現只保留一份正本,而final的感化是用來包管變量弗成變。看上面這個例子:

public class Test {
  public static void main(String[] args) {
    MyClass myClass1 = new MyClass();
    MyClass myClass2 = new MyClass();
    System.out.println(myClass1.i);
    System.out.println(myClass1.j);
    System.out.println(myClass2.i);
    System.out.println(myClass2.j);
  }
}
class MyClass {
  public final double i = Math.random();
  public static double j = Math.random();
} 

  運轉這段代碼就會發明,每次打印的兩個j值都是一樣的,而i的值倒是分歧的。從這裡便可以曉得final和static變量的差別了。

4.匿名外部類中應用的內部部分變量為何只能是final變量?

  這個成績請拜見上一篇博文中《Java外部類詳解》中的說明,在此處不再贅述。

5.關於final參數的成績

  關於網下流傳的”當你在辦法中不須要轉變作為參數的對象變量時,明白應用final停止聲明,會避免你有意的修正而影響到挪用辦法外的變量“這句話,我小我懂得如許說是不適當的。

  由於不管參數是根本數據類型的變量照樣援用類型的變量,應用final聲明都不會到達下面所說的後果。

  看這個例子就清晰了:

 

  下面這段代碼似乎讓人認為用final潤飾以後,就不克不及在辦法中更轉變量i的值了。卻不知,辦法changeValue和main辦法中的變量i基本就不是一個變量,由於java參數傳遞采取的是值傳遞,關於根本類型的變量,相當於直接將變量停止了拷貝。所以即便沒有final潤飾的情形下,在辦法外部轉變了變量i的值也不會影響辦法外的i。

  再看上面這段代碼:

public class Test {
  public static void main(String[] args) {
    MyClass myClass = new MyClass();
    StringBuffer buffer = new StringBuffer("hello");
    myClass.changeValue(buffer);
    System.out.println(buffer.toString());
  }
}
class MyClass {
  void changeValue(final StringBuffer buffer) {
    buffer.append("world");
  }
} 

  運轉這段代碼就會發明輸入成果為 helloworld。很明顯,用final停止潤飾並沒有阻攔在changeValue中轉變buffer指向的對象的內容。有人說假設把final去失落了,萬一在changeValue中讓buffer指向了其他對象怎樣辦。有這類設法主意的同伙可以本身著手寫代碼試一下如許的成果是甚麼,假如把final去失落了,然後在changeValue中讓buffer指向了其他對象,也不會影響到main辦法中的buffer,緣由在於java采取的是值傳遞,關於援用變量,傳遞的是援用的值,也就是說讓實參和形參同時指向了統一個對象,是以讓形參從新指向另外一個對象對實參並沒有任何影響。

以上所述是小編給年夜家分享的Java中的final症結字詳解,願望年夜家愛好。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved