最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

圖文詳解Java的反射機(jī)制

 更新時(shí)間:2022年08月16日 10:00:38   作者:世界盡頭與你  
反射就是Reflection,Java的反射是指程序在運(yùn)行期可以拿到一個(gè)對(duì)象的所有信息。反射機(jī)制是框架的靈魂,一個(gè)java程序員不能不會(huì)使用反射,本文就來(lái)和大家一起詳細(xì)聊聊Java的反射機(jī)制

1.什么是反射

反射就是Reflection,Java的反射是指程序在運(yùn)行期可以拿到一個(gè)對(duì)象的所有信息。

加載類后,在堆中就產(chǎn)生了一個(gè)class類型的對(duì)象,這個(gè)對(duì)象包含了類的完整結(jié)構(gòu)的信息,通過(guò)這個(gè)對(duì)象得到類的結(jié)構(gòu)。這個(gè)class對(duì)象就像一面鏡子,透過(guò)這個(gè)鏡子可以看到類的結(jié)構(gòu),所以形象的稱之為“反射”

反射機(jī)制是框架的靈魂,一個(gè)java程序員不能不會(huì)使用反射,沒(méi)有反射機(jī)制,java將一無(wú)是處

2.Hello,java反射

使用實(shí)例:

Cat類:

public class Cat {
    private String name;
    private String age;

    public void hi() {
        System.out.println("喵喵喵~");
    }
}

測(cè)試類:

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

/**
 * 反射入門
 * 通過(guò)字符串形式的類的路徑和方法信息調(diào)用類的方法
 */
public class reflectionTest {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        // 類的路徑
        String classPath = "reflection.Cat";
        // 要執(zhí)行類的方法名稱
        String classMethod = "hi";
        // 加載類
        Class cls = Class.forName(classPath);
        // 通過(guò)cls得到你加載的類Cat的對(duì)象實(shí)例
        Object o = cls.newInstance();
        // 查看o的運(yùn)行類型,為Cat類型
        System.out.println(o.getClass());
        // 得到加載的類的方法對(duì)象
        // 在反射中,可以把方法視為對(duì)象
        Method method = cls.getMethod(classMethod);
        // 通過(guò)method實(shí)例調(diào)用方法:即通過(guò)方法對(duì)象來(lái)實(shí)現(xiàn)調(diào)用方法
        method.invoke(o);
    }
}

輸出:

class reflection.Cat
喵喵喵~

3.java程序運(yùn)行的三個(gè)階段

反射的基本原理:

4.反射相關(guān)類

現(xiàn)在我們來(lái)完善一下上面的測(cè)試類:

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

/**
 * 反射入門
 * 通過(guò)字符串形式的類的路徑和方法信息調(diào)用類的方法
 */
public class reflectionTest {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        // 類的路徑
        String classPath = "reflection.Cat";
        // 要執(zhí)行類的方法名稱
        String classMethod = "hi";
        // 加載類
        Class cls = Class.forName(classPath);
        // 通過(guò)cls得到你加載的類Cat的對(duì)象實(shí)例
        Object o = cls.newInstance();
        // 查看o的運(yùn)行類型,為Cat類型
        System.out.println(o.getClass());
        // 得到加載的類的方法對(duì)象
        // 在反射中,可以把方法視為對(duì)象
        Method method = cls.getMethod(classMethod);
        // 通過(guò)method實(shí)例調(diào)用方法:即通過(guò)方法對(duì)象來(lái)實(shí)現(xiàn)調(diào)用方法
        method.invoke(o);

        // 得到name字段的信息
        // 注意:getField不能得到私有的屬性信息
        Field nameField = cls.getField("name");
        System.out.println(nameField.get(o));

        // 得到構(gòu)造器
        Constructor constructor = cls.getConstructor();
        System.out.println(constructor);
    }
}

輸出:

class reflection.Cat
喵喵喵~
豹貓
public reflection.Cat()

5.反射的優(yōu)化

反射調(diào)用方法的效率比普通方法調(diào)用的效率低很多

在使用反射調(diào)用方法時(shí),可以關(guān)閉安全訪問(wèn)檢測(cè),這樣會(huì)提高反射調(diào)用的效率

例如:下面是一個(gè)實(shí)例:

// 在反射中,可以把方法視為對(duì)象
Method method = cls.getMethod(classMethod);
// 在反射調(diào)用方法時(shí),取消訪問(wèn)檢測(cè)
method.setAccessible(true);
// 通過(guò)method實(shí)例調(diào)用方法:即通過(guò)方法對(duì)象來(lái)實(shí)現(xiàn)調(diào)用方法
method.invoke(o);

6.Class類分析

Class也是類,因此也繼承Object類

Class對(duì)象不是new出來(lái)的,而是系統(tǒng)創(chuàng)建的(通過(guò)loadClass方法)

