亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java上乘武功入門--反射

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

先來看一段魔法吧

public class Test {
    private static void changeStrValue(String str, char[] value) {
    	// 只要執(zhí)行魔法代碼就可以達到下面的效果
        // 施展魔法的代碼稍后揭秘
    }
    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));
    }
}

在這里插入圖片描述

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

反射機制是個什么玩意兒?

Java的反射(reflection)機制是指在程序的運行狀態(tài)中,可以構造任意一個類的對象,可以了解任意一個對象所屬的類,可以了解任意一個類的成員變量和方法,可以調用任意一個對象的屬性和方法。這種動態(tài)獲取程序信息以及動態(tài)調用對象的功能稱為Java語言的反射機制。反射被視為動態(tài)語言的關鍵。

以上就是百科的解釋??赡苡悬c抽象,接著看二當家的給你秀起來解釋一下。

構造任意一個類的對象

一般情況下,我們如果想要創(chuàng)建一個類的對象,應該要用到new關鍵字。但是像spring這樣的框架,我們只需要配置類名,就可以得到類的實例。他是怎么做到的呢?

import java.util.List;
public class Test {
    /**
     * 根據(jù)類名取得類實例
     * @author 二當家的白帽子 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);
        }
    }
}

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

了解任意一個對象所屬的類

import java.util.ArrayList;
public class Test {
     /**
     * 打印對象的類名
     * @author 二當家的白帽子 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<>());
    }
}

在這里插入圖片描述

了解任意一個類的成員變量和方法

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

import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
    /**
     * 打印類的屬性
     * @author 二當家的白帽子 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 二當家的白帽子 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;
    }
}

在這里插入圖片描述

調用任意一個對象的屬性和方法

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

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
    /**
     * 調用一個對象的方法
     * @author 二當家的白帽子 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);
    }
    /**
     * 修改一個對象的屬性
     * @author 二當家的白帽子 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", "二當家的白帽子");
        // 調用任意方法,即使是私有的
        callMethod(o, "printName");
    }
}
class MyClass {
	// 私有屬性,只可以調用set方法修改
    private String name;
    private void printName() {
        // 私有方法,只有本類自己的實例可以調用
        System.out.println("My name is " + name);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

在這里插入圖片描述

魔法揭秘

是時候揭秘魔法的真面目了,沒錯,也是利用了反射。

import java.lang.reflect.Field;
public class Test {
    /**
     * 修改字符串內部的值
     * @author 二當家的白帽子 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"字符串和上面調用changeStrValue的參數(shù)"abc"會指向同一塊內存
        String abc = "abc";
        System.out.println("abc");
        System.out.println(abc);
        System.out.println("abc".equals(abc));
    }
}

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

原本字符串內容是"abc",我們正常情況下無法修改這個內容,因為String是不變類。但是反射大法卻可以打破一切禁忌。

總結

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

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!

相關文章

  • 淺談Arrays.asList() 和ArrayList類型區(qū)別

    淺談Arrays.asList() 和ArrayList類型區(qū)別

    下面小編就為大家?guī)硪黄狝rrays.asList() 和ArrayList類型區(qū)別。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • 優(yōu)化常見的java排序算法

    優(yōu)化常見的java排序算法

    這篇文章主要介紹了Java編程中快速排序算法的實現(xiàn)及相關算法優(yōu)化,快速排序算法的最差時間復雜度為(n^2),最優(yōu)時間復雜度為(n\log n),存在優(yōu)化的空間,需要的朋友可以參考下
    2021-07-07
  • java 中線程等待與通知的實現(xiàn)

    java 中線程等待與通知的實現(xiàn)

    這篇文章主要介紹了java 中線程等待與通知的實現(xiàn)的相關資料,希望通過本文能幫助到大家,讓大家掌握這樣的功能,需要的朋友可以參考下
    2017-09-09
  • 手把手教你用SpringBoot將文件打包成zip存放或導出

    手把手教你用SpringBoot將文件打包成zip存放或導出

    相信各位看官在工作中都會遇到過要把多個文件打包成一個壓縮文件然后導出,或者將文件打包成Zip存放,這就來上代碼,廢話不多說,需要的朋友可以參考下
    2021-06-06
  • SpringBoot使用自定義注解實現(xiàn)權限攔截的示例

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

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

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

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

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

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

    Java簡單使用EasyExcel操作讀寫excel的步驟與要點

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

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

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

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

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

最新評論