靜態內部類實現的單例模式是線程安全的


一、靜態內部類(靜態嵌套類)vs非靜態內部類(內部類)

靜態內部類

*靜態內部類只能訪問外部類的靜態方法和靜態屬性,如果是private也能訪問,其他則不能訪問,創建對象不依賴外部類
*靜態內部類可以定義靜態的屬性和方法

非靜態內部類

  • 內部類可以訪問其所在類的屬性(包括所在類的私有屬性),內部類創建自身對象需要先創建其所在類的對象
  • 可以定義內部接口,且可以定義另外一個內部類實現這個內部接口
  • 內部類不能定義static元素
  • 內部類可以多嵌套

總結

靜態內部類和外部類是相互獨立的,創建實例或者創建什么類型的對象都不受限制
非靜態內部類是外部類的一部分,創建實例必須先創建外部類的實例,可以訪問外部類的所有屬性

二、類的初始化及對象創建

類的加載、鏈接、初始化

1.class文件(二進制)通過類的加載器(引導類加載器、自定義加載器)加載(雙親委派機制)到內存中,並創建java.lang.Class對象(類是一類事物的抽象,Class是類的抽象,抽象的抽象)
2.鏈接:
①驗證:驗證字節碼文件格式等是否正確
②准備:類的靜態變量分配內存,並設置默認值
③解析:符號引用轉換為直接引用
3.初始化
初始化階段是執行類構造器 ()方法的過程。 ()方法是由編譯器自動收集類中的 所有類變量的賦值動作和靜態語句塊static{}中的語句合並產生的,編譯器收集的順序是由語句在源文件中出現的順序所決定的,靜態語句塊只能訪問到定義在靜態語句塊之前的變量,定義在它之后的變量,在前面的靜態語句塊可以賦值,但是不能訪問

類實例化的時機

1.使用new關鍵字創建對象
2.使用Class類的newInstance方法(反射機制)
3.使用Constructor類的newInstance方法(反射機制)
4.使用Clone方法創建對象
5.使用(反)序列化機制創建對象

類實例化的過程

static final 變量編譯階段分配內存空間並賦值→父類的類構造器 () -> 子類的類構造器 () -> 父類的成員變量和實例代碼塊 -> 父類的構造函數 -> 子類的成員變量和實例代碼塊 -> 子類的構造函數。

三、靜態內部類創建單例對象怎么保證線程安全

package com.bo.singleton;
/*靜態內部類創建單例對象*/
public class StaticInnerTest {
    public StaticInnerTest() {
        System.out.println("靜態內部類無參構造函數");
    }

    public static StaticInnerTest getInstance() {
        return Inner.sit;
    }
    //方法不需要設置同步
    public static class Inner{
        private static final StaticInnerTest sit = new StaticInnerTest();
    }

    public static void main(String[] args) {
        StaticInnerTest s1 = StaticInnerTest.getInstance();
        StaticInnerTest s2 = StaticInnerTest.getInstance();
        System.out.println(s1==s2);
    }
}

靜態內部類的特點:外部類加載時不需要加載靜態內部類,不被加載則不占用內存,(延遲加載)當外部類調用getInstance方法時,才加載靜態內部類,靜態屬性保證了全局唯一,靜態變量初始化保證了線程安全,所以這里的方法沒有加synchronized關鍵字(JVM保證了一個類的 初始化在多線程下被同步加鎖)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM