Carson帶你學(xué)Java:這是一份全面&詳細(xì)的Java反射學(xué)習(xí)指南

前言

  • Java中,反射機(jī)制(Reflection)非常重要,但對(duì)于很多開(kāi)發(fā)者來(lái)說(shuō),這并不容易理解,甚至覺(jué)得有點(diǎn)神秘
  • 今天,我將獻(xiàn)上一份 Java反射機(jī)制的介紹 & 實(shí)戰(zhàn)攻略,希望你們會(huì)喜歡。

目錄

Java反射機(jī)制

1. 簡(jiǎn)介

  • 定義:Java語(yǔ)言中 一種 動(dòng)態(tài)(運(yùn)行時(shí))訪問(wèn)、檢測(cè) & 修改它本身的能力

  • 作用:動(dòng)態(tài)(運(yùn)行時(shí))獲取類的完整結(jié)構(gòu)信息 & 調(diào)用對(duì)象的方法

  1. 類的結(jié)構(gòu)信息包括:變量、方法等
  2. 正常情況下,Java類在編譯前,就已經(jīng)被加載到JVM中;而反射機(jī)制使得程序運(yùn)行時(shí)還可以動(dòng)態(tài)地去操作類的變量、方法等信息

2. 特點(diǎn)

2.1 優(yōu)點(diǎn)

靈活性高。因?yàn)?strong>反射屬于動(dòng)態(tài)編譯,即只有到運(yùn)行時(shí)才動(dòng)態(tài)創(chuàng)建 &獲取對(duì)象實(shí)例。

編譯方式說(shuō)明:

  1. 靜態(tài)編譯:在編譯時(shí)確定類型 & 綁定對(duì)象。如常見(jiàn)的使用new關(guān)鍵字創(chuàng)建對(duì)象
  2. 動(dòng)態(tài)編譯:運(yùn)行時(shí)確定類型 & 綁定對(duì)象。動(dòng)態(tài)編譯體現(xiàn)了Java的靈活性、多態(tài)特性 & 降低類之間的藕合性

2.2 缺點(diǎn)

  • 執(zhí)行效率低
    因?yàn)榉瓷涞牟僮?主要通過(guò)JVM執(zhí)行,所以時(shí)間成本會(huì) 高于 直接執(zhí)行相同操作
  1. 因?yàn)榻涌诘耐ㄓ眯?,Java的invoke方法是傳object和object[]數(shù)組的?;绢愋蛥?shù)需要裝箱和拆箱,產(chǎn)生大量額外的對(duì)象和內(nèi)存開(kāi)銷,頻繁促發(fā)GC。
  2. 編譯器難以對(duì)動(dòng)態(tài)調(diào)用的代碼提前做優(yōu)化,比如方法內(nèi)聯(lián)。
  3. 反射需要按名檢索類和方法,有一定的時(shí)間開(kāi)銷。
  • 容易破壞類結(jié)構(gòu)
    因?yàn)榉瓷洳僮黟堖^(guò)了源碼,容易干擾類原有的內(nèi)部邏輯

3. 應(yīng)用場(chǎng)景

  • 動(dòng)態(tài)獲取 類文件結(jié)構(gòu)信息(如變量、方法等) & 調(diào)用對(duì)象的方法
  • 常用的需求場(chǎng)景有:動(dòng)態(tài)代理、工廠模式優(yōu)化、Java JDBC數(shù)據(jù)庫(kù)操作等

下文會(huì)用實(shí)際例子詳細(xì)講解


4. 具體使用

4.1 Java反射機(jī)制提供的功能

示意圖

4.2 實(shí)現(xiàn)手段

  • 反射機(jī)制的實(shí)現(xiàn) 主要通過(guò) 操作java.lang.Class
  • 下面將主要講解 java.lang.Class
