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

java上乘武功入門--反射

 更新時(shí)間:2021年07月19日 08:51:25   作者:二當(dāng)家的白帽子  
反射是Java的一種機(jī)制,一般也叫做反射機(jī)制,本文會(huì)講反射機(jī)制是什么和怎么使用,喜歡的朋友可以觀看一下,希望能給你帶來(lái)幫助

先來(lái)看一段魔法吧

public class Test {
    private static void changeStrValue(String str, char[] value) {
    	// 只要執(zhí)行魔法代碼就可以達(dá)到下面的效果
        // 施展魔法的代碼稍后揭秘
    }
    public static void main(String[] args) {
        changeStrValue("abc", new char[]{'d','e','f'});
        String abc = "abc";
        System.out.println("abc");
        System.out.println(abc);
        System.out.println("abc".equals(abc));
    }
}

在這里插入圖片描述

二當(dāng)家的第一次看到這個(gè)執(zhí)行結(jié)果覺得很有意思。明明應(yīng)該是"abc"怎么就變成了"def"呢?

反射機(jī)制是個(gè)什么玩意兒?

Java的反射(reflection)機(jī)制是指在程序的運(yùn)行狀態(tài)中,可以構(gòu)造任意一個(gè)類的對(duì)象,可以了解任意一個(gè)對(duì)象所屬的類,可以了解任意一個(gè)類的成員變量和方法,可以調(diào)用任意一個(gè)對(duì)象的屬性和方法。這種動(dòng)態(tài)獲取程序信息以及動(dòng)態(tài)調(diào)用對(duì)象的功能稱為Java語(yǔ)言的反射機(jī)制。反射被視為動(dòng)態(tài)語(yǔ)言的關(guān)鍵。

以上就是百科的解釋??赡苡悬c(diǎn)抽象,接著看二當(dāng)家的給你秀起來(lái)解釋一下。

構(gòu)造任意一個(gè)類的對(duì)象

一般情況下,我們?nèi)绻胍獎(jiǎng)?chuàng)建一個(gè)類的對(duì)象,應(yīng)該要用到new關(guān)鍵字。但是像spring這樣的框架,我們只需要配置類名,就可以得到類的實(shí)例。他是怎么做到的呢?

import java.util.List;
public class Test {
    /**
     * 根據(jù)類名取得類實(shí)例
     * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
     * @param className
     * @param <T>
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
     */
    public static <T> T getInstance(String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        Class<T> clazz = (Class<T>) Class.forName(className);
        return clazz.newInstance();
    }
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        List<String> list = getInstance("java.util.ArrayList");
        list.add("abc");
        list.add("def");
        for (String v : list) {
            System.out.println(v);
        }
    }
}

類名可以在程序運(yùn)行中從配置文件獲取,甚至是從網(wǎng)絡(luò)獲取,然后動(dòng)態(tài)創(chuàng)建一個(gè)類的實(shí)例。

了解任意一個(gè)對(duì)象所屬的類

import java.util.ArrayList;
public class Test {
     /**
     * 打印對(duì)象的類名
     * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
     * @param o
     */
    public static void printClass(Object o) {
        System.out.printf(o.getClass().getName());
    }
    public static void main(String[] args) {
        printClass(new ArrayList<>());
    }
}

在這里插入圖片描述

了解任意一個(gè)類的成員變量和方法

我們一般要使用一個(gè)類,先要知道有什么方法和屬性,先了解,后使用。但是像spring那樣的框架為什么可以為我們自動(dòng)注入呢?他怎么知道我們一個(gè)對(duì)象里有什么屬性呢?

