国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Java final關鍵字

2019-11-15 00:59:35
字體:
來源:轉載
供稿:網友
java 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變量,如果是基本數據類型的變量,則其數值一旦在初始化之后便不能更改;如果是引用類型的變量,則在對其初始化之后便不能再讓其指向另一個對象。

 

二、深入理解final關鍵字

在了解了final關鍵字的基本用法之后,這一節我們來看一下final關鍵字容易混淆的地方。

1、類的final變量和普通變量有什么區別?

  當用final作用于類的成員變量時,成員變量(注意是類的成員變量,局部變量只需要保證在使用之前被初始化賦值即可)必須在定義時或者構造器中進行初始化賦值,而且final變量一旦被初始化賦值之后,就不能再被賦值了。

  那么final變量和普通變量到底有何區別呢?下面請看一個例子:

public class Test {    public static void main(String[] args)  {        String a = "hello2";        String b = "hello2";        String c = new ("hello2");        String d = new ("hello2");        System.out.println((a == b));        System.out.println((c == d));    }}

true輸出結果是:

false

如果這塊能理解再下面的就容易理解了。

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變量?

 

5、關于final參數的問題

      關于網上流傳的“當你在方法中不需要改變作為參數的對象變量時,明確使用final進行聲明,會防止你無意的修改而影響到調用方法外的變量”這句話,我個人理解這樣說是不恰當的。

      因為無論參數是基本數據類型的變量還是引用類型的變量,使用final聲明都不會達到上面所說的效果。

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

      上面這段代碼好像讓人覺得用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采用的是值傳遞,對于引用變量,傳遞的是引用的值,也就是說讓實參和形參同時指向了同一個對象,因此讓形參重新指向另一個對象對實參并沒有任何影響。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 江川县| 荔浦县| 庆安县| 上思县| 哈尔滨市| 罗山县| 明光市| 肃南| 策勒县| 陇西县| 临安市| 绥江县| 韩城市| 莎车县| 遵义市| 湘乡市| 凌云县| 徐闻县| 正阳县| 浏阳市| 新丰县| 南靖县| 靖宇县| 西安市| 云梦县| 长春市| 青岛市| 两当县| 微博| 鞍山市| 湘潭县| 岱山县| 邵武市| 赣州市| 宁明县| 宁化县| 当雄县| 英吉沙县| 柳江县| 志丹县| 施秉县|