4.2.1 java.lang.Class 類
  • 定義:java.lang.Class類是反射機(jī)制的基礎(chǔ)
  • 作用:存放著對(duì)應(yīng)類型對(duì)象的 運(yùn)行時(shí)信息
  1. Java程序運(yùn)行時(shí),Java虛擬機(jī)為所有類型維護(hù)一個(gè)java.lang.Class對(duì)象
  2. Class對(duì)象存放著所有關(guān)于該對(duì)象的 運(yùn)行時(shí)信息
  3. 泛型形式為Class<T>
  • 每種類型的Class對(duì)象只有1個(gè) = 地址只有1個(gè)
// 對(duì)于2個(gè)String類型對(duì)象,它們的Class對(duì)象相同
Class c1 = "Carson".getClass();
Class c2 =  Class.forName("java.lang.String");
// 用==運(yùn)算符實(shí)現(xiàn)兩個(gè)類對(duì)象地址的比較
System.out.println(c1 ==c2);
// 輸出結(jié)果:true
  • Java反射機(jī)制的實(shí)現(xiàn)除了依靠Java.lang.Class類,還需要依靠:Constructor類、Field類、Method類,分別作用于類的各個(gè)組成部分:
示意圖

4.3 使用步驟

在使用Java反射機(jī)制時(shí),主要步驟包括:

  1. 獲取 目標(biāo)類型的Class對(duì)象
  2. 通過(guò) Class 對(duì)象分別獲取Constructor類對(duì)象、Method類對(duì)象 & Field 類對(duì)象
  3. 通過(guò) Constructor類對(duì)象、Method類對(duì)象 & Field類對(duì)象分別獲取類的構(gòu)造函數(shù)、方法&屬性的具體信息,并進(jìn)行后續(xù)操作

下面,我將詳細(xì)講解每個(gè)步驟中的使用方法。

步驟1:獲取 目標(biāo)類型的Class對(duì)象

// 獲取 目標(biāo)類型的`Class`對(duì)象的方式主要有4種

<-- 方式1:Object.getClass() -->
    // Object類中的getClass()返回一個(gè)Class類型的實(shí)例 
    Boolean carson = true; 
    Class<?> classType = carson.getClass(); 
    System.out.println(classType);
    // 輸出結(jié)果:class java.lang.Boolean  

<-- 方式2:T.class 語(yǔ)法    -->
    // T = 任意Java類型
    Class<?> classType = Boolean.class; 
    System.out.println(classType);
    // 輸出結(jié)果:class java.lang.Boolean  
    // 注:Class對(duì)象表示的是一個(gè)類型,而這個(gè)類型未必一定是類
    // 如,int不是類,但int.class是一個(gè)Class類型的對(duì)象

<-- 方式3:static method Class.forName   -->
    Class<?> classType = Class.forName("java.lang.Boolean"); 
    // 使用時(shí)應(yīng)提供異常處理器
    System.out.println(classType);
    // 輸出結(jié)果:class java.lang.Boolean  

<-- 方式4:TYPE語(yǔ)法  -->

    Class<?> classType = Boolean.TYPE; 
    System.out.println(classType);
    // 輸出結(jié)果:boolean  

此處額外講一下java.lang.reflect.Type

  • java.lang.reflect.TypeJava中所有類型的父接口
  • 這些類型包括:
示意圖
  • 之間的關(guān)系如下
示意圖

步驟2:通過(guò) Class 對(duì)象分別獲取Constructor類對(duì)象、Method類對(duì)象 & Field 類對(duì)象

// 即以下方法都屬于`Class` 類的方法。

<-- 1. 獲取類的構(gòu)造函數(shù)(傳入構(gòu)造函數(shù)的參數(shù)類型)->>
  // a. 獲取指定的構(gòu)造函數(shù) (公共 / 繼承)
  Constructor<T> getConstructor(Class<?>... parameterTypes)
  // b. 獲取所有的構(gòu)造函數(shù)(公共 / 繼承) 
  Constructor<?>[] getConstructors(); 
  // c. 獲取指定的構(gòu)造函數(shù) ( 不包括繼承)
  Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
  // d. 獲取所有的構(gòu)造函數(shù)( 不包括繼承)
  Constructor<?>[] getDeclaredConstructors(); 
