Java反射 八股版

目錄

一、核心概念闡釋

1. Class類

2. Constructor類

3. Method類

4. Field類

二、典型應用場景

1. 框架開發

2. 單元測試

3. JSON序列化/反序列化

三、性能考量

四、安全與訪問控制

1. 安全管理器限制

2. 打破封裝性

3. 安全風險

五、版本兼容性問題

六、最佳實踐建議

七、示例代碼


反射是 Java 的核心機制,允許程序在運行時動態分析和操作類、方法、字段等元信息。

通過反射,代碼可以突破編譯期限制,實現靈活的動態行為。在Java編程里,反射是一項極為重要的特性。

它能讓程序在運行時對自身進行檢查,還可以動態地操作類、方法、字段等各種信息。下面為你詳細剖析Java反射的關鍵概念、使用場景以及實際操作中的注意要點。

一、核心概念闡釋

1. Class類

Class類在反射機制中處于核心地位,它代表著Java中的類型(類、接口、數組、基本數據類型等)。要獲取Class對象,有以下幾種常見的方式:

// 方式一:通過類名獲取
Class<?> clazz1 = String.class;// 方式二:通過對象實例獲取
String str = "hello";
Class<?> clazz2 = str.getClass();// 方式三:通過全限定名獲取(可能會拋出ClassNotFoundException異常)
Class<?> clazz3 = Class.forName("java.lang.String");
2. Constructor類

Constructor類的作用是表示類的構造方法,借助它能夠在運行時動態創建對象:

Class<?> clazz = Person.class;
// 獲取無參構造方法
Constructor<?> constructor = clazz.getConstructor();
// 創建實例
Person person = (Person) constructor.newInstance();// 獲取帶參數的構造方法
Constructor<?> paramConstructor = clazz.getConstructor(String.class, int.class);
Person personWithArgs = (Person) paramConstructor.newInstance("Alice", 30);
3. Method類

Method類用于表示類的方法,利用它可以在運行時動態調用方法:

Class<?> clazz = Person.class;
Person person = new Person("Bob", 25);// 獲取方法(參數分別為方法名和參數類型)
Method method = clazz.getMethod("getName");
// 調用方法(參數為實例和傳入參數)
String name = (String) method.invoke(person);// 調用帶參數的方法
Method setAgeMethod = clazz.getMethod("setAge", int.class);
setAgeMethod.invoke(person, 26);
4. Field類

Field類表示類的字段,通過它能在運行時動態訪問和修改字段的值:

Class<?> clazz = Person.class;
Person person = new Person("Charlie", 35);// 獲取字段
Field ageField = clazz.getDeclaredField("age");
// 設置可訪問(若為私有字段)
ageField.setAccessible(true);
// 獲取字段值
int age = (int) ageField.get(person);
// 設置字段值
ageField.set(person, 36);

二、典型應用場景

1. 框架開發

像Spring、Hibernate這類框架,會大量運用反射機制來實現依賴注入、動態代理等功能。例如,Spring通過反射來創建Bean實例:

// Spring框架內部簡化邏輯
Class<?> beanClass = Class.forName(beanClassName);
Constructor<?> constructor = beanClass.getDeclaredConstructor();
Object beanInstance = constructor.newInstance();
2. 單元測試

在單元測試中,反射可用于訪問和測試類的私有方法與字段:

// 測試私有方法
Method privateMethod = TargetClass.class.getDeclaredMethod("privateMethod");
privateMethod.setAccessible(true);
privateMethod.invoke(targetInstance);
3. JSON序列化/反序列化

Jackson、Gson等庫在進行JSON序列化和反序列化時,會利用反射來分析對象的結構:

// Gson庫內部簡化邏輯
Field[] fields = targetClass.getDeclaredFields();
for (Field field : fields) {field.setAccessible(true);String fieldName = field.getName();Object fieldValue = field.get(targetObject);// 序列化為JSON格式
}

三、性能考量

雖然反射功能強大,但它也存在一定的性能開銷,主要體現在以下幾個方面:

  1. 方法調用開銷:反射調用方法的速度比直接調用要慢,大概慢10 - 100倍。
  2. 安全檢查開銷:每次反射操作都需要進行安全檢查,這會消耗額外的系統資源。
  3. JIT優化受限:反射代碼難以被JIT編譯器優化。

為了減少反射帶來的性能影響,可以采取以下優化措施:

  • 緩存反射對象,避免重復獲取。
  • 優先使用MethodHandle(Java 7引入,性能接近直接調用)。
  • 僅在必要的情況下使用反射。

四、安全與訪問控制

1. 安全管理器限制

如果Java應用配置了安全管理器,那么反射操作可能會受到限制,比如無法訪問私有成員等。

2. 打破封裝性

通過setAccessible(true)可以訪問私有成員,這可能會破壞類的封裝性,所以在使用時需要謹慎。

3. 安全風險

反射可能會被用于執行惡意代碼,比如繞過安全檢查等,因此在處理不可信輸入時要格外小心。