public Class<?> loadClass(String name) throws ClassNotFoundException {
    return loadClass(name, false);
}

對(duì)于某個(gè)類的Class對(duì)象,在內(nèi)存中只有一份,因?yàn)轭愔患虞d一次

每個(gè)對(duì)象實(shí)例都會(huì)記錄自己是由哪一個(gè)Class實(shí)例生成的

通過(guò)Class對(duì)象可以完整的得到一個(gè)類的結(jié)構(gòu)

Class對(duì)象存在于堆中

類的字節(jié)碼二進(jìn)制數(shù)據(jù)是放在方法區(qū)里面的,有的地方稱為類的元數(shù)據(jù)

Class對(duì)象方法演示:

實(shí)例

Cat類:

public class Cat {
    public String name = "豹貓";
    public String age;

    public void hi() {
        System.out.println("喵喵喵~");
    }

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

ClassMethod類:

import java.lang.reflect.Field;

/**
 * 演示Class類的常用方法
 */
public class ClassMethod {
    public static void main(String[] args) throws Exception {
        String classAllPath = "reflection.Cat";
        // 獲取Cat類對(duì)應(yīng)的Class對(duì)象
        Class<?> aClass = Class.forName(classAllPath);
        // 顯示aClass對(duì)象是哪一個(gè)類的Class對(duì)象
        System.out.println(aClass);
        // 輸出aClass對(duì)象的運(yùn)行類型
        System.out.println(aClass.getClass());
        // 得到包名
        System.out.println(aClass.getPackage().getName());
        // 得到全類名
        System.out.println(aClass.getName());
        // 創(chuàng)建對(duì)象實(shí)例
        Cat cat = (Cat) aClass.newInstance();
        System.out.println(cat);
        // 通過(guò)反射獲取屬性
        Field name = aClass.getField("name");
        System.out.println(name.get(cat));
        // 通過(guò)反射給屬性設(shè)置值
        name.set(cat,"湯圓");
        System.out.println(name.get(cat));
        // 得到所有的屬性
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
    }
}

輸出:

class reflection.Cat
class java.lang.Class
reflection
reflection.Cat
Cat{name='豹貓', age='null'}
豹貓
湯圓
name
age

7.獲取Class對(duì)象的六種方式

獲取Class對(duì)象細(xì)分可以分為六種方式:

現(xiàn)在我們使用代碼進(jìn)行演示:

/**
 * 獲取Class對(duì)象的六種方式
 */
public class GetClass {
    public static void main(String[] args) throws ClassNotFoundException {
        String classAllPath = "reflection.Cat";
        // 1.forName獲取。多用于配置文件讀取類的全路徑,加載類

        // 2.類名.class。多用于參數(shù)傳遞
        System.out.println(String.class);
        System.out.println(Cat.class);

        // 3.對(duì)象.getClass。適用于已經(jīng)存在對(duì)象實(shí)例的情況
        Cat cat = new Cat();
        System.out.println(cat.getClass());

        // 4.通過(guò)類加載器獲取Class對(duì)象
        // (1)得到類加載器
        ClassLoader classLoader = cat.getClass().getClassLoader();
        // (2)通過(guò)類加載器得到Class對(duì)象
        Class<?> cls = classLoader.loadClass(classAllPath);
        System.out.println(cls);

        // 5.基本數(shù)據(jù)類型通過(guò).class獲取Class對(duì)象
        Class<Integer> integerClass = int.class;
        Class<Character> characterClass = char.class;
        Class<Boolean> booleanClass = boolean.class;
        System.out.println(integerClass);

        // 6.基本數(shù)據(jù)類型的包裝類可以通過(guò).TYPE得到Class對(duì)象
        Class<Integer> type = Integer.TYPE;
        System.out.println(type);
    }
}

輸出:

class java.lang.String
class reflection.Cat
class reflection.Cat
class reflection.Cat
int
int

那么,那些類型擁有Class對(duì)象呢?

  • 外部類
  • 接口
  • 數(shù)組(含二維數(shù)組)
  • 注解
  • 枚舉
  • 基本數(shù)據(jù)類型
  • 包裝類
  • 成員內(nèi)部類

8.類加載機(jī)制

動(dòng)態(tài)加載和靜態(tài)加載

靜態(tài)加載:

在編譯時(shí)加載的類,如果沒(méi)有則直接報(bào)錯(cuò),依賴性太強(qiáng)

動(dòng)態(tài)加載:

運(yùn)行時(shí)加載相應(yīng)的類,如果運(yùn)行時(shí)沒(méi)有用到相應(yīng)的類,則不會(huì)進(jìn)行加載,改善了依賴性的問(wèn)題

通過(guò)new創(chuàng)建實(shí)例的方式就是典型的靜態(tài)加載,通過(guò)反射創(chuàng)建對(duì)象是典型的動(dòng)態(tài)加載

類加載時(shí)機(jī):

