自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java 的反射、內(nèi)省,你會(huì)用嗎?

開發(fā) 前端
反射是Java語(yǔ)言的一個(gè)特性,允許程序在運(yùn)行時(shí)檢查和操作類、方法、字段等。反射可以動(dòng)態(tài)地獲取類的所有屬性和方法,并且可以動(dòng)態(tài)調(diào)用這些方法。

你好,我是看山。

Java的反射和內(nèi)省是兩個(gè)在運(yùn)行時(shí)操作類和對(duì)象的強(qiáng)大機(jī)制,它們之間存在關(guān)聯(lián)和區(qū)別。很多時(shí)候我們用錯(cuò)了,就會(huì)有性能上的損失。

概念

反射(Reflection)

反射是Java語(yǔ)言的一個(gè)特性,允許程序在運(yùn)行時(shí)檢查和操作類、方法、字段等。反射可以動(dòng)態(tài)地獲取類的所有屬性和方法,并且可以動(dòng)態(tài)調(diào)用這些方法。

反射強(qiáng)調(diào)的是運(yùn)行狀態(tài),即在程序運(yùn)行時(shí)能夠訪問和修改類的狀態(tài)或行為。反射提供了更底層的類結(jié)構(gòu)和行為訪問機(jī)制。

反射的核心類都在java.reflect包下,主要類如下:

圖片圖片

圖片圖片

內(nèi)省(Introspection)

內(nèi)省是基于反射實(shí)現(xiàn)的,主要用于操作符合JavaBean規(guī)范的類。

JavaBean是一種特殊的Java類,通常用于封裝多個(gè)屬性為一個(gè)單一的對(duì)象。

內(nèi)省機(jī)制通過(guò)反射獲取屬性描述器(PropertyDescriptor),然后可以方便地獲取和設(shè)置屬性值。

內(nèi)省操作只針對(duì)JavaBean,只有符合JavaBean規(guī)則的類的成員才可以采用內(nèi)省API進(jìn)行操作。

內(nèi)省的核心類在java.beans包下,主要類如下:

圖片圖片

關(guān)系與區(qū)別

  • 適用范圍:

反射可以操作任何類的所有成員,包括私有成員。

內(nèi)省主要針對(duì)JavaBean,只能操作符合JavaBean規(guī)范的類的成員。

  • 操作方式:
  • 反射是先得到類的字節(jié)碼(Class)后再進(jìn)行各種操作。
  • 內(nèi)省是先得到屬性描述器(PropertyDescriptor)后再進(jìn)行各種操作。
  • 復(fù)雜度:
  • 反射提供了更底層的訪問機(jī)制,使用起來(lái)相對(duì)復(fù)雜。
  • 內(nèi)省提供了一套比較簡(jiǎn)單和有層次的API,更專注于JavaBean的屬性操作。
  • 應(yīng)用場(chǎng)景:
  • 反射適用于需要?jiǎng)討B(tài)獲取和調(diào)用類信息的場(chǎng)景,如框架開發(fā)。
  • 內(nèi)省適用于需要操作JavaBean屬性的場(chǎng)景。

來(lái)點(diǎn)小栗子

使用反射創(chuàng)建對(duì)象并調(diào)用方法

我們通過(guò)反射創(chuàng)建對(duì)象并調(diào)用指定方法:

public static void main(String[] args)
        throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException,
        IllegalAccessException, NoSuchFieldException {
    final Class<?> clazz = MyClass.class;
    // Class<?> clazz = new MyClass().getClass();
    // Class<?> clazz = Class.forName("cn.howardliu.tutorials.core.reflect.ReflectDemo.MyClass");

    final Constructor<?> constructor = clazz.getConstructor();
    // Constructor<?> constructor = clazz.getConstructor(String.class);
    final Object o = constructor.newInstance();

    final Field field = clazz.getDeclaredField("name");
    field.setAccessible(true);
    field.set(o, "看山");

    final Method method = clazz.getMethod("echoName");
    final Object result = method.invoke(o);
    System.out.println(result);
}

@Data
@NoArgsConstructor
@AllArgsConstructor
publicstaticclass MyClass {
    private String name;

    public String echoName() {
        return name;
    }
}

首先,我們獲取class對(duì)象,有三種方式:

  • 通過(guò)類名直接獲?。篊lass<?> clazz = MyClass.class;
  • 通過(guò)實(shí)例獲?。篊lass<?> clazz = new MyClass().getClass();
  • 通過(guò)加載類:Class<?> clazz = Class.forName("cn.howardliu.tutorials.core.reflect.ReflectDemo.MyClass"); 。

