Java 反射機制分析指南

森林森發表於2015-03-31

一、JAVA是動態語言嗎?

一般而言,說到動態言,都是指在程式執行時允許改變程式結構或者變數型別,從這個觀點看,JAVA和C++一樣,都不是動態語言。

但JAVA它卻有著一個非常突出的動態相關機制:反射。通過反射,Java可以於執行時載入、探知和使用編譯期間完全求和的類、生成其物件實體,呼叫其方法或者對屬性設值。所以Java算是一個半動態的語言吧。

反射的概念:

在Java中的反射機制是指在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;

對於任意一個物件,都能夠呼叫它的任意一個方法;

這種動態獲取資訊以及動態呼叫物件方法的功能稱為Java語言的反射機制

二、動態性質

2.1、動態性質

  • 執行時生成物件例項;
  • 執行期間呼叫方法;
  • 執行時更改屬性

2.2、Java反射機制能實現的功能

  • 在執行時判斷任意一個物件所屬的類
  • 在執行時構造任意一個類的物件
  • 在執行時判斷任意懷個類所具有的方法和屬性
  • 在執行時呼叫任意一個物件的方法
  • 生成動態代理

2.3、Java反射應用場合

在Java程式中許多物件在執行時都會出現兩種型別:編譯時型別和執行時型別

編譯時的型別由宣告該物件時使用的型別決定,執行時的型別由實際賦給物件的型別決定

如:

Person p =new Student();

編譯時型別為Person,而執行時為Student

除此之外,程式在執行時還可能接收到外部傳入的一個物件,該物件的編譯時型別為Object,但程式又需要呼叫該物件執行時型別的方法。為了這些問題程式需要在執行時發現物件和類的真實資訊。然而,如果編譯時根本無法預知該物件和類可能屬於哪些類,程式只依靠執行時資訊來發現該物件和類的真實資訊,此時就必須使用反射

三、Java反射API

反射API用來生成在當前JAVA虛擬機器中的類、介面或者物件的資訊。

  • Class類:反射的核心類,可以獲取類的屬性,方法等內容資訊。
  • Field類:Java.lang.reflect.表示類的屬性,可以獲取和設定類的中屬性值。
  • Method類:Java.lang.reflect。表示類的方法,它可以用來獲取類中方法的資訊或者執行方法
  • Construcor類:Java.lang.reflect。表示類的構造方法。

四、獲取全部方法和屬性

Person類

package com.pb.Reflect.classinfo;

public class Person {
    private String name;
    private String gender;
    private int age;

    private Person() {
    //
    }
    public Person(String name, String gender, int age) {
        super();
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
    //getter、和setter方法
    private String getName() {
        return name;
    }
    private void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    public String toString(){
        return "姓名:"+name+"年齡: "+age;
    }

}

使用反射:

package com.pb.Reflect.classinfo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import javax.swing.JOptionPane;

/*
 * 通過使用者輸入類的全路徑,來獲取該類的成員方法和屬性
 * Declared獲取全部不管是私有和公有
 * 1.獲取訪問類的Class物件
 * 2.呼叫Class物件的方法返回訪問類的方法和屬性資訊
 */
public class ReflectDemo {

    /*
     * 構造方法
     */
    public ReflectDemo(){
        //使用者輸入類的全路徑徑
        //使用String元件
        String classpsth=JOptionPane.showInputDialog(null,"輸入類的全路徑");
        //使用Class.forName方法根據輸入的類的全路徑 返回該類的Class物件
        try {
            Class cla = Class.forName(classpsth);
            //利用Class物件的cla的自審,返回方法物件集合
            Method [] method=cla.getDeclaredMethods(); //返回所有的方法
            System.out.println("========獲取方法資訊============");
            for (Method meth : method) {
                //遍歷method陣列,並輸出方法資訊
                System.out.println(meth.toString());
            }
            System.out.println("========獲取出方法資訊結束============");
            //獲取屬性利用Class物件的cla的自審,返回成員屬性物件集合
             Field [] field=cla.getDeclaredFields();
                System.out.println("========獲取成員屬性資訊============");
                for (Field f : field) {
                    System.out.println(f.toString());
                }
                System.out.println("========獲取成員屬性資訊結束============");
            //獲取屬性利用Class物件的cla的自審,返回構造方法集合
                Constructor [] constructor=cla.getDeclaredConstructors();
                System.out.println("========獲取成員構造方法資訊============");
                for (Constructor constru : constructor) {
                    System.out.println(constru.toString());
                }
                System.out.println("========獲取成員構造方法資訊結束============");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("路徑輸入錯誤!");
        }
    }

}
package com.pb.Reflect.classinfo;

public class TestReflection {