  • 創(chuàng)建對(duì)象時(shí)
  • 子類被加載
  • 調(diào)用類中的靜態(tài)成員時(shí)
  • 通過(guò)反射(動(dòng)態(tài)加載)

類加載流程概述

類加載的三個(gè)階段:

類加載后的內(nèi)存布局:

整體布局:

加載階段

JVM在該階段的主要目的是將字節(jié)碼從不同的數(shù)據(jù)源轉(zhuǎn)化為二進(jìn)制字節(jié)流加載到內(nèi)存中,并生成一個(gè)代表該類的Class對(duì)象

連接階段

驗(yàn)證:

目的是為了確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求,不會(huì)危害虛擬機(jī)自身的安全

包括:文件格式的驗(yàn)證,元數(shù)據(jù)驗(yàn)證,字節(jié)碼驗(yàn)證,符號(hào)引用驗(yàn)證

準(zhǔn)備:

JVM會(huì)在該階段對(duì)靜態(tài)變量分配內(nèi)存并默認(rèn)初始化(分配默認(rèn)值)。這些變量所使用的內(nèi)存都將在方法區(qū)中進(jìn)行分配

解析:

虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換為直接應(yīng)用的過(guò)程

初始化

<clinit>()方法依次自動(dòng)收集類中的所有靜態(tài)變量的賦值動(dòng)作和靜態(tài)代碼塊中的語(yǔ)句,并進(jìn)行合并

虛擬機(jī)會(huì)保證一個(gè)類的<clinit>()方法在多線程環(huán)境中被正確的加鎖同步,如果多個(gè)線程同時(shí)去初始化一個(gè)類,那么只會(huì)有一個(gè)線程去執(zhí)行這個(gè)類的<clinit>()方法。其他線程都要阻塞等待

9.通過(guò)反射獲取類的結(jié)構(gòu)信息

我們使用一段程序來(lái)演示所有的常用方法:

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

/**
 * 通過(guò)反射獲取類的結(jié)構(gòu)信息
 */
public class ReflectionUtils {
    public static void main(String[] args) throws ClassNotFoundException {
        // 得到Class對(duì)象
        Class<?> personCls = Class.forName("reflection.Person");
        // 得到全類名
        System.out.println(personCls.getName());
        // 得到簡(jiǎn)單類名
        System.out.println(personCls.getSimpleName());
        // 獲取所有的public修飾的屬性,包含父類的
        Field[] fields = personCls.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
        // 獲取本類的所有屬性,不包含父類
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            // 打印屬性名字和等級(jí)和類型
            // 默認(rèn):0,public:1,private:2,protected:4,static:8,final:16
            System.out.println(declaredField.getName() + "\t" +
                    declaredField.getModifiers() + "\t" +
                    declaredField.getType());
        }
        // 獲取所有public方法,包含父類的
        Method[] methods = personCls.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        // 獲取本類的所有方法和等級(jí)和返回類型和參數(shù)類型數(shù)組
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod.getName() + "\t" +
                    declaredMethod.getModifiers() + "\t" +
                    declaredMethod.getReturnType());
            // 獲取方法的參數(shù)類型數(shù)組
            Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println(parameterType);
            }
        }
        // 獲取所有的public構(gòu)造器,不包含父類的
        Constructor<?>[] constructors = personCls.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor.getName());
        }
        // 獲取所有的構(gòu)造器,包含私有的,還有構(gòu)造器的參數(shù)類型
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor.getName());
            Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println(parameterType);
            }
        }
        // 返回包信息
        System.out.println(personCls.getPackage());
        // 以Class形式返回父類的信息
        Class<?> superclass = personCls.getSuperclass();
        System.out.println(superclass);
        // 以Class形式返回接口信息
        Class<?>[] interfaces = personCls.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println(anInterface.getName());
        }
        // 返回注解信息
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
    }
}

interface IA {}

interface IB {}

@Deprecated
class Person extends Something implements IA, IB {
    public String name;
    protected int level;
    private int age;
    String job;

    public Person() {
    }

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

    private Person(String name, int level, int age, String job) {
        this.name = name;
        this.level = level;
        this.age = age;
        this.job = job;
    }

    public void show(String content, int code) {}

    protected void hi() {}

    void say() {}

    private void hei() {}
}

class Something {
    public String hobby;
}

