<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【Java 溫故而知新系列】基礎(chǔ)知識-04 重點關(guān)鍵字(面試經(jīng)常遇到的)

      1、final 

      在 Java 中,final 關(guān)鍵字可以用于變量、方法和類,分別賦予它們不同的語義和行為。以下是 final 關(guān)鍵字的主要作用

      修飾變量

      當(dāng) final 修飾一個變量時,表示該變量的值一旦初始化后就不能再被改變。這適用于基本類型和引用類型。

      • 基本類型:對于基本類型(如 intdouble 等),final 意味著變量的值不能改變。基本類型詳情見這篇【Java 溫故而知新系列】基礎(chǔ)知識-02 數(shù)據(jù)基本類型
      • 引用類型:對于引用類型(如對象或數(shù)組),final 意味著引用本身不能指向另一個對象,但對象內(nèi)部的狀態(tài)是可以改變的(除非對象本身是不可變的)
      1 final int x = 5; // 基本類型的 final 變量
      2 // x = 10; // 錯誤:不能修改 final 變量的值
      3 
      4 final StringBuilder sb = new StringBuilder("Hello");
      5 sb.append(" World"); // 正確:可以修改對象的狀態(tài)
      6 // sb = new StringBuilder("Java"); // 錯誤:不能重新賦值給 final 引用

      修飾方法

      當(dāng) final 修飾一個方法時,表示該方法不能被子類重寫(override)。這有助于確保某些關(guān)鍵行為不會被意外改變,并且可以提高性能優(yōu)化的可能性,因為編譯器知道該方法的行為不會在運行時改變。

      代碼為證:

       修飾類

      當(dāng) final 修飾一個類時,表示該類不能被繼承。這意味著沒有任何其他類可以從這個類派生出來。使用 final 類通常是為了保護(hù)類的設(shè)計不被更改,或者是因為該類提供了非常具體的實現(xiàn),不需要也不應(yīng)該有子類。

      其實Java中我們平時用到的很多類都是被final關(guān)鍵字修飾的,比如常用的包裝類:Integer、Double 等(包裝類詳情可見這篇:【Java 溫故而知新系列】基礎(chǔ)知識-03 基本類型對應(yīng)之包裝類),再比如 String 等等。

      修飾方法參數(shù)

      你也可以將方法參數(shù)聲明為 final,這意味著在方法體內(nèi)不能修改這些參數(shù)的值。這對于編寫清晰、無副作用的方法很有幫助,尤其是在多線程環(huán)境中。其實這個跟第一種修飾變量是比較類似的。

      代碼為證:

      2、static

      static可以用來修飾變量、方法、代碼塊和內(nèi)部類。使用 static 的主要目的是為了創(chuàng)建屬于類本身而不是類的實例(對象)的成員。這意味著靜態(tài)成員可以在沒有創(chuàng)建類的任何實例的情況下被訪問,并且所有實例共享同一個靜態(tài)成員。

       靜態(tài)變量

      • 靜態(tài)變量:又稱為類變量,也就是說這個變量屬于類的,類所有的實例都共享靜態(tài)變量,可以直接通過類名來訪問它。靜態(tài)變量在內(nèi)存中只存在一份。
      • 實例變量:每創(chuàng)建一個實例就會產(chǎn)生一個實例變量,它與該實例同生共死。
       1 class  A {
       2     public static Integer count = 10; //靜態(tài)變量,類變量
       3     public Integer countB= 10;//實例變量
       4 }
       5 public class JavaKeyWorkDemo {
       6     public static void main(String[] args) {
       7         System.out.println(A.count);
       8         A.count = 20;
       9         System.out.println(A.count);
      10     }
      11 }

       

       

      10
      20

       

      靜態(tài)方法

      靜態(tài)方法在類加載的時候就存在了,它不依賴于任何實例。所以靜態(tài)方法必須有實現(xiàn),也就是說它不能是抽象方法。

      1 public abstract class A {
      2     public static void func1(){
      3     }
      4     // public abstract static void func2();  // Illegal combination of modifiers: 'abstract' and 'static'
      5 }

      只能訪問所屬類的靜態(tài)字段和靜態(tài)方法,方法中不能有 this 和 super 關(guān)鍵字,因為這兩個關(guān)鍵字與具體對象關(guān)聯(lián)。

      1 class  A {
      2     public static Integer countA = 10; //靜態(tài)變量,類變量
      3     public Integer countB= 10;//實例變量
      4     public static void func1(){
      5         Integer a = countA;
      6         //Integer b = countB;  // Non-static field 'countB' cannot be referenced from a static context 無法從 static 上下文引用非 static 字段 'countB'
      7         //Integer c = this.countB;     // 'A.this' cannot be referenced from a static context 無法從 static 上下文引用 'A.this'
      8     }
      9 }

       

       靜態(tài)代碼塊

      靜態(tài)語句塊在類初始化時運行一次。靜態(tài)代碼塊用于初始化類級別的資源,在類加載到 JVM 時執(zhí)行一次。如初始化靜態(tài)變量等。

       1 class  A {
       2     static {
       3         System.out.println("123");
       4     }
       5     public static Integer countA = 10; //靜態(tài)變量,類變量
       6     public Integer countB= 10;//實例變量
       7     public static void func1(){
       8         Integer a = countA;
       9         //Integer b = countB;  // Non-static field 'countB' cannot be referenced from a static context 無法從 static 上下文引用非 static 字段 'countB'
      10         //Integer c = this.countB;     // 'A.this' cannot be referenced from a static context 無法從 static 上下文引用 'A.this'
      11     }
      12 }
      13 public class JavaKeyWorkDemo {
      14     public static void main(String[] args) {
      15         A a1= new A();
      16         A a2= new A();
      17     }
      18 }
      123

      靜態(tài)內(nèi)部類

      非靜態(tài)內(nèi)部類依賴于外部類的實例,也就是說需要先創(chuàng)建外部類實例,才能用這個實例去創(chuàng)建非靜態(tài)內(nèi)部類。而靜態(tài)內(nèi)部類不需要。靜態(tài)內(nèi)部類不能訪問外部類的非靜態(tài)的變量和方法。

      靜態(tài)內(nèi)部類實現(xiàn)單例:

       1 public class Singleton {
       2  
       3     // 私有構(gòu)造函數(shù),防止外部直接實例化
       4     private Singleton() {
       5     }
       6  
       7     // 靜態(tài)內(nèi)部類,用于持有外部類的實例
       8     private static class SingletonHolder {
       9         private static final Singleton INSTANCE = new Singleton();
      10     }
      11  
      12     // 提供公有的靜態(tài)方法,用于獲取外部類的實例
      13     public static Singleton getInstance() {
      14         return SingletonHolder.INSTANCE;
      15     }
      16 }

       

      靜態(tài)導(dǎo)包

      在使用靜態(tài)變量和方法時不用再指明 ClassName,從而簡化代碼,但可讀性大大降低。

      import static 包名.類名.靜態(tài)成員;//導(dǎo)入一個類中指定靜態(tài)成員
      import static com.xxx.ClassName.* //導(dǎo)入一個類中的所有靜態(tài)成員,可以使用通配符*

       

      1 import static java.lang.Math.*;
      2 
      3 public class StaticImportExample {
      4     public static void main(String[] args) {
      5         System.out.println(sqrt(16)); // 直接調(diào)用 sqrt 方法,無需前綴 Math.
      6         System.out.println(PI); // 直接使用 PI 常量,無需前綴 Math.
      7     }
      8 }

       

      初始化順序

       靜態(tài)變量和靜態(tài)語句塊優(yōu)先于實例變量和普通語句塊,靜態(tài)變量和靜態(tài)語句塊的初始化順序取決于它們在代碼中的順序。

      存在繼承的情況下,初始化順序為:

      • 父類(靜態(tài)變量、靜態(tài)語句塊)
      • 子類(靜態(tài)變量、靜態(tài)語句塊)
      • 父類(實例變量、普通語句塊)
      • 父類(構(gòu)造函數(shù))
      • 子類(實例變量、普通語句塊)
      • 子類(構(gòu)造函數(shù))

      3、 public,private,protected,以及不寫(默認(rèn))時的區(qū)別

      定義:Java中,可以使用訪問修飾符來保護(hù)對類、變量、方法和構(gòu)造方法的訪 問。Java 支持 4 種不同的 訪問權(quán)限。
      分類:
      • private : 在同一類內(nèi)可見。使用對象:變量、方法。 注意:不能修飾類(外部 類)
      • default (即缺省,什么也不寫,不使用任何關(guān)鍵字): 在同一包內(nèi)可見,不使用 任何修飾符。使用 對象:類、接口、變量、方法。
      • protected : 對同一包內(nèi)的類和所有子類可見。使用對象:變量、方法。 注意: 不能修飾類(外部 類)。
      • public : 對所有類可見。使用對象:類、接口、變量、方法

      4、this關(guān)鍵字的用法

      this是自身的一個對象,代表對象本身,可以理解為:指向?qū)ο蟊旧淼囊粋€指 針。
      this的用法在java中大體可以分為3種:
      • 普通的直接引用,this相當(dāng)于是指向當(dāng)前對象本身。
      • 形參與成員名字重名,用this來區(qū)分
      1 public Person(String name, int age) {
      2  this.name = name;
      3  this.age = age;
      4 }

       

      • 引用本類的構(gòu)造函數(shù)

       

       1  class Person{
       2  private String name;
       3  private int age;
       4 
       5  public Person() {
       6  }
       7 
       8  public Person(String name) {
       9  this.name = name;
      10  }
      11  public Person(String name, int age) {
      12  this(name);
      13  this.age = age;
      14  }
      15  }

       

      5、super關(guān)鍵字的用法

      super可以理解為是指向自己超(父)類對象的一個指針,而這個超類指的是離 自己最近的一個父類。
      super也有三種用法:
      • 普通的直接引用 與this類似,super相當(dāng)于是指向當(dāng)前對象的父類的引用,這樣就可以用super.xxx來引用父類的成員。
      • 子類中的成員變量或方法與父類中的成員變量或方法同名時,用super進(jìn)行區(qū)分 
      • 引用父類構(gòu)造函數(shù)。super(參數(shù)):調(diào)用父類中的某一個構(gòu)造函數(shù)(應(yīng)該為構(gòu)造函數(shù)中的第一條語句);this(參數(shù)):調(diào)用本類中另一種形式的構(gòu)造函數(shù)(應(yīng)該為構(gòu)造函數(shù)中的第一條語句)。 
       1 class Person{
       2     protected String name;
       3 
       4     public Person(String name) {
       5     this.name = name;
       6     }
       7 
       8     }
       9 
      10      class Student extends Person{
      11      private String name;
      12 
      13      public Student(String name, String name1) {
      14      super(name);
      15      this.name = name1;
      16      }
      17 
      18      public void getInfo(){
      19      System.out.println(this.name); //Child
      20      System.out.println(super.name); //Father
      21      }
      22 
      23      }
      24 
      25      public class Test {
      26      public static void main(String[] args) {
      27      Student s1 = new Student("Father","Child");
      28      s1.getInfo();
      29 
      30      }
      31  }

       6、volatile

       volatile是一個變量修飾符,只能用來修飾變量,用法也比較簡單,只需要在聲明一個可能被多線程訪問的變量時,使用volatile修飾即可。在并發(fā)編程的三大特性——原子性、可見性、有序性中,volatile只能保證可見性和有序性(禁止指令重排),并不能保證原子性

      • 原子性:一個操作不可拆分、不被中斷,要么全部執(zhí)行,要么都不執(zhí)行。(數(shù)據(jù)庫中ACID的原子性指的是“要么都執(zhí)行要么都回滾”,這是不同的概念)
      • 可見性:指多個線程之間共享數(shù)據(jù)的可見性。即當(dāng)一個線程修改了共享變量時,其它線程能立即看到這個修改
      • 有序性:volatile除了可以保證數(shù)據(jù)的可見性之外,還有一個強(qiáng)大的功能,那就是它可以禁止指令重排序,所以能在一定程度上保證有序性

      不能保證原子性(代碼為證):

       1 class VolatileIncr {
       2     volatile int num = 0;
       3     public void add() {
       4         num++;
       5     }
       6     public static void main(String[] args) {
       7         VolatileIncr test = new VolatileIncr();
       8         //啟動10個線程
       9         for (int i = 0; i < 10; i++) {
      10             new Thread(() -> {
      11                 //每個線程執(zhí)行1000次+1操作
      12                 for (int j = 0; j < 1000; j++) {
      13                     test.add();
      14                 }
      15             }, String.valueOf(i)).start();
      16         }
      17         while (Thread.activeCount() > 2) {
      18             Thread.yield();
      19         }
      20         System.out.println("最后num的值為:" + test.num);
      21     }
      22 }

       

       

      其中一次的執(zhí)行結(jié)果:

      最后num的值為:9120
      
      進(jìn)程已結(jié)束,退出代碼0

      以上代碼,我們的預(yù)期結(jié)果應(yīng)該是10000才對,但執(zhí)行起來發(fā)現(xiàn),并不是每次都是10000,這就是因為i++這個操作沒辦法保證原子性。它其實包含三個指令:

      • 執(zhí)行GETFIELD拿到主內(nèi)存中的原始值num。
      • 執(zhí)行IADD進(jìn)行+1操作。
      • 執(zhí)行PUTFIELD把工作內(nèi)存中的值寫回主內(nèi)存中。

      當(dāng)多個線程并發(fā)執(zhí)行PUTFILED指令的時候,會出現(xiàn)寫回主存覆蓋的問題,所以最終結(jié)果可能會比預(yù)期的結(jié)果要小,所以volatile不能保證原子性。

      可見性(代碼為證):

       1 class Visibility {
       2     private boolean flag = false;
       3     public void start() {
       4         new Thread(() -> {
       5             System.out.println("Thread1 start");
       6             while (!flag) {
       7                 // 不斷循環(huán),等待flag變?yōu)閠rue
       8             }
       9             System.out.println("Thread1 complet");
      10         }).start();
      11         // 確保線程1先啟動
      12         try {
      13             Thread.sleep(100);
      14         } catch (InterruptedException e) {
      15             e.printStackTrace();
      16         }
      17         new Thread(() -> {
      18             System.out.println("Thread2 start");
      19             // 修改flag的值為true
      20             flag = true;
      21             System.out.println("Thread2 complet");
      22         }).start();
      23     }
      24     public static void main(String[] args) {
      25         Visibility example = new Visibility();
      26         example.start();
      27     }
      28 }

       

      執(zhí)行結(jié)果:

       

      從結(jié)果看,程序“卡”在了Thread1的while循環(huán)中,說明Thread1讀到的flag還是flase,但是Thread2已經(jīng)把它改為true了,這是為什么?這是因為Thread1在執(zhí)行的時候,就把flag的副本保存在這就的工作內(nèi)存中,之后就會一直讀取自己線程工作內(nèi)存中flag變量的值,而不會去主內(nèi)存中重新獲取新的值。

      加了volatile修飾后的運行結(jié)果:

       

      有序性(代碼為證):

      下面是一個經(jīng)典的例子:雙重檢測實現(xiàn)單例的例子(面試經(jīng)常問這樣實現(xiàn)單例會不會有問題?有什么問題?如何解決?)

       1 public class Singleton {
       2     //私有化構(gòu)造函數(shù)
       3     private Singleton(){}
       4     //單例對象(無volatile修飾)
       5     private static Singleton instance=null;
       6     public static Singleton getInstance(){
       7         //第一次檢測
       8         if (instance==null){
       9             //加鎖
      10             synchronized (Singleton.class){
      11                 //第二次檢測
      12                 if (instance==null){
      13                     //初始化
      14                     instance=new Singleton();
      15                 }
      16             }
      17         }
      18         return instance;
      19     }
      20 }

       

      雙重校驗鎖機(jī)制在多線程環(huán)境中,不一定線程安全,原因是有指令重排的存在,在極端情況下,上述的單例對象可能發(fā)生空指針異常

      我們假設(shè)線程1和線程2同時請求getSingleton()方法的時候:

      • 線程1執(zhí)行到instance=new Singleton();,開始初始化。
      • 線程2執(zhí)行到“第一次檢測”的位置,判斷singleton == null。
      • 線程2經(jīng)過判斷發(fā)現(xiàn)singleton !=null,于是就直接執(zhí)行return instance。
      • 線程2拿到singleton對象后,開始執(zhí)行后續(xù)的操作。

      以上過程看似沒有什么問題,但在第4步執(zhí)行后續(xù)操作的時候,是有可能拋空指針異常的,這是因為在第3步的時候,線程2拿到的singleton對象并不是一個完整的對象。

      很明顯instance=new Singleton();,這段代碼出現(xiàn)了問題,那我們來分析一下,這個代碼的執(zhí)行過程可以簡化成3步:

      • JVM為對象分配一塊內(nèi)存M。
      • 在內(nèi)存上為對象進(jìn)行初始化。
      • 將內(nèi)存M的地址賦值給singleton變量。

      因為將內(nèi)存的地址賦值給singleton變量是最后一步,所以線程1在這一步驟執(zhí)行之前,線程2在對singleton == null判斷一直都是true,那么它會一直阻塞,直到線程1執(zhí)行完。

      但是這個過程并不是一個原子操作,并且編譯器可能會進(jìn)行重排序,如果以上步驟被重排序為:

      • JVM為對象分配一塊內(nèi)存M。
      • 將內(nèi)存M的地址賦值給singleton變量。
      • 在內(nèi)存上為對象進(jìn)行初始化。

      這樣的話線程1會先內(nèi)存分配,再執(zhí)行變量賦值,最后執(zhí)行初始化。也就是說在線程1執(zhí)行初始化之前,線程2對singleton == null的判斷會提前得到一個false,于是便返回了一個不完整的對象,所以在執(zhí)行后續(xù)操作時,就發(fā)生了空指針異常。

      要解決的話,直接禁止它指令重排就行了,所以volatile就派上用場了,只需要用volatile修飾一下instance即可。

      7、其他

      class (類):public class A(){}花括號里是已實現(xiàn)的方法體,類名需要與文件名相同
      
      interface (接口):public interface B(){}花括號里有方法體,但沒有實現(xiàn),方法體句子后面是英文分號“;”結(jié)尾
      
      abstract (聲明抽象):public abstract class C(){}介于類與接口中間,可以有,也可以沒有已經(jīng)實現(xiàn)的方法體
      
      implements (實現(xiàn)):用于類或接口,實現(xiàn)接口public class A interface B(){}
      
      extends (繼承):用于類繼承類public class A extends D(){}
      
      new (創(chuàng)建新對象):A a=new A();A表示一個類
      
      import (引入包的關(guān)鍵字):當(dāng)使用某個包的一些類時,僅需要類名,即可自動插入類所在的包
      
      package (定義包的關(guān)鍵字):將所有相關(guān)的類放在一個包類以便查找修改等
      
      assert(斷言):assert <bool expression>,以 Integer類的IntegerCache 方法 中代碼舉例  assert IntegerCache.high >= 127。斷言是為了方便調(diào)試程序,并不是發(fā)布程序的組成部分。理解這一點是很關(guān)鍵的。默認(rèn)情況下,JVM是關(guān)閉斷言的。因此如果想使用斷言調(diào)試程序,需要手動打開斷言功能。在命令行模式下運行Java程序時可增加參數(shù)-enableassertions或者-ea打開斷言。可通過-disableassertions或者-da關(guān)閉斷言(默認(rèn)情況,可有可無)。
      
      const——常量,常數(shù):用于修改字段或局部變量的聲明。保留字(現(xiàn)在沒用以后可能用到作為關(guān)鍵字)
      
      goto——轉(zhuǎn)到:指定跳轉(zhuǎn)到標(biāo)簽,找到標(biāo)簽后,程序?qū)⑻幚韽南乱恍虚_始的命令。保留字(現(xiàn)在沒用以后可能用到作為關(guān)鍵字)

       

       

      雙重校驗鎖機(jī)制在多線程環(huán)境中,不一定線程安全,原因是有指令重排的存在
      posted @ 2025-01-03 16:50  朱小路  閱讀(142)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 欧美视频专区一二在线观看| 成年女人免费碰碰视频| 亚洲中文字幕一区二区| 国产亚洲精品岁国产精品| 大地资源中文在线观看西瓜| 2020年最新国产精品正在播放| 国产自国产自愉自愉免费24区| 国产成人精品亚洲高清在线| 一卡2卡三卡4卡免费网站| 兴业县| 久久涩综合一区二区三区 | 亚洲av第三区国产精品| 午夜精品区| 久久精品国产大片免费观看| 国产亚洲AV电影院之毛片| 内丘县| 国产高清在线精品一本大道| 伊人久久大香线蕉AV网禁呦| 午夜射精日本三级| 激情五月天一区二区三区| 翘臀少妇被扒开屁股日出水爆乳| 久女女热精品视频在线观看| 开心五月婷婷综合网站| 午夜福利国产精品视频| 亚洲欧美不卡视频在线播放| √天堂资源网最新版在线| 国产精品小视频一区二页| 连山| 天堂V亚洲国产V第一次| 国产精品va无码一区二区| 67194亚洲无码| 亚洲国产精品一区二区第一页| 又大又粗又爽18禁免费看| 精品国产成人亚洲午夜福利| 在线高清免费不卡全码| 久9视频这里只有精品| 亚洲精品久久国产高清小说| 丁香花在线影院观看在线播放 | 爱啪啪精品一区二区三区| 丝袜美腿亚洲综合第一区| 91中文字幕一区在线|