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

Java中反射的應(yīng)用

 更新時(shí)間:2023年10月17日 11:14:50   作者:yuhuofei2021  
這篇文章主要介紹了Java中反射的應(yīng)用,通過反射,我們可以在運(yùn)行時(shí)檢查類的屬性、方法和構(gòu)造函數(shù),并且可以在不知道類名的情況下創(chuàng)建對象、調(diào)用方法和訪問屬性,需要的朋友可以參考下

反射的應(yīng)用

1. 獲取運(yùn)行時(shí)類的完整結(jié)構(gòu)

通過反射獲取運(yùn)行時(shí)類的完整結(jié)構(gòu),包括一下所列都是可以獲取的,下面來試試

  • Interface:實(shí)現(xiàn)的全部接口
  • Superclass:所繼承的父類
  • Constructor:全部的構(gòu)造器
  • Method:全部的方法
  • Field:全部的屬性
  • Annotation:注解

新建一個(gè) Person.java 類

package com.javabasic.reflection;

/**
 * @Description
 * @ClassName Person
 * @Author yuhuofei
 * @Date 2022/9/25 16:44
 * @Version 1.0
 */
public class Person {

    private String name;

    private Integer age;

    private String getName() {
        return name;
    }

    private void setName(String name) {
        this.name = name;
    }

    private Integer getAge() {
        return age;
    }

    private void setAge(Integer age) {
        this.age = age;
    }

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

新建 TestReflection.java 類,測試一下通過反射獲取上面這個(gè)類的信息

package com.javabasic.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @Description 反射的應(yīng)用
 * @ClassName TestReflection
 * @Author yuhuofei
 * @Date 2022/10/2 15:57
 * @Version 1.0
 */
public class TestReflection {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class<?> aClass = Class.forName("com.javabasic.reflection.Person");

        System.out.println("==================獲取類名=====================");
        //獲取類的名字
        System.out.println("類名:" + aClass.getSimpleName());
        //獲取包名+類名
        System.out.println("包名及類名:" + aClass.getName());

        System.out.println("==================獲取類的屬性=====================");
        //獲取類的public類型屬性
        Field[] fields1 = aClass.getFields();
        for (Field field : fields1) {
            System.out.println("類的public類型屬性:" + field);
        }
        //獲取類的所有屬性
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            System.out.println("類的所有屬性:" + field);
        }
        //獲取指定的屬性
        Field name = aClass.getDeclaredField("name");
        System.out.println("類的指定屬性:" + name);

        System.out.println("==================獲取類的方法=====================");
        //獲取本類及父類的所有public類型方法
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println("本類及父類的所有public類型方法:" + method);
        }
        //獲取本類及父類的所有方法
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.println("本類父類的所有方法:" + method);
        }
        //獲取指定方法
        Method getName = aClass.getDeclaredMethod("getName", null);
        Method setName = aClass.getDeclaredMethod("setName", String.class);
        System.out.println("獲取指定的getName方法:" + getName);
        System.out.println("獲取指定的setName方法:" + setName);

        System.out.println("==================獲取類的構(gòu)造器=====================");
        //獲取所有public類型構(gòu)造器
        Constructor<?>[] constructors = aClass.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("獲取所有public類型構(gòu)造器:" + constructor);
        }
        //獲取所有構(gòu)造器
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor constructor : declaredConstructors) {
            System.out.println("獲取所有構(gòu)造器:" + constructor);
        }
        //獲取指定的構(gòu)造器
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, Integer.class);
        System.out.println("獲取指定的構(gòu)造器:" + declaredConstructor);
    }
}

結(jié)果如下

在這里插入圖片描述

2. 動(dòng)態(tài)創(chuàng)建對象動(dòng)態(tài)操作方法及屬性

2.1 動(dòng)態(tài)創(chuàng)建對象

通過調(diào)用 Class 對象的 newInstance() 方法,可以創(chuàng)建類的對象

有了類的對象,就可以通過對象.方法名的形式使用方法了,這和平常的使用方式一樣,但需要注意設(shè)置的訪問權(quán)限問題

使用 Class 對象創(chuàng)建類的對象是需要條件的,不同情況下,條件不同

使用無參構(gòu)造器時(shí)的條件

  • 無參構(gòu)造器存在
  • 無參構(gòu)造器的訪問權(quán)限要足夠
        //獲取Class對象
        Class<?> aClass = Class.forName("com.javabasic.reflection.Person");

        //通過一個(gè)無參構(gòu)造器創(chuàng)建一個(gè)Person的對象
        Person person01 = (Person) aClass.newInstance();
        System.out.println(person01);

