成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Final關鍵字的這8個小細節,你get到幾個?

開發 前端
今天來聊 final 關鍵字,因為最近在看的幾本書都講到了 final 關鍵字,發現好多小細節自己都忽視了,抽空總結了一下,分享給大家。

[[378333]]

 前言

大家好,我是狂聊君。

今天來聊 final 關鍵字,因為最近在看的幾本書都講到了 final 關鍵字,發現好多小細節自己都忽視了,抽空總結了一下,分享給大家。

正文

final關鍵字是一個常用的關鍵字,可以修飾變量、方法、類,用來表示它修飾的類、方法和變量不可改變,下面就聊一下使用 final 關鍵字的一些小細節。

細節一、final 修飾類成員變量和實例成員變量的賦值時機

對于類變量:

  1. 聲明變量的時候直接賦初始值
  2. 在靜態代碼塊中給類變量賦初始值

如下代碼所示:

  1. public class FinalTest { 
  2.     //a變量直接賦值 
  3.     private final static  int a = 1; 
  4.  
  5.     private final static  int b; 
  6.     //b變量通過靜態代碼塊賦值 
  7.     static { 
  8.         b=2; 
  9.     } 

對于實例變量:

  1. 在聲明變量的時候直接賦值
  2. 在非靜態代碼塊中賦值
  3. 在構造器中賦初始化值

如下代碼所示:

  1. public class FinalTest { 
  2.     //c變量在在聲明時直接賦值 
  3.     private final  int c =1; 
  4.     private final  int d; 
  5.     private final  int e; 
  6.     //d變量在非靜態代碼塊中賦值 
  7.     { 
  8.         d=2; 
  9.     } 
  10.     //e變量在構造器中賦值 
  11.     FinalTest(){ 
  12.         e=3; 
  13.     } 

細節二、當 final 修飾的成員變量未對它進行初始化時,會出現錯誤嗎?

答:會出現錯誤。因為 java 語法規定,final 修飾的成員變量必須由程序員顯示的初始化,系統不會對變量進行隱式的初始化。

如下圖所示,未初始化變量就會出現編譯錯誤:


細節三、final 修飾基本類型變量和引用類型變量的區別

如果 fianl 修飾的是一個基本數據類型的數據,一旦賦值后就不能再次更改。

那么 final 修飾的是引用數據類型呢?這個引用的變量能夠改變嗎?

看下面的代碼:

  1. public class FinalTest { 
  2.     //在聲明final實例成員變量時進行賦值 
  3.     private final static Student student = new Student(50, "Java"); 
  4.  
  5.     public static void main(String[] args) { 
  6.         //對final引用數據類型student進行更改 
  7.         student.age = 100; 
  8.         System.out.println(student.toString()); 
  9.     } 
  10.  
  11.     static class Student { 
  12.         private int age; 
  13.         private String name
  14.  
  15.         public Student(int age, String name) { 
  16.             this.age = age; 
  17.             this.name = name
  18.         } 
  19.  
  20.         @Override 
  21.         public String toString() { 
  22.             return "Student{" + 
  23.                     "age=" + age + 
  24.                     ", name='" + name + '\'' + 
  25.                     '}'
  26.         } 
  27.     } 
  28.  
  29. //下面是打印結果 
  30. Student{age=100, name='Java'

從打印結果可以看到:引用數據類型變量 student 的 age 屬性修改成 100,是可以修改成功的。

結論:

  1. 當 final 修飾基本數據類型變量時,不能對基本數據類型變量重新賦值,因此基本數據類型變量不能被改變。
  2. 對于引用類型變量而言,它僅僅保存的是一個引用,final 只保證這個引用類型變量所引用的地址不會發生改變,即一直引用這個對象,但這個對象里面的屬性是可以改變的。

細節四、final 修飾局部變量的場景

fianl 局部變量由程序員進行顯示的初始化,如果 final 局部變量進行初始化之后就不能再次進行更改。

如果 final 變量未進行初始化,可以進行賦值,并且只能進行一次賦值,一旦賦值之后再次賦值就會出錯。

下面的代碼演示 final 修飾局部變量的情況:


細節五、final 修飾方法會對重載有影響嗎?重寫呢?

對于重載:final 修飾方法后是可以重載的

如下代碼:

  1. public class FinalTest { 
  2.     public final void test(){ 
  3.  
  4.     } 
  5.     //重載方法不會出現問題 
  6.     public final void test(String test){ 
  7.  
  8.     } 

對于重寫:當父類的方法被 final 修飾的時候,子類不能重寫父類的該方法


如上代碼所示,可以看到會出現 cannot override ,overridden method is final 的編譯錯誤提示

細節六、final 修飾類的場景

當用final修飾一個類時,表明這個類不能被繼承。也就是說,如果一個類你永遠不會讓他被繼承,就可以用 final 進行修飾。

final 類中的成員變量可以根據需要設為 final,但是要注意 final 類中的所有成員方法都會被隱式地指定為 final 方法。

細節七、寫 final 域的重排序規則,你知道嗎?

這個規則是指禁止對 final 域的寫重排序到構造函數之外,這個規則的實現主要包含了兩個方面:

  1. JMM 禁止編譯器把 final 域的寫重排序 到 構造函數 之外
  2. 編譯器會在 final 域寫之后,構造函數 return 之前,插入一個 StoreStore 屏障。這個屏障可以禁止處理器把 final 域的寫重排序到構造函數之外

給舉個例子,要不太抽象了,先看一段代碼

  1. public class FinalTest{ 
  2.  
  3.     private int a;  //普通域 
  4.     private final int b; //final域 
  5.     private static FinalTest finalTest; 
  6.  
  7.     public FinalTest() { 
  8.         a = 1; // 1. 寫普通域 
  9.         b = 2; // 2. 寫final域 
  10.     } 
  11.  
  12.     public static void writer() { 
  13.         finalTest = new FinalTest(); 
  14.     } 
  15.  
  16.     public static void reader() { 
  17.         FinalTest demo = finalTest; // 3.讀對象引用 
  18.         int a = demo.a;    //4.讀普通域 
  19.         int b = demo.b;    //5.讀final域 
  20.     } 

假設線程 A 在執行 writer()方法,線程 B 執行 reader()方法。

由于變量 a 和變量 b 之間沒有依賴性,所以就有可能會出現下圖所示的重排序


由于普通變量 a 可能會被重排序到構造函數之外,所以線程 B 就有可能讀到的是普通變量 a 初始化之前的值(零值),這樣就可能出現錯誤。

而 final 域變量 b,根據重排序規則,會禁止 final 修飾的變量 b 重排序到構造函數之外,從而 b 能夠正確賦值,線程 B 就能夠讀到 final 域變量 b初始化后的值。

結論:寫 final 域的重排序規則可以確保在對象引用為任意線程可見之前,對象的 final 域已經被正確初始化過了,而普通域就不具有這個保障。

細節八:讀 final 域的重排序規則,你知道嗎?

這個規則是指在一個線程中,初次讀對象引用和初次讀該對象包含的 final 域,JMM 會禁止這兩個操作的重排序。

還是上面那段代碼

  1. public class FinalTest{ 
  2.  
  3.     private int a;  //普通域 
  4.     private final int b; //final域 
  5.     private static FinalTest finalTest; 
  6.  
  7.     public FinalTest() { 
  8.         a = 1; // 1. 寫普通域 
  9.         b = 2; // 2. 寫final域 
  10.     } 
  11.  
  12.     public static void writer() { 
  13.         finalTest = new FinalTest(); 
  14.     } 
  15.  
  16.     public static void reader() { 
  17.         FinalTest demo = finalTest; // 3.讀對象引用 
  18.         int a = demo.a;    //4.讀普通域 
  19.         int b = demo.b;    //5.讀final域 
  20.     } 

假設線程 A 在執行 writer()方法,線程 B 執行 reader()方法。

線程 B 可能就會出現下圖所示的重排序


可以看到,由于讀對象的普通域被重排序到了讀對象引用的前面,就會出現線程 B 還未讀到對象引用就在讀取該對象的普通域變量,這顯然是錯誤的操作。而 final 域的讀操作就“限定”了在讀 final 域變量前已經讀到了該對象的引用,從而就可以避免這種情況。

結論:讀 final 域的重排序規則可以確保在讀一個對象的 final 域之前,一定會先讀包含這個 final 域的對象的引用。

結束今天給大家總結了一下使用 final 關鍵字容易忽視的一些小細節,看完希望你能有所收獲。

 

責任編輯:姜華 來源: 狂聊Java
相關推薦

2021-02-17 13:35:17

finalgetJava

2023-01-13 08:54:20

MySQL數據庫

2020-08-10 08:00:13

JavaFinal關鍵字

2020-04-20 17:43:28

Java代碼優化開發

2021-01-05 10:26:50

鴻蒙Javafinal

2024-01-15 10:41:31

C++關鍵字開發

2009-12-08 18:02:06

PHP final關鍵

2012-03-13 14:41:41

JavaJVM

2018-11-19 11:43:13

Python數據函數

2011-05-27 15:00:12

網站優化關鍵字

2011-06-24 17:39:08

長尾關鍵詞

2019-08-28 16:38:49

finalJava編程語言

2024-01-25 11:36:08

C++構造函數關鍵字

2023-12-11 13:59:00

YieldPython生成器函數

2023-03-09 07:38:58

static關鍵字狀態

2022-11-29 07:33:15

JavaLombokRecord

2021-01-07 11:10:47

關鍵字

2023-06-26 08:02:34

JSR重排序volatile

2023-11-28 21:50:39

finalstaticvolatile

2022-02-17 08:31:38

C語言staic關鍵字
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美在线一区二区三区四区 | 在线免费观看视频你懂的 | 欧美精品电影一区 | 中文字幕在线视频观看 | 亚洲福利av | 国产精品精品久久久 | 国产视频中文字幕 | 午夜影院在线观看 | 久久精品亚洲一区二区三区浴池 | 激情一区二区三区 | 国产区视频在线观看 | 欧美一区二区三区视频在线观看 | 欧美日韩国产在线观看 | 日韩精品在线视频 | 女人夜夜春 | 日韩在线视频免费观看 | 国产精品久久久久久久久久不蜜臀 | 羞羞色视频 | 韩国av网站在线观看 | 成人在线免费观看视频 | 久久久久久国产精品 | 亚洲国产精品va在线看黑人 | 中文字幕在线精品 | 精品久久伊人 | a黄在线观看 | 亚洲a在线观看 | 久久久久精 | 日韩在线国产 | 先锋影音资源网站 | 精产国产伦理一二三区 | 欧美精品在线播放 | 99国内精品久久久久久久 | 青青久久 | 一级a爱片性色毛片免费 | 欧美一级电影免费 | 荷兰欧美一级毛片 | www国产成人 | 中文字幕久久精品 | 中文二区 | 免费在线看黄视频 | 一区二区中文 |