欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Java中的Reflection反射和暴力反射

 更新時間:2023年06月16日 11:14:11   作者:魚找水需要時間  
本文主要介紹了詳解Java中的Reflection反射和暴力反射,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1. 反射(Reflection)的概念

1.1 反射的出現(xiàn)背景

Java程序中,所有的對象都有兩種類型:編譯時類型運行時類型,而很多時候?qū)ο蟮木幾g時類型和運行時類型不一致。

例如:

Object obj = new String("hello");
obj.getClass()

如上:某些變量或形參的聲明類型是Object類型,但是程序卻需要調(diào)用該對象運行時類型的方法,該方法不是Object中的方法,那么如何解決呢?

解決這個問題,有兩種方案:

方案1:在編譯和運行時都完全知道類型的具體信息,在這種情況下,我們可以直接先使用instanceof運算符進行判斷,再利用強制類型轉(zhuǎn)換符將其轉(zhuǎn)換成運行時類型的變量即可。

方案2:編譯時根本無法預(yù)知該對象和類的真實信息,程序只能依靠運行時信息來發(fā)現(xiàn)該對象和類的真實信息,這就必須使用反射

1.2 反射概述

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

加載完類之后,在堆內(nèi)存的方法區(qū)中就產(chǎn)生了一個Class類型的對象(一個類只有一個Class對象),這個對象就包含了完整的類的結(jié)構(gòu)信息。此時就可以通過這個對象看到類的結(jié)構(gòu)。這個對象就像一面鏡子,透過這個鏡子看到類的結(jié)構(gòu),所以,我們形象的稱之為:反射。

從內(nèi)存加載上看反射:

1.3 Java反射機制研究及應(yīng)用

Java反射機制提供的功能:

  • 在運行時判斷任意一個對象所屬的類
  • 在運行時構(gòu)造任意一個類的對象
  • 在運行時判斷任意一個類所具有的成員變量和方法
  • 在運行時獲取泛型信息
  • 在運行時調(diào)用任意一個對象的成員變量和方法
  • 在運行時處理注解
  • 生成動態(tài)代理

1.4 反射相關(guān)的主要API

java.lang.Class:代表一個類
java.lang.reflect.Method:代表類的方法
java.lang.reflect.Field:代表類的成員變量
java.lang.reflect.Constructor:代表類的構(gòu)造器
......

1.5 反射的優(yōu)缺點

優(yōu)點:

  • 提高了Java程序的靈活性和擴展性,降低了耦合性,提高自適應(yīng)能力
  • 允許程序創(chuàng)建和控制任何類的對象,無需提前硬編碼目標(biāo)類

缺點:

  • 反射的性能較低。
    • 反射機制主要應(yīng)用在對靈活性和擴展性要求很高的系統(tǒng)框架上
  • 反射會模糊程序內(nèi)部邏輯,可讀性較差。

2. Class類并獲取Class實例

要想解剖一個類,必須先要獲取到該類的Class對象。而剖析一個類或用反射解決具體的問題就是使用相關(guān)API:

java.lang.Classjava.lang.reflect.*

所以,Class對象是反射的根源。

2.1 理解Class

2.1.1 理論上

在Object類中定義了以下的方法,此方法將被所有子類繼承

public final Class getClass()

以上的方法返回值的類型是一個Class類,此類是Java反射的源頭,實際上所謂反射從程序的運行結(jié)果來看也很好理解,即:可以通過對象反射求出類的名稱。

對象照鏡子后可以得到的信息:某個類的屬性、方法和構(gòu)造器、某個類到底實現(xiàn)了哪些接口。對于每個類而言,JRE 都為其保留一個不變的 Class 類型的對象。一個 Class 對象包含了特定某個結(jié)構(gòu)(class/interface/enum/annotation/primitive type/void/[])的有關(guān)信息。

  • Class本身也是一個類
  • Class 對象只能由系統(tǒng)建立對象
  • 一個加載的類在 JVM 中只會有一個Class實例
  • 一個Class對象對應(yīng)的是一個加載到JVM中的一個.class文件
  • 每個類的實例都會記得自己是由哪個 Class 實例所生成
  • 通過Class可以完整地得到一個類中的所有被加載的結(jié)構(gòu)
  • Class類是Reflection的根源,針對任何你想動態(tài)加載、運行的類,唯有先獲得相應(yīng)的Class對象

2.1.2 內(nèi)存結(jié)構(gòu)上

說明:上圖中字符串常量池在JDK6中存儲在方法區(qū);JDK7及以后,存儲在堆空間。

2.2 獲取Class類的實例(四種方法)

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

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

實例:

Class clazz = String.class;

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

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

實例:

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

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

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

實例:

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

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

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

實例:

ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 = cl.loadClass("類的全類名");

再舉例:

public class GetClassObject {
    @Test
    public void test01() throws ClassNotFoundException{
        Class c1 = GetClassObject.class;
        GetClassObject obj = new GetClassObject();
        Class c2 = obj.getClass();
        Class c3 = Class.forName("com.example.classtype.GetClassObject");
        Class c4 = ClassLoader.getSystemClassLoader().loadClass("com.example.classtype.GetClassObject");
        System.out.println("c1 = " + c1);
        System.out.println("c2 = " + c2);
        System.out.println("c3 = " + c3);
        System.out.println("c4 = " + c4);
        System.out.println(c1 == c2);
        System.out.println(c1 == c3);
        System.out.println(c1 == c4);
    }
}

2.3 哪些類型可以有Class對象

簡而言之,所有Java類型!