// 最終都是獲得一個(gè)Constructor類對(duì)象

// 特別注意:
  // 1. 不帶 "Declared"的方法支持取出包括繼承、公有(Public) & 不包括有(Private)的構(gòu)造函數(shù)
  // 2. 帶 "Declared"的方法是支持取出包括公共(Public)、保護(hù)(Protected)、默認(rèn)(包)訪問(wèn)和私有(Private)的構(gòu)造方法,但不包括繼承的構(gòu)造函數(shù)
  // 下面同理

<--  2. 獲取類的屬性(傳入屬性名) -->
  // a. 獲取指定的屬性(公共 / 繼承)
   Field getField(String name) ;
  // b. 獲取所有的屬性(公共 / 繼承)
   Field[] getFields() ;
  // c. 獲取指定的所有屬性 (不包括繼承)
   Field getDeclaredField(String name) ;
  // d. 獲取所有的所有屬性 (不包括繼承)
   Field[] getDeclaredFields() ;
// 最終都是獲得一個(gè)Field類對(duì)象

<-- 3. 獲取類的方法(傳入方法名 & 參數(shù)類型)-->
  // a. 獲取指定的方法(公共 / 繼承)
    Method getMethod(String name, Class<?>... parameterTypes) ;
  // b. 獲取所有的方法(公共 / 繼承)
   Method[] getMethods() ;
  // c. 獲取指定的方法 ( 不包括繼承)
   Method getDeclaredMethod(String name, Class<?>... parameterTypes) ;
  // d. 獲取所有的方法( 不包括繼承)
   Method[] getDeclaredMethods() ;
// 最終都是獲得一個(gè)Method類對(duì)象

<-- 4. Class類的其他常用方法 -->
getSuperclass(); 
// 返回父類

String getName(); 
// 作用:返回完整的類名(含包名,如java.lang.String ) 
 
Object newInstance(); 
// 作用:快速地創(chuàng)建一個(gè)類的實(shí)例
// 具體過(guò)程:調(diào)用默認(rèn)構(gòu)造器(若該類無(wú)默認(rèn)構(gòu)造器,則拋出異常 
// 注:若需要為構(gòu)造器提供參數(shù)需使用java.lang.reflect.Constructor中的newInstance()

步驟3:通過(guò) Constructor類對(duì)象、Method類對(duì)象 & Field類對(duì)象分別獲取類的構(gòu)造函數(shù)、方法 & 屬性的具體信息 & 進(jìn)行操作

// 即以下方法都分別屬于`Constructor`類、`Method`類 & `Field`類的方法。

<-- 1. 通過(guò)Constructor 類對(duì)象獲取類構(gòu)造函數(shù)信息 -->
  String getName();// 獲取構(gòu)造器名
  Class getDeclaringClass();// 獲取一個(gè)用于描述類中定義的構(gòu)造器的Class對(duì)象
  int getModifiers();// 返回整型數(shù)值,用不同的位開(kāi)關(guān)描述訪問(wèn)修飾符的使用狀況
  Class[] getExceptionTypes();// 獲取描述方法拋出的異常類型的Class對(duì)象數(shù)組
  Class[] getParameterTypes();// 獲取一個(gè)用于描述參數(shù)類型的Class對(duì)象數(shù)組

<-- 2. 通過(guò)Field類對(duì)象獲取類屬性信息 -->
  String getName();// 返回屬性的名稱
  Class getDeclaringClass(); // 獲取屬性類型的Class類型對(duì)象
  Class getType();// 獲取屬性類型的Class類型對(duì)象
  int getModifiers(); // 返回整型數(shù)值,用不同的位開(kāi)關(guān)描述訪問(wèn)修飾符的使用狀況
  Object get(Object obj) ;// 返回指定對(duì)象上 此屬性的值
  void set(Object obj, Object value) // 設(shè)置 指定對(duì)象上此屬性的值為value
 
