反射 p3 類載入

来源:https://www.cnblogs.com/zh-Note/archive/2023/07/25/17557510.html
-Advertisement-
Play Games

# 類載入 ## **基本說明** 反射機制是Java實現動態語言的關鍵,也就是通過反射實現類動態載入。 1. **靜態載入:**編譯時載入相關的類,如果沒有則報錯,依賴性太強。 2. **動態載入:**運行時載入相關的類,如果運行時不用該類,即使不存在該類,也不會報錯,降低了依賴性。 - **代碼 ...


類載入

基本說明

反射機制是Java實現動態語言的關鍵,也就是通過反射實現類動態載入。

  1. 靜態載入:編譯時載入相關的類,如果沒有則報錯,依賴性太強。
  2. 動態載入:運行時載入相關的類,如果運行時不用該類,即使不存在該類,也不會報錯,降低了依賴性。
  • 代碼演示:

    import java.util.*;
    import java.lang.reflect.*;
    
    public class ClassLoad_{
    	public static void main(String[] args) throws Exception{
    		Scanner scan = new Scanner(System.in);
    		String key = scan.next();
    
    		switch(key){
    			case "1":
    				Dog dog = new Dog();//靜態載入,依賴性很強
    				dog.cry();
    				break;
    			case "2":
    				//反射 -> 動態載入
    				Class cls = Class.forName("Person");//載入Person類[動態載入]
    				Object o = cls.newInstance();
    				Method m = cls.getMethod("hi");
    				m.invoke(o);
    				System.out.println("OK");
    				break;
    			default:
    				System.out.println("do nothing....");
    		}
    
    	}
    }
    
    
    /* 未寫Dog類時,DOS視窗運行結果,編譯錯誤
    C:\Users\86199\Desktop>javac ClassLoad_.java
    ClassLoad_.java:11: 錯誤: 找不到符號
                                    Dog dog = new Dog();//靜態載入,依賴性很強
                                    ^
      符號:   類 Dog
      位置: 類 ClassLoad_
    ClassLoad_.java:11: 錯誤: 找不到符號
                                    Dog dog = new Dog();//靜態載入,依賴性很強
                                                  ^
      符號:   類 Dog
      位置: 類 ClassLoad_
    註: ClassLoad_.java使用了未經檢查或不安全的操作。
    註: 有關詳細信息, 請使用 -Xlint:unchecked 重新編譯。
    2 個錯誤
    */
    
    
    //因為 new Dog() 是靜態載入,因此必須編寫Dog類,否則在編譯過程就會報錯
    //Person類是動態載入,所以沒有編寫Person類在編譯過程也不會報錯,
    //只有在動態載入該類時才會報錯
    
    class Dog{
    	public void cry(){
    		System.out.println("小狗汪汪叫");
    	}
    }
    
    
    /* 未寫Person類時,DOS視窗運行結果,運行時報錯
    C:\Users\86199\Desktop>java ClassLoad_
    1
    小狗汪汪叫
    ===============================================================
    C:\Users\86199\Desktop>java ClassLoad_
    2
    Exception in thread "main" java.lang.ClassNotFoundException: Person
            at java.net.URLClassLoader.findClass(Unknown Source)
            at java.lang.ClassLoader.loadClass(Unknown Source)
            at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
            at java.lang.ClassLoader.loadClass(Unknown Source)
            at java.lang.Class.forName0(Native Method)
            at java.lang.Class.forName(Unknown Source)
            at ClassLoad_.main(ClassLoad_.java:16)
    */
    
    
    class Person{
    	public void hi(){
    		System.out.println("hi....");
    	}
    }
    
    /* 寫了Peson類後,DOS視窗運行結果
    C:\Users\86199\Desktop>java ClassLoad_
    1
    小狗汪汪叫
    =================================================
    C:\Users\86199\Desktop>java ClassLoad_
    2
    hi....
    OK
    */
    

類載入時機

  1. 當創建對象時(new),靜態載入;
  2. 當子類被載入時,父類也載入,靜態載入;
  3. 調用類中的靜態成員時,靜態載入;
  4. 通過反射,動態載入;

類載入流程

類載入流程圖

  • 類載入過程圖

  • 類載入各階段完成的任務