import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
    /**
     * 打印類的屬性
     * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
     * @param clazz
     */
    public static void printFields(Class clazz) {
        System.out.println(clazz.getName() + "包含如下屬性:");
        for (Field f : clazz.getDeclaredFields()) {
            System.out.println(f);
        }
    }
    /**
     * 打印類的方法
     * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
     * @param clazz
     */
    public static void printMethods(Class clazz) {
        System.out.println(clazz.getName() + "包含如下方法:");
        for (Method m : clazz.getDeclaredMethods()) {
            System.out.println(m);
        }
    }
    public static void main(String[] args) {
        printFields(MyClass.class);
        printMethods(MyClass.class);
    }
}
class MyClass {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

在這里插入圖片描述

調(diào)用任意一個(gè)對(duì)象的屬性和方法

像spring這樣的框架,即使一個(gè)屬性是私有屬性并且沒有set方法,一樣可以注入。

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
    /**
     * 調(diào)用一個(gè)對(duì)象的方法
     * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
     * @param o
     * @param methodName
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public static void callMethod(Object o, String methodName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method m = o.getClass().getDeclaredMethod(methodName);
        m.setAccessible(true);
        m.invoke(o);
    }
    /**
     * 修改一個(gè)對(duì)象的屬性
     * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
     * @param o
     * @param fieldName
     * @param value
     * @throws IllegalAccessException
     */
    public static void changeFieldValue(Object o, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
        Field f = o.getClass().getDeclaredField(fieldName);
        f.setAccessible(true);
        f.set(o, value);
    }
    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, NoSuchFieldException {
        MyClass o = new MyClass();
        // 修改任意屬性,即使是私有的
        changeFieldValue(o, "name", "二當(dāng)家的白帽子");
        // 調(diào)用任意方法,即使是私有的
        callMethod(o, "printName");
    }
}
class MyClass {
	// 私有屬性,只可以調(diào)用set方法修改
    private String name;
    private void printName() {
        // 私有方法,只有本類自己的實(shí)例可以調(diào)用
        System.out.println("My name is " + name);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

在這里插入圖片描述

魔法揭秘

是時(shí)候揭秘魔法的真面目了,沒錯(cuò),也是利用了反射。

import java.lang.reflect.Field;
public class Test {
    /**
     * 修改字符串內(nèi)部的值
     * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
     * @param str
     * @param value
     */
    private static void changeStrValue(String str, char[] value) {
        try {
            Field f = str.getClass().getDeclaredField("value");
            f.setAccessible(true);
            f.set(str, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        changeStrValue("abc", new char[]{'d','e','f'});
        // 這里的"abc"字符串和上面調(diào)用changeStrValue的參數(shù)"abc"會(huì)指向同一塊內(nèi)存
        String abc = "abc";
        System.out.println("abc");
        System.out.println(abc);
        System.out.println("abc".equals(abc));
    }
}

要理解這段代碼,除了反射機(jī)制還需要了解java對(duì)于字符串的處理。"字符串常量池"已經(jīng)超出本文的范圍,是另一個(gè)話題,本文就不多說(shuō)了。

原本字符串內(nèi)容是"abc",我們正常情況下無(wú)法修改這個(gè)內(nèi)容,因?yàn)镾tring是不變類。但是反射大法卻可以打破一切禁忌。

總結(jié)

一般的程序可能用不到寫反射的代碼。但是像spring這樣的框架,如果沒有反射,我真的想不出如何實(shí)現(xiàn)呢。哪怕永遠(yuǎn)不需要用反射,了解機(jī)制對(duì)我們都有著莫大的好處。

本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • SpringBoot使用自定義注解實(shí)現(xiàn)權(quán)限攔截的示例

    SpringBoot使用自定義注解實(shí)現(xiàn)權(quán)限攔截的示例

    本篇文章主要介紹了SpringBoot使用自定義注解實(shí)現(xiàn)權(quán)限攔截的示例,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-09-09
  • 詳解用Eclipse如何創(chuàng)建Web項(xiàng)目

    詳解用Eclipse如何創(chuàng)建Web項(xiàng)目

    本篇文章主要介紹了詳解用Eclipse如何創(chuàng)建Web項(xiàng)目,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • Java的分片上傳功能的實(shí)現(xiàn)

    Java的分片上傳功能的實(shí)現(xiàn)

    本文主要介紹了Java的分片上傳功能的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • Java簡(jiǎn)單使用EasyExcel操作讀寫excel的步驟與要點(diǎn)

    Java簡(jiǎn)單使用EasyExcel操作讀寫excel的步驟與要點(diǎn)

    相信現(xiàn)在很多搞后端的同學(xué)大部分做的都是后臺(tái)管理系統(tǒng),那么管理系統(tǒng)就肯定免不了Excel的導(dǎo)出導(dǎo)入功能,下面這篇文章主要給大家介紹了關(guān)于Java簡(jiǎn)單使用EasyExcel操作讀寫excel的步驟與要點(diǎn),需要的朋友可以參考下
    2022-09-09
  • SpringBoot的攔截器中依賴注入為null的解決方法

    SpringBoot的攔截器中依賴注入為null的解決方法

    這篇文章主要介紹了SpringBoot的攔截器中依賴注入為null的解決方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-06-06
  • springboot 接口版本區(qū)分方式

    springboot 接口版本區(qū)分方式

    這篇文章主要介紹了springboot 接口版本區(qū)分方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 最新評(píng)論