<-- 3. 通過(guò)Method 類對(duì)象獲取類方法信息 -->
  String getName();// 獲取方法名
  Class getDeclaringClass();// 獲取方法的Class對(duì)象 
  int getModifiers();// 返回整型數(shù)值,用不同的位開(kāi)關(guān)描述訪問(wèn)修飾符的使用狀況
  Class[] getExceptionTypes();// 獲取用于描述方法拋出的異常類型的Class對(duì)象數(shù)組
  Class[] getParameterTypes();// 獲取一個(gè)用于描述參數(shù)類型的Class對(duì)象數(shù)組

<--額外:java.lang.reflect.Modifier類 -->
// 作用:獲取訪問(wèn)修飾符

static String toString(int modifiers)   
// 獲取對(duì)應(yīng)modifiers位設(shè)置的修飾符的字符串表示

static boolean isXXX(int modifiers) 
// 檢測(cè)方法名中對(duì)應(yīng)的修飾符在modifiers中的值

至此,關(guān)于Java反射機(jī)制的步驟說(shuō)明已經(jīng)講解完畢。


4.4 特別注意:訪問(wèn)權(quán)限問(wèn)題

  • 背景
    反射機(jī)制的默認(rèn)行為受限于Java的訪問(wèn)控制

如,無(wú)法訪問(wèn)( private )私有的方法、字段

  • 沖突
    Java安全機(jī)制只允許查看任意對(duì)象有哪些域,而不允許讀它們的值

若強(qiáng)制讀取,將拋出異常

  • 解決方案
    脫離Java程序中安全管理器的控制、屏蔽Java語(yǔ)言的訪問(wèn)檢查,從而脫離訪問(wèn)控制

  • 具體實(shí)現(xiàn)手段:使用Field類、Method類 & Constructor類對(duì)象的setAccessible()

void setAccessible(boolean flag)    
// 作用:為反射對(duì)象設(shè)置可訪問(wèn)標(biāo)志
// 規(guī)則:flag = true時(shí) ,表示已屏蔽Java語(yǔ)言的訪問(wèn)檢查,使得可以訪問(wèn) & 修改對(duì)象的私有屬性

boolean isAccessible()  
// 返回反射對(duì)象的可訪問(wèn)標(biāo)志的值

static void setAccessible(AccessibleObject[] array, boolean flag)   
// 設(shè)置對(duì)象數(shù)組可訪問(wèn)標(biāo)志

5. 實(shí)例應(yīng)用講解

5.1 基礎(chǔ)應(yīng)用講解

實(shí)例1:利用反射獲取類的屬性 & 賦值
<-- 測(cè)試類定義-->
public class Student {

    public Student() {
        System.out.println("創(chuàng)建了一個(gè)Student實(shí)例");
    }
    private String name;
}

<-- 利用反射獲取屬性 & 賦值 -->
        // 1. 獲取Student類的Class對(duì)象
        Class studentClass = Student.class;

        // 2. 通過(guò)Class對(duì)象創(chuàng)建Student類的對(duì)象
        Object mStudent = studentClass.newInstance();
   
        // 3. 通過(guò)Class對(duì)象獲取Student類的name屬性
        Field f = studentClass.getDeclaredField("name");
 
        // 4. 設(shè)置私有訪問(wèn)權(quán)限
        f.setAccessible(true);

        // 5. 對(duì)新創(chuàng)建的Student對(duì)象設(shè)置name值
        f.set(mStudent, "Carson_Ho");

        // 6. 獲取新創(chuàng)建Student對(duì)象的的name屬性 & 輸出
        System.out.println(f.get(mStudent));
  • 測(cè)試結(jié)果
image.png
實(shí)例2:利用反射調(diào)用類的構(gòu)造函數(shù)

