偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

一文講透 Java 中的反射

開發(fā)
反射機(jī)制的核心是Class對(duì)象,它代表一個(gè)類。Java 虛擬機(jī)(JVM)在加載類時(shí)會(huì)自動(dòng)創(chuàng)建這個(gè)Class對(duì)象。

什么是反射

反射是 Java 中的一個(gè)特性,它允許程序在運(yùn)行時(shí)獲取自身的信息,并動(dòng)態(tài)地操作類或?qū)ο蟮膶傩浴⒎椒ê蜆?gòu)造函數(shù)。通過(guò)反射,我們可以在事先不知道確切類名的情況下實(shí)例化對(duì)象、調(diào)用方法和設(shè)置屬性。

反射機(jī)制的核心是Class對(duì)象,它代表一個(gè)類。Java 虛擬機(jī)(JVM)在加載類時(shí)會(huì)自動(dòng)創(chuàng)建這個(gè)Class對(duì)象。

JVM 如何創(chuàng)建一個(gè)類

當(dāng)我們編寫一個(gè)類并進(jìn)行編譯時(shí),編譯器會(huì)將其轉(zhuǎn)換為存儲(chǔ)在.class文件中的字節(jié)碼。在類加載過(guò)程中,JVM 使用ClassLoader讀取.class文件,將字節(jié)碼加載到內(nèi)存中,并根據(jù)這些信息創(chuàng)建相應(yīng)的Class對(duì)象。由于每個(gè)類在 JVM 中只加載一次,所以每個(gè)類都對(duì)應(yīng)一個(gè)唯一的Class對(duì)象。

示例:

public class User extends People {
    public String name;
    private int age;

    private static int staticFiled = 10;
    private final String sex;
    protected String protectedFiled;

    static {
        System.out.println("靜態(tài)方法執(zhí)行");
    }

    public User(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

    private void privateMethod() {
        System.out.println("我是私有方法");
    }

    public void publicMethod() {
        System.out.println("我是公共方法");
    }
}

public class People {
    public String publicFiled;
    private String privateFiled;
}

獲取Class對(duì)象的三種方式

(1) 第一種方法通過(guò)類名使用.class獲取類對(duì)象。這是在編譯時(shí)完成的,所以明確指定了類型User,不會(huì)導(dǎo)致任何錯(cuò)誤。使用這種方法獲取對(duì)象不會(huì)觸發(fā)類初始化;只有在訪問(wèn)類的靜態(tài)成員或?qū)嵗龝r(shí)才會(huì)進(jìn)行初始化。

Class<User> userClass = User.class;

實(shí)例化一個(gè)對(duì)象:

User userInstance = userClass.getDeclaredConstructor(String.class, String.class).newInstance("張三", "男");

(2) 第二種方法通過(guò)對(duì)象的getClass()方法獲取類對(duì)象。這種方法適用于從已實(shí)例化的類對(duì)象中獲取類對(duì)象。請(qǐng)注意,類型不是User,而是通配符?,因?yàn)镃lass對(duì)象是從User的實(shí)例中獲取的,實(shí)例的具體類型只能在運(yùn)行時(shí)確定,而不是在編譯時(shí)。

User user = new User("張三", "男");
Class<?> userClass = user.getClass();

實(shí)例化一個(gè)對(duì)象:

Constructor<?> constructor = userClass.getConstructor(String.class, String.class);
User userInstance = (User) constructor.newInstance("張三", "男");

(3) 第三種方法使用靜態(tài)方法Class.forName()通過(guò)全路徑獲取類對(duì)象。由于類型只能在運(yùn)行時(shí)知道,所以類型是通配符?。通過(guò)這種方法獲取類對(duì)象將立即觸發(fā)類初始化。

Class<?> userClass = Class.forName("org.example.reflect.entity.User");

創(chuàng)建一個(gè)實(shí)例:

Constructor<?> constructor = userClass.getDeclaredConstructor(String.class, String.class);
User userInstance = (User) constructor.newInstance("張三", "男");

在 Java 中訪問(wèn)對(duì)象字段

獲取所有公共字段要獲取所有公共字段,包括從父類繼承的字段,使用getFields():

Field[] fields = user.getFields();
for (Field field : fields) {
    System.out.println(field);
}

輸出:

public java.lang.String org.example.reflect.entity.User.name
public java.lang.String org.example.reflect.entity.People.publicField

(2) 獲取所有聲明的字段要獲取類中所有聲明的字段,無(wú)論其訪問(wèn)級(jí)別如何,使用getDeclaredFields()。這不包括從超類繼承的字段:

Field[] fields = user.getDeclaredFields();
for (Field field : fields) {
    System.out.println(field);
}

輸出:

public java.lang.String org.example.reflect.entity.User.name
private int org.example.reflect.entity.User.age
private final java.lang.String org.example.reflect.entity.User.sex
protected java.lang.String org.example.reflect.entity.User.protectedField

(3) 獲取超類中的字段要獲取超類中的字段,使用getSuperclass():

Field[] fields = user.getSuperclass().getDeclaredFields();
for (Field field : fields) {
    System.out.println(field);
}

輸出:

public java.lang.String org.example.reflect.entity.People.publicField
private java.lang.String org.example.reflect.entity.People.privateField

(4) 獲取特定字段要通過(guò)名稱獲取特定公共字段,使用getField(String name)。對(duì)于任何特定字段,無(wú)論其訪問(wèn)級(jí)別如何,使用getDeclaredField(String name)。

(5) 處理不存在的字段嘗試訪問(wèn)不存在的字段不會(huì)產(chǎn)生編譯時(shí)錯(cuò)誤,但會(huì)在運(yùn)行時(shí)拋出異常:

try {
    Field nonExistentField = user.getDeclaredField("nonExistentField");
} catch (NoSuchFieldException e) {
    e.printStackTrace();
}

輸出:

java.lang.NoSuchFieldException: nonExistentField

(6) 設(shè)置字段值要設(shè)置私有靜態(tài)字段的值,首先使其可訪問(wèn):

Class<?> userClass = Class.forName("org.example.reflect.entity.User");
Field staticField = userClass.getDeclaredField("staticField");
staticField.setAccessible(true);
System.out.println(staticField.get(null));

如果字段是final的,仍然可以修改它:

Field field = userClass.getDeclaredField("sex");
field.setAccessible(true);
field.set(obj, "女生");
System.out.println(field.get(obj));

輸出:

女生

訪問(wèn)方法

訪問(wèn)方法與訪問(wèn)字段類似:

  • getMethods()檢索類及其超類中的所有公共方法。
  • getDeclaredMethods()檢索類中所有聲明的方法,無(wú)論訪問(wèn)級(jí)別如何。
  • getMethod(String name, Class<?>... parameterTypes)按名稱和參數(shù)類型檢索特定公共方法。
  • getDeclaredMethod(String name, Class<?>... parameterTypes)按名稱和參數(shù)類型檢索特定聲明的方法,無(wú)論訪問(wèn)級(jí)別如何。

總結(jié)

從上面的示例中可以看出,以Declared為前綴的方法(如getDeclaredField)用于檢索所有字段或方法,無(wú)論其訪問(wèn)級(jí)別如何。相比之下,沒有Declared的方法(如getField)僅檢索公共字段或方法。

反射允許繞過(guò)訪問(wèn)控制檢查。用private或final修飾的字段和方法可以被訪問(wèn)和修改,這破壞了封裝性。因此,應(yīng)該謹(jǐn)慎使用。

責(zé)任編輯:趙寧寧 來(lái)源: 程序猿技術(shù)充電站
相關(guān)推薦

2020-03-26 09:18:54

高薪本質(zhì)因素

2024-08-13 17:09:00

架構(gòu)分庫(kù)分表開發(fā)

2020-07-16 09:02:45

aPaaS云計(jì)算aPaaS平臺(tái)

2020-08-04 10:56:09

進(jìn)程線程協(xié)程

2023-11-09 08:41:25

DevOpsAIOps軟件

2021-01-18 13:05:52

Serverless Serverfull FaaS

2020-12-01 11:34:14

Elasticsear

2024-08-07 10:54:59

正則表達(dá)式Java RegexJava

2023-05-04 08:24:52

ChatGPT產(chǎn)品經(jīng)理工業(yè)革命

2024-05-31 13:23:19

OceanBase單機(jī)版架構(gòu)

2020-05-20 09:55:42

Git底層數(shù)據(jù)

2024-07-10 12:00:42

2021-06-29 12:10:00

CRC校驗(yàn)碼C語(yǔ)言

2020-01-02 09:06:23

微服務(wù)數(shù)據(jù)框架

2020-07-16 07:30:15

數(shù)據(jù)庫(kù)SQL技術(shù)

2022-05-15 09:16:28

IPv6IPIP地址

2023-05-11 08:16:13

可視化監(jiān)控工具Kafka

2024-11-07 22:57:30

2022-04-28 10:41:08

SaaS業(yè)務(wù)方式

2025-06-13 08:05:00

DevOps運(yùn)維SRE
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)