以上就是圖文詳解Java的反射機(jī)制的詳細(xì)內(nèi)容,更多關(guān)于Java反射機(jī)制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • mybatis深入講解resultMap的定義及用法

    mybatis深入講解resultMap的定義及用法

    MyBatis的每一個(gè)查詢映射的返回類型都是ResultMap,當(dāng)我們提供返回類型屬性是resultType時(shí),MyBatis會(huì)自動(dòng)給我們把對(duì)應(yīng)值賦給resultType所指定對(duì)象的屬性,當(dāng)我們提供返回類型是resultMap時(shí),將數(shù)據(jù)庫(kù)中列數(shù)據(jù)復(fù)制到對(duì)象的相應(yīng)屬性上,可以用于復(fù)制查詢,兩者不能同時(shí)用
    2022-04-04
  • java實(shí)現(xiàn)點(diǎn)擊按鈕彈出新窗體功能

    java實(shí)現(xiàn)點(diǎn)擊按鈕彈出新窗體功能

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)點(diǎn)擊按鈕彈出新窗體功能,舊窗體不進(jìn)行操作,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • jdk8?FunctionalInterface注解源碼解讀

    jdk8?FunctionalInterface注解源碼解讀

    這篇文章主要介紹了jdk8?FunctionalInterface注解源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • IDEA搭建純注解版本SpringMVC的web開(kāi)發(fā)環(huán)境全過(guò)程并分析啟動(dòng)原理

    IDEA搭建純注解版本SpringMVC的web開(kāi)發(fā)環(huán)境全過(guò)程并分析啟動(dòng)原理

    本文詳細(xì)介紹了如何使用注解開(kāi)發(fā)搭建Spring Web環(huán)境,包括創(chuàng)建Maven工程、配置web環(huán)境、設(shè)置pom.xml、創(chuàng)建配置類和控制器等步驟,同時(shí),文章還探討了注解開(kāi)發(fā)中如何創(chuàng)建IOC容器和添加DispatcherServlet組件,并通過(guò)Servlet 3.0規(guī)范
    2024-11-11
  • SpringBoot動(dòng)態(tài)生成接口實(shí)現(xiàn)流程示例講解

    SpringBoot動(dòng)態(tài)生成接口實(shí)現(xiàn)流程示例講解

    最近遇到一個(gè)需求,需要在程序運(yùn)行過(guò)程中,可以動(dòng)態(tài)新增接口,自定義接口參數(shù)名稱,基本類型,以及請(qǐng)求方法,請(qǐng)求頭等等。通過(guò)幾天的研究,找到了我需要的解決方案
    2023-01-01
  • Java并發(fā)編程之柵欄(CyclicBarrier)實(shí)例介紹

    Java并發(fā)編程之柵欄(CyclicBarrier)實(shí)例介紹

    這篇文章主要介紹了Java并發(fā)編程之柵欄(CyclicBarrier)實(shí)例介紹,柵欄類似閉鎖,但是它們是有區(qū)別的,需要的朋友可以參考下
    2015-04-04
  • SpringBoot內(nèi)部外部配置文件加載順序解析

    SpringBoot內(nèi)部外部配置文件加載順序解析

    這篇文章主要介紹了SpringBoot內(nèi)部外部配置文件加載順序解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 解決spirngboot連接redis報(bào)錯(cuò):READONLY?You?can‘t?write?against?a?read?only?replica的問(wèn)題

    解決spirngboot連接redis報(bào)錯(cuò):READONLY?You?can‘t?write?against?

    docker部署的redis,springboot基本每天來(lái)連redis都報(bào)錯(cuò):READONLY?You?can't?write?against?a?read?only?replica,重啟redis后,可以正常連接。但是每天都重啟redis,不現(xiàn)實(shí),也很麻煩,今天給大家分享解決方式,感興趣的朋友一起看看吧
    2023-06-06
  • Java元素排序Comparable與Comparator的區(qū)別

    Java元素排序Comparable與Comparator的區(qū)別

    這篇文章主要介紹了Java元素排序Comparable與Comparator的區(qū)別,二者都是頂級(jí)的接口,但擁有的方法和用法是不同的,下面我們分別來(lái)看看具體是怎樣的區(qū)別吧
    2022-05-05
  • Java編寫實(shí)現(xiàn)多人聊天室

    Java編寫實(shí)現(xiàn)多人聊天室

    這篇文章主要為大家詳細(xì)介紹了Java編寫實(shí)現(xiàn)多人聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-09-09

最新評(píng)論

滦南县| 海门市| 清丰县| 山东省| 库尔勒市| 石首市| 紫阳县| 金沙县| 通江县| 柘城县| 天水市| 东台市| 丰台区| 余庆县| 汤原县| 清流县| 和政县| 平乡县| 竹溪县| 城市| 周至县| 马山县| 三亚市| 武功县| 翁源县| 五常市| 蒲江县| 柏乡县| 罗田县| 平顶山市| 广宗县| 睢宁县| 平舆县| 银川市| 凉山| 潮州市| 霍州市| 潼南县| 奉节县| 绥阳县| 格尔木市|