Java反射機制

我是南城余!阿里云開發者平臺專家博士證書獲得者!

歡迎關注我的博客!一同成長!

一名從事運維開發的worker,記錄分享學習。

專注于AI,運維開發,windows Linux 系統領域的分享!

本章節對應知識庫

反射機制 · 語雀


反射

Java給我們提供的一套API,使用這套API可以在運行時動態獲取指定對象所屬的類,創建運行時類的對象,調用指定的結構(屬性、方法)等。

Reflection(反射)是被視為動態語言的關鍵,反射機制允許程序在運行期間借助于Reflection API取得任何類的內部信息,并能直接操作任意對象的內部屬性及方法。

面向對象,調用指定結構(屬性、方法)等功能,使用反射與不使用的區別

不使用反射,我們需要考慮封裝性。比如出了Person類之后,就不能調用Person類中私有的結構

使用反射,我們可以調用運行時類中任意的構造器、屬性、方法。包括了私有的屬性、方法、構造器。

反射與創建對象調用方法的方式使用場景

》從作為開發者角度,我們開發中主要是完成業務代碼,對于相關的對象、方法的調用都是確定的。所以在開發中,我們使用非反射的方式多一些。

》因為反射體現了動態性(可以在運行時動態的獲取對象所屬的類,動態的調用相關的方法),所以我們在涉及框架時,會使用大量的反射。意味著,如果需要學習框架源碼時,那么就需要學習反射。

框架 = 注解+反射+設計模式

封裝性:體現的是是否建議我們調用內部api的問題。比如,private聲明的結構,意味著不建議調用

反射: 體現的是我們能否調用的問題。因為類的完整結構都加載了內存中,所以我們就有能力進行調用

反射的優缺點

優點:

》提高了Java程序的靈活性和擴展性,降低了耦合性,提高了自適應能力

》允許程序創建個控制任何類的對象,無需提前硬編碼目標類

缺點:

》反射的性能較低

反射機制主要應用在對靈活性和擴展性要求很高的系統框架上

》反射會模糊程序內部邏輯,可讀性較差

反射,平時開發中,我們使用的并不多。主要是在框架的底層使用

class - 反射的源頭

針對于編寫好的。java源文件進行編譯(使用javac.exe)會生成一個或多個.class字節碼文件。接著,我們使用java.exe命令對指定的.class文件進行解釋運行。在這個解釋運行的過程中,我們需要將.class字節碼文件加載(使用類的加載器)到內存中(存在方法區)。加載到內存中的.class文件對應的結構即為Class的一個實例。

比如:加載到內存中的Person類或String類,都作為Class的一個一個的實例

Class clazz1 = Person.class;

Class clazz1 =String.class;


class可以看作是反射的源頭

獲取Class實例的幾種方式

方式1:要求編譯期間已知類型

前提:若已知具體的類,通過類的class屬性獲取,該方法最為安全可靠,程序性能最高

實例:

Class clazz = String.class;

方式2:獲取對象的運行時類型

前提:已知某個類的實例,調用該實例的getClass()方法獲取Class對象

實例:

Class clazz = "www.atguigu.com".getClass();

方式3:可以獲取編譯期間未知的類型

前提:已知一個類的全類名,且該類在類路徑下,可通過Class類的靜態方法forName()獲取,可能拋出ClassNotFoundException

實例:

Class clazz = Class.forName("java.lang.String");

方式4:其他方式(不做要求)

前提:可以用系統類加載對象或自定義加載器對象加載指定路徑下的類型

實例:

ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 = cl.loadClass("類的全類名");
Class的實例指向結構

簡言,所有的Java類型

》class:外部類,成員(成員內部類,靜態內部類),局部內部類,匿名內部類

》interface:接口

》[]:數組

》enum:枚舉

》annotation:注解@interface

》primitive type :基本數據類型

》void

類的加載過程(了解)

過程1:類的裝載(loading)

將類的class文件讀入內存,并為之創建一個java.lang.Class對象。此過程由類加載器完成

過程2:鏈接(linking)

> 驗證(Verify):確保加載的類信息符合JVM規范,例如:以cafebabe開頭,沒有安全方面的問題。