<-- 測(cè)試類定義-->

public class Student {

    // 無(wú)參構(gòu)造函數(shù)
    public Student() {
        System.out.println("調(diào)用了無(wú)參構(gòu)造函數(shù)");
    }

    // 有參構(gòu)造函數(shù)
    public Student(String str) {
        System.out.println("調(diào)用了有參構(gòu)造函數(shù)");
    }

    private String name;
}

<-- 利用反射調(diào)用構(gòu)造函數(shù) -->
        // 1. 獲取Student類的Class對(duì)象
        Class studentClass studentClass = Student.class;

        // 2.1 通過(guò)Class對(duì)象獲取Constructor類對(duì)象,從而調(diào)用無(wú)參構(gòu)造方法
        // 注:構(gòu)造函數(shù)的調(diào)用實(shí)際上是在newInstance(),而不是在getConstructor()中調(diào)用
        Object mObj1 = studentClass.getConstructor().newInstance();
      
        // 2.2 通過(guò)Class對(duì)象獲取Constructor類對(duì)象(傳入?yún)?shù)類型),從而調(diào)用有參構(gòu)造方法
        Object mObj2 = studentClass.getConstructor(String.class).newInstance("Carson");
        
  • 測(cè)試結(jié)果
示意圖
實(shí)例3:利用反射調(diào)用類對(duì)象的方法
<-- 測(cè)試類定義-->
public class Student {

    public Student() {
        System.out.println("創(chuàng)建了一個(gè)Student實(shí)例");
    }

    // 無(wú)參數(shù)方法
    public void setName1 (){
        System.out.println("調(diào)用了無(wú)參方法:setName1()");
    }

    // 有參數(shù)方法
    public void setName2 (String str){
        System.out.println("調(diào)用了有參方法setName2(String str):" + str);
    }
}

<-- 利用反射調(diào)用方法 -->
        // 1. 獲取Student類的Class對(duì)象
        Class studentClass = Student.class;

        // 2. 通過(guò)Class對(duì)象創(chuàng)建Student類的對(duì)象
        Object  mStudent = studentClass.newInstance();

        // 3.1 通過(guò)Class對(duì)象獲取方法setName1()的Method對(duì)象:需傳入方法名
        // 因?yàn)樵摲椒?= 無(wú)參,所以不需要傳入?yún)?shù)
        Method  msetName1 = studentClass.getMethod("setName1");

        // 通過(guò)Method對(duì)象調(diào)用setName1():需傳入創(chuàng)建的實(shí)例
        msetName1.invoke(mStudent);

        // 3.2 通過(guò)Class對(duì)象獲取方法setName2()的Method對(duì)象:需傳入方法名 & 參數(shù)類型
        Method msetName2 = studentClass.getMethod("setName2",String.class);

       // 通過(guò)Method對(duì)象調(diào)用setName2():需傳入創(chuàng)建的實(shí)例 & 參數(shù)值
        msetName2.invoke(mStudent,"Carson_Ho");
    

  • 測(cè)試結(jié)果
示意圖

5.2 常見(jiàn)需求場(chǎng)景講解

實(shí)例1:工廠模式優(yōu)化

  • 背景
    采用簡(jiǎn)單工廠模式
  • 沖突
    1. 操作成本高:每增加一個(gè)接口的子類,必須修改工廠類的邏輯
    2. 系統(tǒng)復(fù)雜性提高:每增加一個(gè)接口的子類,都必須向工廠類添加邏輯

關(guān)于 簡(jiǎn)單工廠模式的介紹 & 使用 請(qǐng)看文章:簡(jiǎn)單工廠模式(SimpleFactoryPattern)- 最易懂的設(shè)計(jì)模式解析

  • 解決方案
    采用反射機(jī)制: 通過(guò) 傳入子類名稱 & 動(dòng)態(tài)創(chuàng)建子類實(shí)例,從而使得在增加產(chǎn)品接口子類的情況下,也不需要修改工廠類的邏輯
  • 實(shí)例演示

