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

Java基礎(chǔ)之反射詳解

 更新時間:2021年05月12日 10:52:17   作者:福建選手阿俊  
這篇文章主要介紹了教你怎么通過IDEA設(shè)置堆內(nèi)存空間,文中有非常詳細(xì)的代碼示例,對正在使用IDEA的小伙伴們很有幫助喲,需要的朋友可以參考下

前言

反射是我們框架的靈魂,反射也是我們框架的一個底層基石,沒有反射也就沒有框架,如果我們學(xué)好了反射,對我們閱讀框架底層是有很大班助的——阿俊。有些文章上來就講反射,就會很懵逼,不知道是干啥的,所以我們就引出一些問題來看看為什么需要反射

一、一個需求引出反射

看下面的問題
根據(jù)配置文件reflection.properties指定信息,創(chuàng)建People對象并調(diào)用方法hi

classullpath= com.reflection.People
method=hi

思考:使用現(xiàn)有技術(shù),能做嗎?
我們可以來試一試
我們根據(jù)要求創(chuàng)建出兩個類和一個配置文件

在這里插入圖片描述

People 類

public class People {
    private String name="zlj";
    public void hi(){
        System.out.println("hi"+name);
    }
}
classullpath= com.reflection.People
method=hi

在QuestionReflectionQuestion類中進行測試,我們學(xué)Java的時候可知,可以通過如下的方法創(chuàng)建People對象并調(diào)用方法hi

public class QuestionReflectionQuestion {
    public static void main(String[] args) {
            //傳統(tǒng)方式
        People people = new People();
        people.hi();
    }
}

那我們?nèi)绾瓮ㄟ^配置文件reflection.properties指定信息,創(chuàng)建People對象并調(diào)用方法hi呢?

注意:這樣的需求在學(xué)習(xí)框架時特別多,即通過外部文件配置,在不修改源碼情況下,來控制程序,也符合設(shè)計模式的ocp原則(開閉原則:不修改源碼來擴展功能)

嘗試1:Java中有一個Properties類,可以讀寫配置文件,我們可以用它進行嘗試

public class QuestionReflectionQuestion {
    public static void main(String[] args) throws IOException {
        //我們嘗試做一下-》明白反射
        //Java中有一個Properties類,可以讀寫配置文件,我們可以用它進行嘗試
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\reflection.properties"));
        String classullpath = properties.get("classullpath").toString();//classullpath:com.reflection.People
        String method = properties.get("method").toString();//method:hi
        System.out.println("classullpath:"+classullpath);
        System.out.println("method:"+method);
        //那我們可以不可以直接使用new classullpath();來創(chuàng)建呢?這樣顯然不行的
    }
}

結(jié)論:嘗試失敗,我們就可以使用反射機制來解決上述:通過配置文件reflection.properties指定信息,創(chuàng)建People對象并調(diào)用方法hi,下一節(jié)進行代碼演示

二、反射入門

解決第一節(jié)問題的代碼演示

分四個步驟:

1.加載類,返回class類型對象:cls
2.通過cls得到你的加載類com.reflection.People的對象實例
3.通過cls得到你加載的類com.reflection.People的method=hi的方法對象(即:在反射中,可以把方法視為對象(即:萬物皆對象))
4.通過method調(diào)用方法:即通過方法對象來實現(xiàn)調(diào)用方法

public class QuestionReflectionQuestion {
    public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\reflection.properties"));
        String classullpath = properties.get("classullpath").toString();//classullpath:com.reflection.People
        String methodName = properties.get("method").toString();//method:hi
        System.out.println("====使用反射機制解決=====");
        //1:加載類,返回class類型對象:cls
        Class cls = Class.forName(classullpath);
        //2:通過cls得到你的加載類com.reflection.People的對象實例
        Object o = cls.newInstance();
        System.out.println("o的運行類型="+o.getClass());//運行類型
        //3.通過cls得到你加載的類com.reflection.People的method=hi的方法對象
        //即:在反射中,可以把方法視為對象(即:萬物皆對象)
        Method method = cls.getMethod(methodName);
        //4.通過method調(diào)用方法:即通過方法對象來實現(xiàn)調(diào)用方法
        method.invoke(o);//傳統(tǒng)方法:對象.方法()    反射機制 方法.invoke(對象)
    }
}
====使用反射機制解決=====
o的運行類型=class com.reflection.People
hizlj

我們先知道一下反射實現(xiàn)方式的步驟即可,一些類的介紹,我們后續(xù)會進行介紹

如果Java沒有反射機制,Java就不是一種動態(tài)語言,而且我們所說的spring mybatis 框架就都不存在了,反射機制是框架的靈魂,也是底層機制的基石

反射機制的牛之處就在于:可以通過外部文件配置,在不修改源碼的情況下,來控制程序(這就是開閉原則)
比如,我們在People類中新增cry方法,我們就不需要在QuestionReflectionQuestion類中新增 people.cry();這個方法,只需要在配置文件中reflection.properties進行如下修改method=cry即可。

====使用反射機制解決=====
o的運行類型=class com.reflection.People
cryzlj

三、反射原理圖

前面我們對反射進行了一個快速入門,接下來,我們來介紹一下它的原理

反射機制允許程序在執(zhí)行期借助于ReflectionAPI取得任何類的內(nèi)部信息(比如成員變量,構(gòu)造器,成員方法等等),并能操作對象的屬性及方法。反射在設(shè)計模式和框架底層都會用到

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