> 準備(Prepare):正式為類變量(static)分配內存并設置類變量默認初始值的階段,這些內存都將在方法區中進行分配。

> 解析(Resolve):虛擬機常量池內的符號引用(常量名)替換為直接引用(地址)的過程。

過程3:初始化(initialization)

執行類構造器<clinit>()方法的過程。

類構造器<clinit>()方法是由編譯期自動收集類中所有類變量的賦值動作和靜態代碼塊中的語句合并產生的。

關于類的加載器(了解、JDK8版本為例)

作用:負責類的加載,并對應于一個Class的實例。

分類(分為兩種):

> BootstrapClassLoader:引導類加載器、啟動類加載器

> 使用C/C++語言編寫的,不能通過Java代碼獲取其實例

> 負責加載Java的核心庫(JAVA_HOME/jre/lib/rt.jar或sun.boot.class.path路徑下的內容)

> 繼承于ClassLoader的類加載器

> ExtensionClassLoader:擴展類加載器

> 負責加載從java.ext.dirs系統屬性所指定的目錄中加載類庫,或從JDK的安裝目錄的jre/lib/ext子目錄 下加載類庫

> SystemClassLoader/ApplicationClassLoader:系統類加載器、應用程序類加載器

> 我們自定義的類,默認使用的類的加載器。

> 用戶自定義類的加載器

> 實現應用的隔離(同一個類在一個應用程序中可以加載多份);數據的加密。

以上的類的加載器是否存在繼承關系? No!

使用類的加載器獲取流,并讀取配置文件信息
/*
* 需求:通過ClassLoader加載指定的配置文件
* */
@Test
public void test3() throws IOException {Properties pros = new Properties();//通過類的加載器讀取的文件的默認的路徑為:當前module下的src下InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("info1.properties");pros.load(is);String name = pros.getProperty("name");String pwd = pros.getProperty("password");System.out.println(name + ":" +pwd);
}

反射的應用

1. 創建運行時類的對象

如何實現

通過Class的實例調用newInstance()方法即可

且需要滿足以下條件:

》要求運行時必須提供一個空參構造器

》要求提供的空參構造器的權限要足夠

JavaBean中要求給當前類提供一個公共的的空參的構造器。

作用:

>場景1:子類對象在實例化時,子類的構造器的首行默認調用父類空參構造器

>場景2:在反射中,經常用來創建運行時類的對象。那么我們要求各個運行時類都提供一個空參構造器,便于我們編寫創建運行時類對象的代碼。

2. 獲取運行時類的內部結構

》獲取運行時類的內部結構:所有屬性、所有方法、所有構造器

》獲取運行時類的內部結構:父類、接口、包、帶泛型的父類、父類的泛型等

3. 調用指定的結構:指定的屬性、方法、構造器

調用指定的屬性步驟

步驟1. 通過Class實例調用getDeclareField(String fieldName),獲取運行時類指定名的屬性

步驟2. setAccessible(true),確保此屬性是可以訪問的

步驟3. 通過Field類的實例調用get(Object obj)(獲取操作)

或set(Object obj,Object value)(設置的操作)進行操作

調用指定的方法步驟

步驟1. 通過Class實例調用getDeclareField(String methodName,Class ... args),獲取運行時類指定的方法

步驟2. setAccessible(true),確保此屬性是可以訪問的

步驟3. 通過Method實例invoke(Object obj,Object .. objs),即為對Method對應方法的調用

invoke()返回值即為Method對應方法的返回值

特別的:如果Method對應的方法的返回值類型為void,則invoke()返回值為null

調用指定的構造器步驟

步驟1. 通過Class的實例調用getDeclaredConstructor(Class ... args),獲取指定參數的構造器

步驟2. setAccessible(true):確保此構造器是可訪問的

步驟3. 通過Constructor實例調用newInstance(Object ... objs),返回一個運行時類的實例

4. 注解的使用

框架層面

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/164882.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/164882.shtml
英文地址,請注明出處:http://en.pswp.cn/news/164882.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

RK3399平臺開發系列講解(內核入門篇)ConfigFS 的核心數據結構