步驟1. 創(chuàng)建抽象產(chǎn)品類的公共接口

Product.java

abstract class Product{
    public abstract void show();
}

步驟2. 創(chuàng)建具體產(chǎn)品類(繼承抽象產(chǎn)品類),定義生產(chǎn)的具體產(chǎn)品

<-- 具體產(chǎn)品類A:ProductA.java -->
public class  ProductA extends  Product{

    @Override
    public void show() {
        System.out.println("生產(chǎn)出了產(chǎn)品A");
    }
}

<-- 具體產(chǎn)品類B:ProductB.java -->
public class  ProductB extends  Product{

    @Override
    public void show() {
        System.out.println("生產(chǎn)出了產(chǎn)品B");
    }
}


步驟3. 創(chuàng)建工廠類

Factory.java

public class Factory {

    // 定義方法:通過(guò)反射動(dòng)態(tài)創(chuàng)建產(chǎn)品類實(shí)例
    public static Product getInstance(String ClassName) {

        Product concreteProduct = null;

        try {
            
            // 1. 根據(jù) 傳入的產(chǎn)品類名 獲取 產(chǎn)品類類型的Class對(duì)象
            Class product_Class = Class.forName(ClassName);
            // 2. 通過(guò)Class對(duì)象動(dòng)態(tài)創(chuàng)建該產(chǎn)品類的實(shí)例
            concreteProduct = (Product) product_Class.newInstance();

        } catch (Exception e) {
            e.printStackTrace();
        }
        
        // 3. 返回該產(chǎn)品類實(shí)例
        return concreteProduct;
    }
    
}

步驟4:外界通過(guò)調(diào)用工廠類的靜態(tài)方法(反射原理),傳入不同參數(shù)從而創(chuàng)建不同具體產(chǎn)品類的實(shí)例

TestReflect.java

public class TestReflect {
    public static void main(String[] args) throws Exception {

       // 1. 通過(guò)調(diào)用工廠類的靜態(tài)方法(反射原理),從而動(dòng)態(tài)創(chuàng)建產(chǎn)品類實(shí)例
        // 需傳入完整的類名 & 包名
        Product concreteProduct = Factory.getInstance("scut.carson_ho.reflection_factory.ProductA");

        // 2. 調(diào)用該產(chǎn)品類對(duì)象的方法,從而生產(chǎn)產(chǎn)品
        concreteProduct.show();
    }
}
  • 展示結(jié)果
示意圖

如此一來(lái),通過(guò)采用反射機(jī)制(通過(guò) 傳入子類名稱 & 動(dòng)態(tài)創(chuàng)建子類實(shí)例),從而使得在增加產(chǎn)品接口子類的情況下,也不需要修改工廠類的邏輯 & 增加系統(tǒng)復(fù)雜度