    public static void main(String[] args) {
        ReflectDemo rd=new ReflectDemo();

    }

}

輸入com.pb.Reflect.classinfo.Person

結果:

========獲取方法資訊============
public java.lang.String com.pb.Reflect.classinfo.Person.getGender()
public void com.pb.Reflect.classinfo.Person.setGender(java.lang.String)
public int com.pb.Reflect.classinfo.Person.getAge()
public void com.pb.Reflect.classinfo.Person.setAge(int)
public java.lang.String com.pb.Reflect.classinfo.Person.toString()
private java.lang.String com.pb.Reflect.classinfo.Person.getName()
private void com.pb.Reflect.classinfo.Person.setName(java.lang.String)
========獲取出方法資訊結束============
========獲取成員屬性資訊============
private java.lang.String com.pb.Reflect.classinfo.Person.name
private java.lang.String com.pb.Reflect.classinfo.Person.gender
private int com.pb.Reflect.classinfo.Person.age
========獲取成員屬性資訊結束============
========獲取構造方法資訊============
private com.pb.Reflect.classinfo.Person()
public com.pb.Reflect.classinfo.Person(java.lang.String,java.lang.String,int)
========獲取構造方法資訊結束============

五、使用反射的步驟

5.1、步驟

Java.lang.reflect

  • 獲得想操作類的Java.lang.Class物件
  • 呼叫Class的方法
  • 使用反射API來操作這些資訊

 

5.2、獲取Class物件方式

  • 呼叫某個物件的getClass()方法
Person p = new Person();
Class cla=p.getClass();
  • 呼叫某個類的class屬性來獲取該類對應的Class物件
Class cls=Person.class;
  • 使用Class類的forName()靜態方法
Class cla=Class.forName(“類的全路徑”);

 六、第二種方式物件的getClass()方法

Person類,因為要宣告物件所以將構造方法public

package com.pb.Reflect.classinfo;

public class Person {
    private String name;
    private String gender;
    private int age;

    public Person() {
    //
    }
    public Person(String name, String gender, int age) {
        super();
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
    //getter、和setter方法
    private String getName() {
        return name;
    }
    private void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    public String toString(){
        return "姓名:"+name+"年齡: "+age;
    }

}

使用反射:

package com.pb.Reflect.classinfo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import javax.swing.JOptionPane;

/*
 * 通過使用者輸入類的全路徑,來獲取該類的成員方法和屬性
 * Declared獲取全部不管是私有和公有
 * 1.獲取訪問類的Class物件
 * 2.呼叫Class物件的方法返回訪問類的方法和屬性資訊
 */

    public ReflectDemo(Person p){
        Class cla=p.getClass();
        //利用Class物件的cla的自審,返回方法物件集合
        Method [] method=cla.getDeclaredMethods(); //返回所有的方法
        System.out.println("========獲取方法資訊============");
        for (Method meth : method) {
            //遍歷method陣列,並輸出方法資訊
            System.out.println(meth.toString());
        }
        System.out.println("========獲取出方法資訊結束============");
        //獲取屬性利用Class物件的cla的自審,返回成員屬性物件集合
         Field [] field=cla.getDeclaredFields();
            System.out.println("========獲取成員屬性資訊============");
            for (Field f : field) {
                System.out.println(f.toString());
            }
            System.out.println("========獲取成員屬性資訊結束============");
        //獲取屬性利用Class物件的cla的自審,返回構造方法集合
            Constructor [] constructor=cla.getDeclaredConstructors();
            System.out.println("========獲取成員構造方法資訊============");
            for (Constructor constru : constructor) {
                System.out.println(constru.toString());
            }
            System.out.println("========獲取成員構造方法資訊結束============");
    }

}

測試類

package com.pb.Reflect.classinfo;

public class TestReflection {