(1)class:外部類,成員(成員內(nèi)部類,靜態(tài)內(nèi)部類),局部內(nèi)部類,匿名內(nèi)部類
(2)interface:接口
(3)[]:數(shù)組
(4)enum:枚舉
(5)annotation:注解@interface
(6)primitive type:基本數(shù)據(jù)類型
(7)void

舉例:

Class c1 = Object.class;
Class c2 = Comparable.class;
Class c3 = String[].class;
Class c4 = int[][].class;
Class c5 = ElementType.class;
Class c6 = Override.class;
Class c7 = int.class;
Class c8 = void.class;
Class c9 = Class.class;
int[] a = new int[10];
int[] b = new int[100];
Class c10 = a.getClass();
Class c11 = b.getClass();
// 只要元素類型與維度一樣,就是同一個Class
System.out.println(c10 == c11);

2.4 Class類的常用方法

方法名功能說明
static Class forName(String name)返回指定類名 nameClass 對象
Object newInstance()調(diào)用缺省構(gòu)造函數(shù),返回該Class對象的一個實例
getName()返回此Class對象所表示的實體(類、接口、數(shù)組類、基本類型或void)名稱
Class getSuperClass()返回當(dāng)前Class對象的父類的Class對象
Class [] getInterfaces()獲取當(dāng)前Class對象的接口
ClassLoader getClassLoader()返回該類的類加載器
Class getSuperclass()返回表示此Class所表示的實體的超類的Class
Constructor[] getConstructors()返回一個包含某些Constructor對象的數(shù)組
Field[] getDeclaredFields()返回Field對象的一個數(shù)組
Method getMethod(String name,Class … paramTypes)返回一個Method對象,此對象的形參類型為paramType

舉例:

String str = "test4.Person";
Class clazz = Class.forName(str);
Object obj = clazz.newInstance();
Field field = clazz.getField("name");
field.set(obj, "Peter");
Object name = field.get(obj);
System.out.println(name);
//注:test4.Person是test4包下的Person類

到此這篇關(guān)于詳解Java中的Reflection反射和暴力反射的文章就介紹到這了,更多相關(guān)Java Reflection反射和暴力反射內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中過濾器 (Filter) 和 攔截器 (Interceptor)的使用

    Java中過濾器 (Filter) 和 攔截器 (Interceptor)的使用

    這篇文章主要介紹了Java中過濾器 (Filter) 和 攔截器 (Interceptor)的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • mybatis-plus批量插入優(yōu)化方式

    mybatis-plus批量插入優(yōu)化方式

    MyBatis-Plus的saveBatch()方法默認是單條插入,通過在JDBC URL添加rewriteBatchedStatements=true參數(shù)啟用批量插入,官方提供的sql注入器可自定義方法,如InsertBatchSomeColumn實現(xiàn)真批量插入,但存在單次插入數(shù)據(jù)量過大問題,可通過分批插入優(yōu)化,避免超出MySQL限制
    2024-09-09
  • java8 stream的多字段排序?qū)崿F(xiàn)(踩坑)

    java8 stream的多字段排序?qū)崿F(xiàn)(踩坑)

    這篇文章主要介紹了java8 stream的多字段排序?qū)崿F(xiàn)(踩坑),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • jenkins如何通過pipeline部署springboot項目

    jenkins如何通過pipeline部署springboot項目

    為了提高SpringBoot項目的部署效率和規(guī)范性,建議將項目代碼和部署腳本分離,項目代碼倉庫專注業(yè)務(wù)邏輯,構(gòu)建為jar包;另外設(shè)立獨立代碼倉庫存放Jenkinsfile等部署配置文件,在Jenkins中配置pipeline,自動拉取項目代碼進行構(gòu)建和部署
    2024-09-09
  • JavaWeb三大組件之Filter過濾器詳解

    JavaWeb三大組件之Filter過濾器詳解

    這篇文章主要介紹了JavaWeb三大組件之Filter過濾器詳解,過濾器Filter是Java?Web應(yīng)用中的一種組件,它在請求到達Servlet或JSP之前或者響應(yīng)送回客戶端之前,對請求和響應(yīng)進行預(yù)處理和后處理操作,需要的朋友可以參考下
    2023-10-10
  • Java中調(diào)用Python的實現(xiàn)示例

    Java中調(diào)用Python的實現(xiàn)示例

    本文主要介紹了Java中調(diào)用Python的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • 使用lombok注解導(dǎo)致mybatis-plus TypeHandler失效的解決

    使用lombok注解導(dǎo)致mybatis-plus TypeHandler失效的解決

    這篇文章主要介紹了使用lombok注解導(dǎo)致mybatis-plus TypeHandler失效的解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • java實現(xiàn)讀取txt文件中的內(nèi)容

    java實現(xiàn)讀取txt文件中的內(nèi)容

    本文通過一個具體的例子向大家展示了如何使用java實現(xiàn)讀取TXT文件里的內(nèi)容的方法以及思路,有需要的小伙伴可以參考下
    2016-03-03
  • Java漢字轉(zhuǎn)拼音pinyin4j用法詳解

    Java漢字轉(zhuǎn)拼音pinyin4j用法詳解

    這篇文章主要介紹了Java漢字轉(zhuǎn)拼音pinyin4j用法詳解,需要的朋友可以參考下
    2020-02-02
  • java 二分法詳解幾種實現(xiàn)方法

    java 二分法詳解幾種實現(xiàn)方法

    這篇文章主要介紹了java 二分法詳解幾種方法的相關(guān)資料,需要的朋友可以參考下
    2017-02-02

最新評論