??返回專欄總目錄 文章目錄 一、關鍵數據結構二、config_item 的結構體三、屬性和方法沉淀、分享、成長,讓自己和他人都能有所收獲!?? ??虛擬文件系統 ConfigFS 是一個特殊的文件系統,旨在提供一種動態配置 Linux 內核和設備的機制。 一、關鍵數據結構 ConfigFS 的核…

Vue表單的整體處理

在前端的處理中&#xff0c;表單的處理永遠是占高比例的。在BOMDOMjs的時候是這樣&#xff0c;在Vue的時候也是這樣。Vue的表單處理做了特別的優化&#xff0c;如值綁定、數據驗證、錯誤提示、修飾符等。 表單組件的示例&#xff1a; <script setup lang"ts">…

如何用Postman做接口自動化測試?一文5個步驟帶你成功實現!

什么是自動化測試 把人對軟件的測試行為轉化為由機器執行測試行為的一種實踐。 例如GUI自動化測試&#xff0c;模擬人去操作軟件界面&#xff0c;把人從簡單重復的勞動中解放出來 本質是用代碼去測試另一段代碼&#xff0c;屬于一種軟件開發工作&#xff0c;已經開發完成的用例…

解決kubernetes中微服務pod之間調用失敗報錯connection refused的問題

現象&#xff1a; 從這里可以看到是當前服務在調用product service服務是出現了連接拒絕connection refused 走讀一下原始代碼&#xff1a; 可以看到請求是由FeignClient代理發出的 &#xff0c;但問題在于為什么Feign請求的時候會產生connection refused錯誤&#xff1f; 上…

Programming Tensor Cores: NATIVE VOLTA TENSOR CORES WITH CUTLASS

PROGRAMMING TENSOR CORES: NATIVE VOLTA TENSOR CORES WITH CUTLASS 源自于 GTC Silicon Valley-2019: cuTENSOR: High-performance Tensor Operations in CUDA&#xff0c;介紹了 CUTLASS 1.3 中基于 Volta Tensor Core 實現高效矩陣乘法計算的策略。主要內容為以下三點&…

Python函數式編程:讓你的代碼更優雅更簡潔

概要 函數式編程&#xff08;Functional Programming&#xff09;是一種編程范式&#xff0c;它將計算視為函數的求值&#xff0c;并且避免使用可變狀態和循環。 函數式編程強調的是函數的計算&#xff0c;而不是它的副作用。 在函數式編程中&#xff0c;函數是第一類公民&a…

【Vue3】解決Vue打包后上傳服務器 資源路徑加載錯誤

問題&#xff1a; 我這里在打包Vue之后將打包后的dist 上傳至服務器站點根目錄內子目錄 名為 "adminstore" , 但是當我通過域名打開站點后發現 資源加載路徑內并沒有攜帶 子目錄 "adminstore" 文件名稱 錯誤&#xff1a;http://your website domain/js/app…

Java 開發常用的 Linux 命令匯總(建議收藏)

雖然平時大部分工作都是和Java相關的開發, 但是每天都會接觸Linux系統, 尤其是使用了Mac之后, 每天都是工作在黑色背景的命令行環境中. 自己記憶力不好, 很多有用的Linux命令不能很好的記憶, 現在逐漸總結一下, 以便后續查看. 基本操作 Linux關機,重啟 # 關機 shutdown -h n…

面試Java筆試題精選解答

文章目錄 熱身級別數組中重復的數字思路&#xff1a;使用map或HashSet來遍歷一遍就可以找出重復的字符樣例解答 用兩個棧實現隊列思路&#xff1a;Stack1正向進入&#xff0c;隊頭在棧底&#xff0c;用于進隊列操作&#xff1b;Stack2是Stack1倒棧形成&#xff0c;隊頭在棧頂&a…

學生成績管理系統(C++實現)

問題描述 實現學生成績管理系統&#xff1a; 學生信息包括&#xff1a;學號、姓名、性別、年齡、班級等信息。除了包括學生所有信息外&#xff0c;還包括專業、英語、程序設計和高等數學等課程。 設計一程序能夠對學生成績進行管理&#xff0c;應用到繼承、抽象類、虛函數、虛…

基于5G+物聯網+SaaS+AI的農業大數據綜合解決方案:PPT全文44頁,附下載