使用有參構(gòu)造器時(shí)的條件

  • 通過 Class 類的 getDeclaredConstructor(Class<?>… parameterTypes) 獲取當(dāng)前類的指定有參構(gòu)造器
  • 向構(gòu)造器的形參中傳遞一個(gè)對象數(shù)組進(jìn)去,里面要包含構(gòu)造器中所需的各個(gè)參數(shù)
  • 通過 Constructor 實(shí)例化對象
        //獲取Class對象
        Class<?> aClass = Class.forName("com.javabasic.reflection.Person");
        //通過有參構(gòu)造器創(chuàng)建對象
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, Integer.class);
        Person person02 = (Person) declaredConstructor.newInstance("張三", 20);
        System.out.println(person02);

2.2 動(dòng)態(tài)操作方法及屬性

這里延用上面的 Person.java 類,然后新建一個(gè)測試類來測試

package com.javabasic.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @Description
 * @ClassName Test01
 * @Author yuhuofei
 * @Date 2022/10/2 17:08
 * @Version 1.0
 */
public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //獲取Class對象
        Class<?> aClass = Class.forName("com.javabasic.reflection.Person");

        //通過一個(gè)無參構(gòu)造器創(chuàng)建一個(gè)Person的對象
        Person person01 = (Person) aClass.newInstance();
        System.out.println(person01);

        //通過有參構(gòu)造器創(chuàng)建對象
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, Integer.class);
        Person person02 = (Person) declaredConstructor.newInstance("張三", 20);
        System.out.println(person02);

        //通過反射調(diào)用普通方法
        Method method = aClass.getDeclaredMethod("setName", String.class);
        method.setAccessible(true); //關(guān)閉安全檢測,允許訪問private方法
        Person person03 = (Person) aClass.newInstance();
        method.invoke(person03, "李四");   //向person03對象中的setName方法傳參
        System.out.println(person03);

        //通過反射調(diào)用屬性
        Field field01 = aClass.getDeclaredField("name");
        Field field02 = aClass.getDeclaredField("age");
        field01.setAccessible(true); //關(guān)閉安全檢測,允許訪問private屬性
        field02.setAccessible(true);
        Person person04 = (Person) aClass.newInstance();
        field01.set(person04, "王五");    //設(shè)置名字
        field02.set(person04, 19);      //設(shè)置年齡
        System.out.println(person04);
    }
}

值得注意的是,如果方法或者屬性的訪問權(quán)限是 private,那么需要配置 .setAccessible(true);,不然無法訪問

3. 反射操作泛型

java 采用泛型擦除的機(jī)制來引入泛型,但卻只是給編譯器 javac 使用的,用于確保數(shù)據(jù)的安全性和免去強(qiáng)制類型轉(zhuǎn)換的問題,而一旦編譯完成,所有與泛型相關(guān)的類型會(huì)全部擦除

為了通過反射能操作這些類型,java 新增了 ParameterizedType、GenericArrayType、TypeVariable、WildcardType 這幾種類型來代表不能被歸一到 Class 類中的類型但又和原始類型齊名的類型

  • ParameterizedType:表示一種參數(shù)化類型,比如 Collection< String >
  • GenericArrayType:表示一種元素類型是參數(shù)化類型或者類型變量的數(shù)組類型
  • TypeVariable:各種類型變量的公共父接口
  • WildcardType :代表一種通配符類型表達(dá)式

下面寫一個(gè)類來實(shí)踐一下,這里還是延用前面的 Person 類

package com.javabasic.reflection;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
 * @Description 測試反射獲取泛型
 * @ClassName Test02
 * @Author yuhuofei
 * @Date 2022/10/2 20:06
 * @Version 1.0
 */
public class Test02 {

    public void getData(Map<String, Person> map, List<Person> list) {
        System.out.println("getData()");
    }

    public Map<String, Person> getMap() {
        System.out.println("getMap()");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {

        //獲取入?yún)⒎盒?
        Method method = Test02.class.getMethod("getData", Map.class, List.class);
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("泛型:" + genericParameterType);
            //判斷拿到的是不是參數(shù)化類型,即是不是前面定義的Map或者List
            if (genericParameterType instanceof ParameterizedType) {
                //獲取真實(shí)參數(shù)
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }
        }

        System.out.println("============分割線===========");
        //獲取返回值泛型
        method = Test02.class.getMethod("getMap", null);
        Type genericReturnType = method.getGenericReturnType();
        System.out.println("返回值類型:" + genericReturnType);
        if (genericReturnType instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type at : actualTypeArguments) {
                System.out.println(at);
            }
        }
    }

}

得到的結(jié)果如下:

在這里插入圖片描述

4. 反射操作注解

定義一個(gè)注解,如下:

package com.javabasic.annotation;

import java.lang.annotation.*;

/**
 * @Description 自定義注解
 * @InterfaceName MyAnnotation
 * @Author yuhuofei
 * @Date 2022/9/18 11:26
 * @Version 1.0
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

    /**
     * 描述信息
     */
    String value() default "";
}

定義一個(gè)使用上面的注解的類,如下:

package com.javabasic.annotation;

/**
 * @Description 測試自定義注解的使用
 * @ClassName TestAnnotation
 * @Author yuhuofei
 * @Date 2022/9/18 11:32
 * @Version 1.0
 */
@MyAnnotation(value = "打印出兩個(gè)整數(shù)之和,這是標(biāo)記在類上的注解")
public class TestAnnotation {

    @MyAnnotation(value = "打印出兩個(gè)整數(shù)之和,這是標(biāo)記在方法上的注解")
    public static void printResult() {
        int a = 39;
        int b = 54;
        int result = a + b;
        System.out.println(result);
    }

    public static void main(String[] args) {
        printResult();
    }
}

定義一個(gè)測試類,測試通過反射操作注解,如下:

package com.javabasic.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * @Description 測試反射獲得注解
 * @ClassName Test03
 * @Author yuhuofei
 * @Date 2022/10/2 20:36
 * @Version 1.0
 */
public class Test03 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        Class c = Class.forName("com.javabasic.annotation.TestAnnotation");
        //通過反射獲得注解
        Annotation[] annotations = c.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        //獲得注解的value
        MyAnnotation annotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
        String value = annotation.value();
        System.out.println(value);

        //獲得類中方法或者屬性上指定的注解
        System.out.println("============分割線===========");
        Method method = c.getMethod("printResult", null);
        MyAnnotation an = method.getAnnotation(MyAnnotation.class);
        System.out.println(an);
        System.out.println(an.value());
    }
}

運(yùn)行結(jié)果:

在這里插入圖片描述

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

相關(guān)文章

  • Java class文件格式之屬性詳解_動(dòng)力節(jié)點(diǎn)java學(xué)院整理

    Java class文件格式之屬性詳解_動(dòng)力節(jié)點(diǎn)java學(xué)院整理

    這篇文章主要介紹了Java class文件格式之屬性詳解,需要的朋友可以參考下
    2017-06-06
  • Java 內(nèi)省(Introspector)深入理解

    Java 內(nèi)省(Introspector)深入理解

    這篇文章主要介紹了Java 內(nèi)省(Introspector)深入理解的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Java原子操作CAS原理解析

    Java原子操作CAS原理解析

    這篇文章主要介紹了Java原子操作CAS原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • SpringBoot為啥不用配置啟動(dòng)類的實(shí)現(xiàn)

    SpringBoot為啥不用配置啟動(dòng)類的實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot為啥不用配置啟動(dòng)類的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • Spring4下validation數(shù)據(jù)校驗(yàn)無效(maven)的解決

    Spring4下validation數(shù)據(jù)校驗(yàn)無效(maven)的解決

    這篇文章主要介紹了Spring4下validation數(shù)據(jù)校驗(yàn)無效(maven)的解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java調(diào)用opencv實(shí)現(xiàn)圖片矯正功能

    Java調(diào)用opencv實(shí)現(xiàn)圖片矯正功能

    這篇文章主要為大家詳細(xì)介紹了Java如何調(diào)用opencv實(shí)現(xiàn)圖片矯正功能,文中的示例代碼簡潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-09-09
  • Java?正則表達(dá)式URL?匹配與源碼全解析

    Java?正則表達(dá)式URL?匹配與源碼全解析

    在Web應(yīng)用開發(fā)中,我們經(jīng)常需要對URL進(jìn)行格式驗(yàn)證,今天我們結(jié)合?Java?的?Pattern?和?Matcher?類,深入理解正則表達(dá)式在實(shí)際應(yīng)用中的強(qiáng)大功能,并剖析一段實(shí)際的?Java?示例源碼,感興趣的朋友一起看看吧
    2025-04-04
  • Spring boot詳解緩存redis實(shí)現(xiàn)定時(shí)過期方法

    Spring boot詳解緩存redis實(shí)現(xiàn)定時(shí)過期方法

    本篇文章分享的就是spring boot中的一個(gè)輪子,spring cache注解的方式實(shí)現(xiàn)接口數(shù)據(jù)緩存。默認(rèn)的配置想非常簡單,但是有一個(gè)弊端是緩存數(shù)據(jù)為永久緩存,本次將介紹如何設(shè)置接口緩存數(shù)據(jù)的過期時(shí)間
    2022-07-07
  • Java中數(shù)組與集合的相互轉(zhuǎn)換實(shí)現(xiàn)解析

    Java中數(shù)組與集合的相互轉(zhuǎn)換實(shí)現(xiàn)解析

    這篇文章主要介紹了Java中數(shù)組與集合的相互轉(zhuǎn)換實(shí)現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • Java中JSONObject與JSONArray的使用區(qū)別詳解

    Java中JSONObject與JSONArray的使用區(qū)別詳解

    這篇文章主要介紹了Java中JSONObject與JSONArray的使用區(qū)別詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-11-11

最新評論