天天看點

一步一步學JAVA(18)-反射技術

反射技術:其實就是動态加載一個指定的類,并擷取該類中的所有的内容。而且将位元組碼檔案封裝成對象,并将位元組碼檔案中的内容都封裝成對象,這樣便于操作這些成員。簡單說:反射技術可以對一個類進行解剖。

反射的好處:大大的增強了程式的擴充性。

反射的基本步驟:

  1. 獲得Class 對象,就是擷取到指定的名稱的位元組碼檔案對象。
  2. 執行個體化對象,獲得類的屬性、方法或構造函數。
  3. 通路屬性、調用方法、調用構造函數建立對象。

擷取這個Class 對象,有三種方式:

  1. 通過每個對象都具備的方法getClass 來擷取。弊端:必須要建立該類對象,才可以調用getClass 方法。
  2. 每一個資料類型(基本資料類型和引用資料類型)都有一個靜态的屬性class。弊端:必須要先明确該類。
  3. 3:使用的Class 類中的方法,靜态的forName 方法。

前兩種方式不利于程式的擴充,因為都需要在程式使用具體的類來完成。

指定什麼類名,就擷取什麼類位元組碼檔案對象,這種方式的擴充性最強,隻要将類名的字元串傳入即可。

// 1. 根據給定的類名來獲得 用于類加載
String classname = "cn.itcast.reflect.Person";// 來自配置檔案
Class clazz = Class.forName(classname);// 此對象代表Person.class
// 2. 如果拿到了對象,不知道是什麼類型 用于獲得對象的類型
Object obj = new Person();
Class clazz1 = obj.getClass();// 獲得對象具體的類型
// 3. 如果是明确地獲得某個類的Class 對象 主要用于傳參
Class clazz2 = Person.class;
           

反射的用法:

1)、需要獲得java 類的各個組成部分,首先需要獲得類的Class 對象,獲得Class 對象的三種方式:

Class.forName(classname) 用于做類加載

obj.getClass() 用于獲得對象的類型

類名.class 用于獲得指定的類型,傳參用

2)、反射類的成員方法:

Class clazz = Person.class;

Method method = clazz.getMethod(methodName, new Class[]{paramClazz1, paramClazz2});

method.invoke();

3)、反射類的構造函數:

Constructor con = clazz.getConstructor(new Class[]{paramClazz1, paramClazz2,...})

con.newInstance(params...)

4)、反射類的屬性:

Field field = clazz.getField(fieldName);

field.setAccessible(true);

field.setObject(value);

擷取了位元組碼檔案對象後,最終都需要建立指定類的對象:

建立對象的兩種方式(其實就是對象在進行執行個體化時的初始化方式):

1,調用空參數的構造函數:使用了Class 類中的newInstance()方法。

2,調用帶參數的構造函數:先要擷取指定參數清單的構造函數對象,然後通過該構造函數的對象的newInstance(實際參數) 進行對象的初始化。

綜上所述,第二種方式,必須要先明确具體的構造函數的參數類型,不便于擴充。是以一般情況下,被反射的類,内部通常都會提供一個公有的空參數的構造函數。

// 如何生成擷取到位元組碼檔案對象的執行個體對象。
Class clazz = Class.forName("cn.itcast.bean.Person");//類加載
// 直接獲得指定的類型
clazz = Person.class;
// 根據對象獲得類型
Object obj = new Person("zhangsan", 19);
clazz = obj.getClass();
Object obj = clazz.newInstance();//該執行個體化對象的方法調用就是指定類中的空參數構造函數,給建立對象進行初始化。當指定類中沒有空參數構造函數時,該如何建立該類對象呢?請看method_2();
public static void method_2() throws Exception {
    Class clazz = Class.forName("cn.itcast.bean.Person");
    //既然類中沒有空參數的構造函數,那麼隻有擷取指定參數的構造函數,用該函數來進行執行個體化。
    //擷取一個帶參數的構造器。
    Constructor constructor = clazz.getConstructor(String.class,int.class);
    //想要對對象進行初始化,使用構造器的方法newInstance();
    Object obj = constructor.newInstance("zhagnsan",30);
    //擷取所有構造器。
    Constructor[] constructors = clazz.getConstructors();//隻包含公共的
    constructors = clazz.getDeclaredConstructors();//包含私有的
    for(Constructor con : constructors) {
        System.out.println(con);
    }
}
           

反射指定類中的方法:

//擷取類中所有的方法。
public static void method_1() throws Exception {
    Class clazz = Class.forName("cn.itcast.bean.Person");
    Method[] methods = clazz.getMethods();//擷取的是該類中的公有方法和父類中的公有方法。
    methods = clazz.getDeclaredMethods();//擷取本類中的方法,包含私有方法。
    for(Method method : methods) {
        System.out.println(method);
    }
}
//擷取指定方法;
public static void method_2() throws Exception {
    Class clazz = Class.forName("cn.itcast.bean.Person");
    //擷取指定名稱的方法。
    Method method = clazz.getMethod("show", int.class,String.class);
    //想要運作指定方法,當然是方法對象最清楚,為了讓方法運作,調用方法對象的invoke 方法即可,
    但是方法運作必須要明确所屬的對象和具體的實際參數。
    Object obj = clazz.newInstance();
    method.invoke(obj, 39,"hehehe");//執行一個方法
}
//想要運作私有方法。
public static void method_3() throws Exception {
    Class clazz = Class.forName("cn.itcast.bean.Person");
    //想要擷取私有方法。必須用getDeclearMethod();
    Method method = clazz.getDeclaredMethod("method", null);
    // 私有方法不能直接通路,因為權限不夠。非要通路,可以通過暴力的方式。
    method.setAccessible(true);//一般很少用,因為私有就是隐藏起來,是以盡量不要通路。
}
//反射靜态方法。
public static void method_4() throws Exception {
    Class clazz = Class.forName("cn.itcast.bean.Person");
    Method method = clazz.getMethod("function",null);
    method.invoke(null,null);
}
           
  • 一步一步學JAVA(1)-初識java
  • 一步一步學JAVA(2)-JDK的配置
  • 一步一步學JAVA(3)-javac與java 指令
  • 一步一步學JAVA(4)-文法基礎
  • 一步一步學JAVA(5)-面向對象
  • 一步一步學JAVA(6)-封裝
  • 一步一步學JAVA(7)-繼承
  • 一步一步學JAVA(8)-多态
  • 一步一步學JAVA(9)-設計模式
  • 一步一步學JAVA(10)-接口
  • 一步一步學JAVA(11)-異常
  • 一步一步學JAVA(12)-多線程
  • 一步一步學JAVA(13)-同步
  • 一步一步學JAVA(14)-集合架構
  • 一步一步學JAVA(15)-API
  • 一步一步學JAVA(16)-IO流
  • 一步一步學JAVA(17)-網絡程式設計
  • 一步一步學JAVA(18)-反射技術
  • 一步一步學JAVA(19)-正規表達式