類載入五個階段

  1. 載入階段(Loading)

    JVM在該階段的主要目的是將位元組碼從不同的數據源(可能是class文件、也可能是jar包,甚至網路)轉化為二進位位元組流載入到記憶體中,並生成一個代表該類的java.lang.Class對象;

  2. 連接階段(Linking)

    1. 驗證(Verification):

      • 目的:是為了確保Class文件的位元組流中包含的信息符合當前虛擬機的要求,並且不會危害虛擬機自身的安全;
      • 包括:文件格式驗證(是否以魔數 oxcafebabe 開頭)、元數據驗證、位元組碼驗證和符號引用驗證;
      • 可以考慮使用 -Xverify:none 參數來關閉大部分的類驗證措施,縮短虛擬機載入的時間;
    2. 準備(Preparation):

      JVM 會在該階段對靜態變數,分配記憶體並預設初始化(對應數據類型的預設初始值,如0、0L、null、false等)。這些變數所使用的記憶體都將在方法區中進行分配。

      package com.hspedu.classload_;
      
      /**
       * @author: 86199
       * @date: 2023/6/2 21:19
       * @description: 說明類載入夾的連接階段(Linking)-準備(Preparation)
       */
      public class ClassLoad02 {
      }
      
      class A{
          //屬性-欄位-成員變數
          //分析類載入階段的連接階段(Linking)-準備,屬性是如何處理的
          //1. n1是實例屬性,不是靜態變數,因此在準備階段是不會分配記憶體的
          //2. n2是靜態屬性,分配記憶體,n2 預設初始化為0,而不是20,20是在連接階段之後的初始化階段進行的
          //3. n3是static final 是常量
          public int n1 = 1;
          public static int n2 = 2;
          public final static int n3 = 3;
      }
      
    3. 解析(Resolution):虛擬機將常量池內的符號引用替換為直接引用的過程。

  3. 初始化(Initialization):

    • 到初始化階段,才是真正的開始執行類中定義的Java程式代碼,此階段是執行()方法的過程;

    • ()方法是由編譯器按語句在源文件中出現的順序,依次自動收集類中的所有靜態變數的賦值動作和靜態代碼塊中的語句,併進行合併;

    • 虛擬機會保證一個類的()方法在多線程環境中被正確地加鎖、同步,如果多個線程同時去初始化一個類,那麼只會有一個線程去執行這個類的()方法,其他線程都需要阻塞等待,直到活動線程執行()方法完畢;

      源碼:

    案例演示:

    package com.hspedu.classload_;
    
    /**
     * @author: 86199
     * @date: 2023/6/2 22:19
     * @description: 演示類載入——初始化階段(Initialization)
     */
    public class ClassLoad03_ {
        static {
            System.out.println("ClassLoad03_ 靜態代碼塊被執行");
        }
        public static void main(String[] args) throws ClassNotFoundException {
            //1. Loading:載入B類,並生成B類的Class對象
            //2. Linking:num = 0
            //3. Initialization:
            //      依次收集類中所有的靜態變數和靜態代碼塊中的語句入clinit()中,併合並
            /*
                clinit(){
                    System.out.println("B 靜態代碼塊被執行");
                    //num = 300;
                    num = 100;
                }
                合併:num = 300, num = 100  --> num = 100
             */
    //        new B();//也會使B類載入,但是B類載入只會執行一遍
    //        System.out.println(B.num);//直接使用B類的靜態屬性,也會導致B類載入
    
            //看看類載入時,是有同步機制控制的
            /*
                protected Class<?> loadClass(String name, boolean resolve)
                    throws ClassNotFoundException
                {
                    synchronized (getClassLoadingLock(name)) {
                    //拿到一個同步鎖,正因為有這個機制,才能保證某個類在記憶體中只有一份Class對象
                    }
                }
             */
            Class<?> aClass = Class.forName("B");
        }
    }
    
    class B{
        static {
            System.out.println("B 靜態代碼塊被執行");
            num = 300;
        }
    
        static int num = 100;
    
        public B() {//構造器
            System.out.println("B() 構造器被執行...");
        }
    }
    
    

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Docker CLI (命令行界面) 是一個強大的工具,可讓您與 Docker 容器、映像、捲和網路進行交互和管理。它為用戶提供了廣泛的命令,用於在其開發和生產工作流中創建、運行和管理 Docker 容器和其他 Docker 資源。 ### 安裝 要開始使用 Docker CLI,您需要在電腦上安 ...
  • # 未定義行為之 NULL dereference 下麵這段代碼中 `is_valid()` 解引用了空指針 `str`,我們的直覺是編譯運行後將迎來 SIGSEGV,然而事情並非所期望的那樣。 ```c /* * ub_null.c - 未定義行為演示 之 NULL dereference */ ...
  • 本專題寫作的目的其實是分享go語言編程的使用場景,介紹go語言編程的方方面面,讓大家能夠用好這個由google公司發明的強力工具,提升大家在這方面的生產力,畢竟**”君子善假與物也“**嘛。 這裡我先說明一下,我並不是一個對go語言的所有一切都認同的人,你會發現很多相關從業者也會吐槽go語言的“專制 ...
  • # **反射相關使用和暴破** ## **通過反射創建對象** 1. **方式一:**調用類中的public修飾的無參構造器; 2. **方式二:**調用類中的指定構造器; 3. **Class類相關方法:** - newInstance():調用類中的無參構造器,獲取對應類的對象; - getCo ...
  • 原文在[這裡](https://grpc.io/docs/languages/go/basics/)。 本教程為Go程式員提供了使用gRPC的基本介紹。 通過跟隨本示例,你將學會如何: - 在.proto文件中定義一個服務。 - 使用協議緩衝編譯器生成伺服器和客戶端代碼。 - 使用Go gRPC A ...
  • # 反射獲取類的結構信息 1. **關於Class的API** 1. getName:獲取全類名 2. getSimpleName:獲取簡單類名 3. getFields:獲取所有Public修飾的屬性,包含本類及其父類(不僅僅是直接父類) 4. getDeclaredFields:獲取本類中的所有 ...
  • 【不定期更新】本文主要介紹了Java學習前期的一些概念問題,包括“面向對象和麵向過程的區別”、“C++和Java的不同之處”等等,適合初學者學習。 ...
  • ![file](https://img2023.cnblogs.com/other/488581/202307/488581-20230725174651506-356208797.jpg) > > 這篇文章全面探討了Python作為數據科學領域首選語言的原因。從Python的歷史、特性,到在數據科 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...