    public static void main(String[] args) {
        Person p=new Person();
        ReflectDemo rd=new ReflectDemo(p);

    }

}
========獲取方法資訊============
public java.lang.String com.pb.Reflect.classinfo.Person.getGender()
public void com.pb.Reflect.classinfo.Person.setGender(java.lang.String)
public int com.pb.Reflect.classinfo.Person.getAge()
public void com.pb.Reflect.classinfo.Person.setAge(int)
public java.lang.String com.pb.Reflect.classinfo.Person.toString()
private java.lang.String com.pb.Reflect.classinfo.Person.getName()
private void com.pb.Reflect.classinfo.Person.setName(java.lang.String)
========獲取出方法資訊結束============
========獲取成員屬性資訊============
private java.lang.String com.pb.Reflect.classinfo.Person.name
private java.lang.String com.pb.Reflect.classinfo.Person.gender
private int com.pb.Reflect.classinfo.Person.age
========獲取成員屬性資訊結束============
========獲取成員構造方法資訊============
public com.pb.Reflect.classinfo.Person()
public com.pb.Reflect.classinfo.Person(java.lang.String,java.lang.String,int)
========獲取成員構造方法資訊結束============

七、第三種方法類的.class屬性

Person類同上

測試類:

package com.pb.Reflect.classinfo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestReflection {

    public static void main(String[] args) {
        /*第二種方法
        Person p=new Person();
        ReflectDemo rd=new ReflectDemo(p);
*/

        /*
         * 第三種方式.class屬性
         */
        Class cla=Person.class;
        //利用Class物件的cla的自審,返回方法物件集合
                Method [] method=cla.getDeclaredMethods(); //返回所有的方法
                System.out.println("========獲取方法資訊============");
                for (Method meth : method) {
                    //遍歷method陣列,並輸出方法資訊
                    System.out.println(meth.toString());
                }
                System.out.println("========獲取出方法資訊結束============");
                //獲取屬性利用Class物件的cla的自審,返回成員屬性物件集合
                 Field [] field=cla.getDeclaredFields();
                    System.out.println("========獲取成員屬性資訊============");
                    for (Field f : field) {
                        System.out.println(f.toString());
                    }
                    System.out.println("========獲取成員屬性資訊結束============");
                //獲取屬性利用Class物件的cla的自審,返回構造方法集合
                    Constructor [] constructor=cla.getDeclaredConstructors();
                    System.out.println("========獲取成員構造方法資訊============");
                    for (Constructor constru : constructor) {
                        System.out.println(constru.toString());
                    }
                    System.out.println("========獲取成員構造方法資訊結束============");
    }

}

結果:

同上

========獲取方法資訊============
public java.lang.String com.pb.Reflect.classinfo.Person.getGender()
public void com.pb.Reflect.classinfo.Person.setGender(java.lang.String)
public int com.pb.Reflect.classinfo.Person.getAge()
public void com.pb.Reflect.classinfo.Person.setAge(int)
public java.lang.String com.pb.Reflect.classinfo.Person.toString()
private java.lang.String com.pb.Reflect.classinfo.Person.getName()
private void com.pb.Reflect.classinfo.Person.setName(java.lang.String)
========獲取出方法資訊結束============
========獲取成員屬性資訊============
private java.lang.String com.pb.Reflect.classinfo.Person.name
private java.lang.String com.pb.Reflect.classinfo.Person.gender
private int com.pb.Reflect.classinfo.Person.age
========獲取成員屬性資訊結束============
========獲取成員構造方法資訊============
public com.pb.Reflect.classinfo.Person()
public com.pb.Reflect.classinfo.Person(java.lang.String,java.lang.String,int)
========獲取成員構造方法資訊結束============

相關文章