然后獲取構(gòu)造器對(duì)象,使用Class對(duì)象的getConstructor()或getDeclaredConstructor()方法獲取構(gòu)造器對(duì)象。

  • 無(wú)參構(gòu)造函數(shù):Constructor<?> constructor = clazz.getConstructor();
  • 有參構(gòu)造函數(shù):Constructor<?> constructor = clazz.getConstructor(String.class); 。

使用newInstance()創(chuàng)建實(shí)體對(duì)象:final Object o = constructor.newInstance();。

示例中我們對(duì)name屬性賦值,首先得獲取Field對(duì)象,可以用getDeclaredField()或者getField()。

因?yàn)閚ame屬性是非public的,調(diào)用setAccessible設(shè)置可訪問,然后賦值。

最后就是獲取Method對(duì)象,使用invoke方法實(shí)現(xiàn)對(duì)象的動(dòng)作。

以上就是反射常用的邏輯了。反射還提供了基于枚舉的API,有需要的時(shí)候可以用一用。

通過(guò)內(nèi)省給對(duì)象賦值

內(nèi)省就是轉(zhuǎn)為JavaBean準(zhǔn)備的,主要包括下面幾個(gè)類:

  1. Introspector類:這是內(nèi)省API的核心類,提供了獲取BeanInfo對(duì)象的方法,例如Introspector.getBeanInfo()方法。
  2. BeanInfo類:這個(gè)類包含了關(guān)于一個(gè)對(duì)象的所有Bean屬性信息,包括屬性的描述符(PropertyDescriptor)。
  3. PropertyDescriptor類:表示一個(gè)JavaBean屬性的信息,包括getter和setter方法。

以下是一個(gè)簡(jiǎn)單的示例,我們首先獲取User的JavaBean信息BeanInfo,然后找到屬性描述符PropertyDescriptor列表。

使用屬性的讀方法獲取數(shù)據(jù),使用寫方法賦值。

public static void main(String[] args)
        throws IntrospectionException, InvocationTargetException, IllegalAccessException {
    final BeanInfo beanInfo = Introspector.getBeanInfo(User.class);
    final User user = new User();

    // 遍歷所有屬性描述符
    for (PropertyDescriptor prop : beanInfo.getPropertyDescriptors()) {
        System.out.println("Property Name: " + prop.getName());

        // 獲取getter方法
        final Method readMethod = prop.getReadMethod();
        if (readMethod != null) {
            Object value = readMethod.invoke(user);
            System.out.println("Property Value: " + value);
        }

        if ("username".equals(prop.getName())) {
            // 獲取setter方法
            final Method writeMethod = prop.getWriteMethod();
            if (writeMethod != null) {
                Object value = writeMethod.invoke(user, "看山");
                System.out.println("Property Value: " + value);
            }
        }
    }
    System.out.println(user);
}

@Data
publicstaticclass User {
    private String username;
}

在JavaBean的操作方面,內(nèi)省確實(shí)比反射更方便。

文末總結(jié)

今天通過(guò)示例介紹了Java的反射和內(nèi)省,下次我們看看在Bean賦值方面,兩者的性能差異有多少。

責(zé)任編輯:武曉燕 來(lái)源: 看山的小屋
相關(guān)推薦

2025-01-10 00:00:00

內(nèi)省機(jī)制JavaBean描述器

2010-03-12 08:55:06

Java內(nèi)省反射

2018-09-29 15:34:34

JavaList接口

2020-06-04 14:15:55

Java中BigDecimal函數(shù)

2025-01-15 00:00:00

Java內(nèi)省性能

2019-07-25 12:46:32

Java高并發(fā)編程語(yǔ)言

2023-11-01 13:48:00

反射java

2021-05-21 12:36:16

限流代碼Java

2024-03-06 08:15:03

@Autowired注入方式Spring

2023-12-01 11:13:50

JavaTreeSet

2021-08-11 10:00:51

緩存MyBatis管理

2021-09-06 10:42:18

Linux命令服務(wù)器

2025-01-03 08:40:53

Java并發(fā)編程Guava庫(kù)

2019-01-28 17:42:33

Python數(shù)據(jù)預(yù)處理數(shù)據(jù)標(biāo)準(zhǔn)化

2021-11-03 17:40:51

Python線程

2022-02-10 09:04:50

架構(gòu)

2024-04-08 00:00:00

asyncawaiPromise

2009-07-14 18:09:08

Jython的內(nèi)省

2011-02-28 09:51:43

內(nèi)省

2018-06-26 10:04:41

Siri語(yǔ)音微信
點(diǎn)贊
收藏

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