實(shí)例2:應(yīng)用了反射機(jī)制的工廠模式再次優(yōu)化

  • 背景
    在上述方案中,通過(guò)調(diào)用工廠類的靜態(tài)方法(反射原理),從而動(dòng)態(tài)創(chuàng)建產(chǎn)品類實(shí)例(該過(guò)程中:需傳入完整的類名 & 包名)

  • 沖突
    開(kāi)發(fā)者 無(wú)法提前預(yù)知 接口中的子類類型 & 完整類名

  • 解決方案
    通過(guò) 屬性文件的形式( Properties 配置所要的子類信息,在使用時(shí)直接讀取屬性配置文件從而獲取子類信息(完整類名)

  • 具體實(shí)現(xiàn)

步驟1:創(chuàng)建抽象產(chǎn)品類的公共接口

Product.java

abstract class Product{
    public abstract void show();
}

步驟2. 創(chuàng)建具體產(chǎn)品類(繼承抽象產(chǎn)品類),定義生產(chǎn)的具體產(chǎn)品

<-- 具體產(chǎn)品類A:ProductA.java -->
public class  ProductA extends  Product{

    @Override
    public void show() {
        System.out.println("生產(chǎn)出了產(chǎn)品A");
    }
}

<-- 具體產(chǎn)品類B:ProductB.java -->
public class  ProductB extends  Product{

    @Override
    public void show() {
        System.out.println("生產(chǎn)出了產(chǎn)品B");
    }
}


步驟3. 創(chuàng)建工廠類

Factory.java

public class Factory {

    // 定義方法:通過(guò)反射動(dòng)態(tài)創(chuàng)建產(chǎn)品類實(shí)例
    public static Product getInstance(String ClassName) {

        Product concreteProduct = null;

        try {
            
            // 1. 根據(jù) 傳入的產(chǎn)品類名 獲取 產(chǎn)品類類型的Class對(duì)象
            Class product_Class = Class.forName(ClassName);
            // 2. 通過(guò)Class對(duì)象動(dòng)態(tài)創(chuàng)建該產(chǎn)品類的實(shí)例
            concreteProduct = (Product) product_Class.newInstance();

        } catch (Exception e) {
            e.printStackTrace();
        }
        
        // 3. 返回該產(chǎn)品類實(shí)例
        return concreteProduct;
    }
    
}

步驟4:創(chuàng)建屬性配置文件
Product.properties

// 寫入抽象產(chǎn)品接口類的子類信息(完整類名)
ProductA = scut.carson_ho.reflection_factory.ProductA
ProductB = scut.carson_ho.reflection_factory.ProductB

步驟5:將屬性配置文件 放到src/main/assets文件夾中

若沒(méi)assets文件夾,則自行創(chuàng)建

步驟6:在動(dòng)態(tài)創(chuàng)建產(chǎn)品類對(duì)象時(shí),動(dòng)態(tài)讀取屬性配置文件從而獲取子類完整類名
TestReflect.java

public class TestReflect {
    public static void main(String[] args) throws Exception {

        // 1. 讀取屬性配置文件
        Properties pro = new Properties() ;
        pro.load(this.getAssets().open("Product.properties"));
            
        // 2. 獲取屬性配置文件中的產(chǎn)品類名
        String Classname = pro.getProperty("ProductA");
        
        // 3. 動(dòng)態(tài)生成產(chǎn)品類實(shí)例
        Product concreteProduct = Factory.getInstance(Classname);

        // 4. 調(diào)用該產(chǎn)品類對(duì)象的方法,從而生產(chǎn)產(chǎn)品
        concreteProduct.show();

}
  • 測(cè)試結(jié)果
示意圖

實(shí)例3:動(dòng)態(tài)代理

通過(guò)反射機(jī)制實(shí)現(xiàn)動(dòng)態(tài)代理,具體請(qǐng)看文章:Carson帶你學(xué)設(shè)計(jì)模式:動(dòng)態(tài)代理模式(Proxy Pattern)


6. 總結(jié)

本文全面講解了Java反射機(jī)制(Reflection)的相關(guān)知識(shí),相信您對(duì)Java反射機(jī)制已經(jīng)非常了解


歡迎關(guān)注Carson_Ho的簡(jiǎn)書(shū)!

分享Android技術(shù)干貨,追求短、平、快,但卻不缺深度


請(qǐng)點(diǎn)贊!因?yàn)槟愕墓膭?lì)是我寫作的最大動(dòng)力!

相關(guān)文章閱讀
Android開(kāi)發(fā):最全面、最易懂的Android屏幕適配解決方案
Android事件分發(fā)機(jī)制詳解:史上最全面、最易懂
Android開(kāi)發(fā):史上最全的Android消息推送解決方案
Android開(kāi)發(fā):最全面、最易懂的Webview詳解
Android開(kāi)發(fā):JSON簡(jiǎn)介及最全面解析方法!
Android四大組件:Service服務(wù)史上最全面解析
Android四大組件:BroadcastReceiver史上最全面解析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容