五、版本兼容性問題

  • Java 9+的模塊系統:在Java 9及以后的版本中,由于引入了模塊系統,反射訪問可能會受到模塊訪問規則的限制。
  • API變更:部分反射API在新版本中可能會被標記為過時,需要關注官方文檔的更新。

六、最佳實踐建議

  1. 優先使用直接調用:在性能敏感的代碼中,應盡量避免使用反射。
  2. 進行異常處理:反射操作可能會拋出多種異常,如NoSuchMethodExceptionIllegalAccessException等,需要進行妥善處理。
  3. 做好注釋說明:對于使用反射的代碼,要添加清晰的注釋,解釋其必要性。
  4. 進行性能測試:在關鍵代碼中使用反射后,要進行性能測試,評估其影響。

七、示例代碼

下面是一個完整的示例,展示了反射的基本用法:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;class Person {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}private void privateMethod() {System.out.println("This is a private method.");}
}public class ReflectionExample {public static void main(String[] args) throws Exception {// 1. 獲取Class對象Class<?> clazz = Person.class;// 2. 創建實例Constructor<?> constructor = clazz.getConstructor(String.class, int.class);Person person = (Person) constructor.newInstance("David", 40);// 3. 調用方法Method getNameMethod = clazz.getMethod("getName");String name = (String) getNameMethod.invoke(person);System.out.println("Name: " + name);// 4. 訪問私有字段Field ageField = clazz.getDeclaredField("age");ageField.setAccessible(true);int age = (int) ageField.get(person);System.out.println("Age: " + age);// 5. 調用私有方法Method privateMethod = clazz.getDeclaredMethod("privateMethod");privateMethod.setAccessible(true);privateMethod.invoke(person);}
}

通過上述內容,你對Java反射機制應該有了全面的了解。反射是一把雙刃劍,雖然它能提供強大的動態能力,但也存在性能和安全方面的問題,所以在實際開發中要謹慎使用。

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

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

相關文章

操作系統的初步了解

目錄 引言&#xff1a;什么是操作系統&#xff1f; 一、設計操作系統的目的 二、操作系統是做什么的&#xff1a; 操作系統主要有四大核心任務&#xff1a; 1. 管理硬件 2. 運行軟件 3. 存儲數據 4. 提供用戶界面 如何理解操作系統的管理呢&#xff1f; 1. 什么是操作…

Mkdocs頁面如何嵌入PDF

嵌入PDF 嵌入PDF代碼 &#xff0c;注意PDF的相對地址 <iframe src"../個人簡歷.pdf (相對地址)" width"100%" height"800px" style"border: 1px solid #ccc; overflow: auto;"></iframe>我的完整代碼&#xff1a; <d…

鏈表結構深度解析:從單向無頭到雙向循環的實現全指南

上篇博客實現動態順序表時&#xff0c;我們會發現它存在許多弊端&#xff0c;如&#xff1a; ? 中間/頭部的插?刪除&#xff0c;時間復雜度為O(N) ? 增容需要申請新空間&#xff0c;拷?數據&#xff0c;釋放舊空間。會有不?的消耗。 ? 增容?般是呈2倍的增?&#xff0c;…

@PostConstruct @PreDestroy

PostConstruct 是 Java EE&#xff08;現 Jakarta EE&#xff09;中的一個注解&#xff0c;用于標記一個方法在對象初始化完成后立即執行。它在 Spring 框架、Java Web 應用等場景中廣泛使用&#xff0c;主要用于資源初始化、依賴注入完成后的配置等操作。 1. 基本作用 執行時…

【ArcGIS微課1000例】0146:將多個文件夾下的影像移動到一個目標文件夾(以Landscan數據為例)

本文講述將多個文件夾下的影像移動到一個目標文件夾,便于投影變換、裁剪等操作。 文章目錄 一、數據準備二、解壓操作三、批量移動四、查看效果五、ArcGIS操作一、數據準備 全球人口數據集Landscan2000-2023如下所示,每年數據位一個壓縮包: 二、解壓操作 首先將其解壓,方…

專業級 GIF 制作工具深度解析:Gifski 與 GIPHY CAPTURE 的技術對比與實戰指南

《Gifski 與 GIPHY CAPTURE&#xff1a;GIF 制作工具的深度對比與實戰應用》 最近在嘗試做一些培訓文檔&#xff0c;需要使用GIF圖做動態效果&#xff0c;把工具選型過程給大家做一下分享。 先看一張對比表&#xff0c;具體如下&#xff1a; 場景 Windows macOS Linux 移…

selenium替代----playwright

安裝 好處特點&#xff1a;這個東西不像selenium需要固定版本的驅動 pip config set global.index-url https://mirrors.aliyun.com/pypi/simplepip install --upgrade pippip install playwright playwright installplaywright install ffmpeg (處理音視頻的)驗證&#x…

Python代碼編程基礎

字符串 str.[]實現根據下標定位實現對元素的截取 for 循環可以實現遍歷 while 循環可以在實現遍歷的同時實現對某一下標數值的修改 字符串前加 r 可以實現對字符串的完整內容輸出 字符串前加 f 可以實現對字符串內{}中包裹內容的格式化輸出&#xff0c;僅在 v3.6 之后可用…

5月9號.

v-for: v-bind: v-if&v-show: v-model: v-on: Ajax: Axios: async&await: Vue生命周期: Maven: Maven坐標:

Spring 必會之微服務篇(1)

目錄 引入 單體架構 集群和分布式架構 微服務架構 挑戰 Spring Cloud 介紹 實現方案 Spring Cloud Alibaba 引入 單體架構 當我們剛開始學開發的時候&#xff0c;基本都是單體架構&#xff0c;就是把一個項目的所有業務的實現功能都打包在一個 war 包或者 Jar 包中。…

計算機的基本組成

#靈感# 記錄下基礎知識&#xff0c;此處專指計算機硬件方面&#xff0c;捎帶記下芯片知識。 綜述&#xff1a; 計算機硬件的基本組成包括運算器、控制器、存儲器、輸入設備和輸出設備五大部分。其中&#xff0c;集成在一起的運算器和控制器稱為 CPU&#xff08;處理器&#x…

【Python 列表(List)】

Python 中的列表&#xff08;List&#xff09;是最常用、最靈活的有序數據集合&#xff0c;支持動態增刪改查操作。以下是列表的核心知識點&#xff1a; 一、基礎特性 有序性&#xff1a;元素按插入順序存儲可變性&#xff1a;支持增刪改操作允許重復&#xff1a;可存儲重復元…

Qt 的原理及使用(1)——qt的背景及安裝

1. Qt 背景介紹 1.1 什么是 Qt Qt 是?個 跨平臺的 C 圖形??界?應?程序框架 。它為應?程序開發者提供了建?藝術級圖形 界?所需的所有功能。它是完全?向對象的&#xff0c;很容易擴展。Qt 為開發者提供了?種基于組件的開發模 式&#xff0c;開發者可以通過簡單的拖拽…

多分類問題softmax傳遞函數+交叉熵損失

在多分類問題中&#xff0c;Softmax 函數通常與交叉熵損失函數結合使用。 Softmax 函數 Softmax 函數是一種常用的激活函數&#xff0c;主要用于多分類問題中。它將一個實數向量轉換為概率分布&#xff0c;使得每個元素的值在 0 到 1 之間&#xff0c;且所有元素的和為 1。 …

數智讀書筆記系列032《統一星型模型--一種敏捷靈活的數據倉庫和分析設計方法》

引言 在當今數字化時代,數據倉庫作為企業數據管理的核心基礎設施,承擔著整合、存儲和提供企業數據的關鍵角色。隨著商業環境的快速變化和業務需求的日益復雜,數據倉庫的設計方法也在不斷演進,以適應新的挑戰和要求。 背景與意義 數據倉庫領域長期存在著兩種主流方法論之…

RT-Thread 深入系列 Part 1:RT-Thread 全景總覽

摘要&#xff1a; 本文將從 RTOS 演進、RT-Thread 的版本分支、內核架構、核心特性、社區與生態、以及典型產品應用等多維度&#xff0c;全面呈現 RT-Thread 的全景圖。 關鍵詞&#xff1a;RT-Thread、RTOS、微內核、組件化、軟件包管理、SMP 1. RTOS 演進與 RT-Thread 定位 2…

[docker基礎一]docker簡介

目錄 一 消除恐懼 1) 什么是虛擬化&#xff0c;容器化 2)案例 3)為什么需要虛擬化&#xff0c;容器化 二 虛擬化實現方式 1)應用程序執行環境分層 2)虛擬化常見類別 3)常見虛擬化實現 一&#xff09;主機虛擬化(虛擬機)實現 二&#xff09;容器虛擬化實現 一 消除恐…

PostgreSQL 的 pg_advisory_lock 函數

PostgreSQL 的 pg_advisory_lock 函數 pg_advisory_lock 是 PostgreSQL 提供的一種應用級鎖機制&#xff0c;它不鎖定具體的數據庫對象&#xff08;如表或行&#xff09;&#xff0c;而是通過數字鍵值來協調應用間的并發控制。 鎖的基本概念 PostgreSQL 提供兩種咨詢鎖(advi…

SGLang 實戰介紹 (張量并行 / Qwen3 30B MoE 架構部署)

一、技術背景 隨著大語言模型&#xff08;LLM&#xff09;的飛速發展&#xff0c;如何更高效、更靈活地駕馭這些強大的模型生成我們期望的內容&#xff0c;成為了開發者們面臨的重要課題。傳統的通過拼接字符串、管理復雜的狀態和調用 API 的方式&#xff0c;在處理復雜任務時…

微服務中 本地啟動 springboot 無法找到nacos配置 啟動報錯

1. 此處的環境變量需要匹配nacos中yml配置文件名的后綴 對于粗心的小伙伴在切換【測試】【開發】環境的nacos使用時會因為這里導致項目總是無法啟動成功