我們可以拿第一節(jié)的例子,畫圖來說明

在這里插入圖片描述

四、反射相關(guān)類

接下來講完反射機制原理,我們就來看一下反射機制可以做那些事情

1.在運行時判斷任意一個對象所屬的類

2.在運行時構(gòu)造任意一個類的對象

3.在運行時得到任意一個類所具有的成員變量和方法

4.在運行時調(diào)用任意一個對象的成員變量和方法

5.生成動態(tài)代理

反射相關(guān)的主要類:

1.java.lang.Class:代表個類, Class對象表示某 個類加載后在堆中的對象

2.java.lang.reflect.Method:代表類的方法

3.java.lang.reflect.Field: 代表類的成員變量

4.java.lang.reflect.Constructor:代表類的構(gòu)造方法

我們上面第二節(jié)介紹了Method演示,我們接下來進行Field和Constructor演示
People.java

public class People {
    public String name="zlj";
    public People(){
        this.name="zzg";
    }
    public People(String name){
        this.name=name;
    }
    public void hi(){
        System.out.println("hi"+name);
    }
    public void cry(){
        System.out.println("cry"+name);
    }
}

QuestionReflectionQuestion.java

public class QuestionReflectionQuestion {
    public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\reflection.properties"));
        String classullpath = properties.get("classullpath").toString();//classullpath:com.reflection.People
        String methodName = properties.get("method").toString();//method:hi
        String fieldName = properties.get("field").toString();
        String constructorName = properties.get("constructor").toString();
        System.out.println("====使用反射機制解決=====");
        //1:加載類,返回class類型對象:cls
        Class cls = Class.forName(classullpath);
        //2:通過cls得到你的加載類com.reflection.People的對象實例
        Object o = cls.newInstance();
        System.out.println("o的運行類型="+o.getClass());//運行類型
        //3.通過cls得到你加載的類com.reflection.Field 的field=name的字段
        //即:在反射中,可以把方法視為對象(即:萬物皆對象)
        //getField不可以得到私有屬性
        Field field = cls.getField(fieldName);
        //4.通過field 調(diào)用方法:即通過方法對象來實現(xiàn)調(diào)用方法
        //因為對象賦了初始值;所以就是zzg,而不是zlj
        System.out.println(field.get(o));
        System.out.println("People類的字段name是否為zlj:"+field.equals("zlj"));
        //構(gòu)造器的3,4和Field 一樣
        Constructor constructors = cls.getConstructor();//()中可以指定構(gòu)造器參數(shù)類型。默認(rèn)返回?zé)o參構(gòu)造器
        System.out.println(constructors);
        Constructor constructor = cls.getConstructor(String.class);//傳入構(gòu)造參數(shù)的類型對象
        System.out.println(constructor);
    }
}

reflection.properties

classullpath= com.reflection.People
method=cry
field=name
constructor=People

演示

====使用反射機制解決=====
o的運行類型=class com.reflection.People
People類的字段name是否為zlj:false
public com.reflection.People()
public com.reflection.People(java.lang.String)

五、反射調(diào)用優(yōu)化

前面我們說了反射的原理和反射的作用,接下來我們就說一下它的優(yōu)缺點

反射優(yōu)點和缺點

優(yōu)點:可以動態(tài)的創(chuàng)建和使用對象(也是框架底層核心),使用靈活沒有反射機制,框架技術(shù)就失去底層支撐。

缺點:使用反射基本是解釋執(zhí)行,對執(zhí)行速度有影響。

基于缺點,我們可以進行反射調(diào)用優(yōu)化。
我們先看一下傳統(tǒng)方法調(diào)用和反射機制調(diào)用的耗時

public class ReflectionOptimize {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        ReflectionOptimize.m1();
        ReflectionOptimize.m2();
    }
    //傳統(tǒng)方法調(diào)用hi
    public static void m1(){
        People people = new People();
        long start = System.currentTimeMillis();
        for (int i=0;i<900000;i++){
            people.hi();
        }
        long end = System.currentTimeMillis();
        System.out.println("傳統(tǒng)方法調(diào)用hi耗時:"+(end-start));
    }
    //反射機制調(diào)用hi
    public static void m2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class<?> cls = Class.forName("com.reflection.People");
        Object o = cls.newInstance();
       Method method = cls.getMethod("hi");
12       
        long start = System.currentTimeMillis();
        for (int i=0;i<900000;i++){
           method.invoke(o);
        }
        long end = System.currentTimeMillis();
        System.out.println("反射機制調(diào)用hi耗時:"+(end-start));
    }
}
傳統(tǒng)方法調(diào)用hi耗時:4
反射機制調(diào)用hi耗時:19

結(jié)論:使用反射機制調(diào)用方法耗時更長
我們可以進行如下優(yōu)化

反射調(diào)用優(yōu)化關(guān)閉訪問檢查

1.Method和Field、 Constructor對象都有setAccessible()方法

2.setAccessible作用是啟動和禁用訪問安全檢查的開關(guān)

3.參數(shù)值為true表示 反射的對象在使用時取消訪問檢查,提高反射的效率。參數(shù)值為false則表示反射的對象執(zhí)行訪問檢查

在這里插入圖片描述

代碼第12行加入method.setAccessible(true);//反射的對象在使用時取消訪問檢查,提高反射的效率
代碼效果演示

傳統(tǒng)方法調(diào)用hi耗時:3
反射機制調(diào)用hi耗時:16

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

相關(guān)文章

最新評論