關鍵詞&#xff1a;智慧農業大數據&#xff0c;5G智慧農業&#xff0c;物聯網智慧農業&#xff0c;SaaS智慧農業&#xff0c;AI智慧農業&#xff0c;智慧農業大數據平臺 一、智慧農業大數據建設背景 1、應對全球人口快速增長帶來的糧食生產壓力&#xff0c;未來的糧食生產力必…

宣傳技能培訓1——《新聞攝影技巧》光影魔法:理解不同光線、角度、構圖的攝影效果,以及相機實戰操作 + 新聞攝影實例講解

新聞攝影技巧 寫在最前面摘要 構圖與拍攝角度景別人物表情與敘事遠景與特寫 構圖與拍攝角度案例 主體、陪體、前景、背景強調主體利用前景和背景層次感的創造 探索新聞攝影中的構圖技巧基本構圖技巧構圖技巧的應用實例實例分析1. 黃金分割和九宮格2. 三角型構圖3. 引導線構圖4.…

1)業務平臺集成電子簽章平臺

1.前言 電子簽章平臺隨著企業數字化轉型逐步滲透到日常運營項目中&#xff0c;如合同蓋章/規章制度發布/法審意見等場景下引入電子章解決蓋章需求。 作為特定業務下的統一處理方案&#xff0c;需要在業務管理平臺與電子簽章平臺之間構建一個橋梁&#xff0c;簡化電子簽章平臺…

Spring配置其他注解Spring注解的解析原理

Spring配置其他注解 Primary注解用于標注相同類型的Bean優先被使用權&#xff0c;Primary是Spring 3.0引入的&#xff0c;與Component和Bean一起使用&#xff0c;標注該Bean的優先級更高&#xff0c;則在通過類型獲取Bean或通過Autowired根據類型進行注入時&#xff0c;會選用優…

【C++11并發】future庫 筆記

簡介 C11之前&#xff0c;主線程要想獲取子線程的返回值&#xff0c;一般都是通過全局變量&#xff0c;或者類似機制。C11開始為我們提供了一組方法來獲取子線程的返回值&#xff0c;并保證其原子性。 頭文件 #include <future>std::promise 在promise中保存了一個值…

Python 的字符串格式化指南

字符串格式化 Python 中控制字符串格式通常有三種形式&#xff1a; % 占位符&#xff08;格式化符&#xff09;str.format() 函數f-string 內嵌式 Python 最先開始格式化字符串是用 %&#xff0c;但它的致命缺點是支持的類型有限制&#xff0c;只支持 int&#xff0c;str&am…

【從零開始實現意圖識別】中文對話意圖識別詳解

前言 意圖識別&#xff08;Intent Recognition&#xff09;是自然語言處理&#xff08;NLP&#xff09;中的一個重要任務&#xff0c;它旨在確定用戶輸入的語句中所表達的意圖或目的。簡單來說&#xff0c;意圖識別就是對用戶的話語進行語義理解&#xff0c;以便更好地回答用戶…

XUbuntu22.04之解決gpg keyserver receive failed no data(一百九十三)

簡介&#xff1a; CSDN博客專家&#xff0c;專注Android/Linux系統&#xff0c;分享多mic語音方案、音視頻、編解碼等技術&#xff0c;與大家一起成長&#xff01; 優質專欄&#xff1a;Audio工程師進階系列【原創干貨持續更新中……】&#x1f680; 人生格言&#xff1a; 人生…

DevExpress WinForms TreeMap組件,用嵌套矩形可視化復雜分層數據

DevExpress WinForms TreeMap控件允許用戶使用嵌套的矩形來可視化復雜的平面或分層數據結構。 DevExpress WinForms有180組件和UI庫&#xff0c;能為Windows Forms平臺創建具有影響力的業務解決方案。同時能完美構建流暢、美觀且易于使用的應用程序&#xff0c;無論是Office風…

中文rlhf數據集50w條數據解析

中文rlhf數據集50w條數據解析 解析代碼數據名代碼解析 解析代碼 import jieba from tqdm import tqdm import re import pandas as pd import numpy as npdef find_non_english_text(text):pattern re.compile(r[^a-zA-Z])return pattern.sub(, text)def find_chinese_text(t…