Java反射機制

Java反射機制

前言

什麼是反射機制

反射是java語言的一個特性,它允程序在運行時(注意不是編譯的時候)來進行自我檢查而且對內部的成員進行操做。例如它容許一個java的類獲取他全部的成員變量和方法而且顯示出來。這個能特定咱們不常看到,可是在其餘的好比C或者C++語言中很不就存在這個特性。一個常見的例子是在JavaBean中,一些組件能夠經過一個構造器來操做。這個構造器就是用的反射在動態加載的時候來獲取的java中類的屬性的。github

主要的類

  • Class 類的實例表示正在運行的 Java 應用程序中的類和接口。Class沒有公共的構造方法,Class 對象是在加載類時由 Java 虛擬機以及經過調用類加載器中的 defineClass 方法自動構造的api

  • Constructor 提供關於類的單個構造方法的信息以及對它的訪問權限(主要提供的是對構造方法使用)數組

  • Method 提供關於類或接口上單獨某個方法(以及如何訪問該方法)的信息。所反映的方法多是類方法或實例方法(包括抽象方法)函數

  • Field 主要提供對類中的成員變量的訪問和使用this

Class<T>

Class類也使用了泛型,便是Class<T>這種形式的,能夠直接使用一個具體的類傳入,這樣的話就不須要強制轉換了,好比Class.newInstance()這樣使用默認的構造方法構造一個對象就須要再也不須要強制轉換了即便用(ClassName)Class.newInstance().net

經常使用的方法

  • getConstructor(Class[] params) 獲取公共的(public)的構造方法,而且限定其中的參數個數和類型能夠得到不一樣的公共構造方法code

  • Constructor[] getConstructors() 返回全部的公共(public)的構造方法

  • getDeclaredConstructor(Class[] params) 獲取全部指定的構造方法,可是須要注意的是當獲取私有的構造方法的時候須要使用setAccessible設置訪問權限爲true才能進行構造,不然出現異常

  • Constructor[] getDeclaredConstructors() 返全部的構造方法包括public和private,protected修飾的

  • T newInstance() 返回的是一個調用默認的構造方法(public class_name())實例化的一個Object對象,若是使用泛型那麼就返回T類型的,反之返回的是Object須要強制轉換才能使用這個對象調用成員函數和成員變量

  • Class forName(String class_name) 返回class對象,每個對都有一個方象法返回Class對象(test.class)

  • Package getPackage() 返回此類所在的包名(package demo) 固然也可使用Package.getName()得到包的名字(demo)好比constructor.getPackage().getName()

  • int getModifiers() 返回的是類的修飾符的整數 類型(修飾符的類型有public private protected)其中獲得整數可使用Modifier中toString(int num)獲得public,private,protected的類型,好比Modifier.toString(class1.getModifiers())
    * Method getMethod(String name, Class<?>... parameterTypes) 返回指定參數的方法Method對象,注意這裏僅僅是返回的時公共的方法(public) 好比:Method method=class1.getMethod("display",new Class[]{int.class})這裏的display是方法的名字,有一個參數,類型爲int

  • Method[] getMethods() 獲取全部的公共的方法(public)返回的是一個數組(Method)

  • Method getDeclaredMethod(String name,Class<?>... parameterTypes)返回全部的指定的參數的方法(public,private,protected,可是不包括繼承的),其中參數能夠爲null(無參數)

  • Method[] getDeclaredMethods() 獲取全部的方法

  • Field getField(String name) 指定名字的公共成員變量(public)

  • Field[] getFields() 獲取全部的公共的成員變量

  • Field getDeclaredField(String name) 獲取全部的指定名稱的成員變量(public,protected,private),一樣在調用私有成員變量的時候須要先設置訪問的權限,field.setAccessible(true)

  • Field[] getDeclaredFields() 獲取全部的成員變量(public,protected,private)

  • getSuperclass() 返回表示此 Class 所表示的實體(類、接口、基本類型或 void)的超類的 Class。

  • URL getResource(String name) 查找指定名稱的資源(圖片,文件...)注意這個資源必定要和指定類在一個包中,不然返回null,好比查找Test類下的airplane.png圖片:Test.class.getResource("airplane.png")這裏返回的將是絕對路徑

獲取Class的對象而且實例化

  • 使用Class.forName(String className) 其中className必定是包含包的名字,下面的demo就是包的名字,Test是類的名字。這是最經常使用的方法,學過JDBC的都知道加載驅動的時候就是使用的Class.forName()

/*
     * 第一種使用forName(String className),其中className必定是包含包的名字,下面的demo就是包的名字,Test是類的名字
     */
    Class cls=Class.forName("demo.Test");
    Test test=(Test)cls.newInstance();    //這裏只是使用了默認的構造方法實例化對象
  • 使用類名.class

Class cls=Test.class;
  • 使用對象.getClass()

Test test=new Test();
    Class cls=test.getClass();

Constructor<T>

  • 主要是用來對類的構造方法進行操做的,能夠看出這個也使用了泛型,和上面的Class是同樣的,注意這裏若是沒有使用泛型,那麼本來放回T類型的如今都是返回Object

經常使用的方法

  • T newInstance(Object parms) 使用帶有參數的構造方法實例化對象,若是使用了泛型,那麼返回的就是T類型的,反之返回的是Object類型的,須要強制轉換

  • getName() 以字符串的形式返回構造方法的名稱,具體的路徑包含包名(demo.Test)

  • int getModifiers()Class類中的方法同樣

Method

主要提供的是對類中的方法的操做

經常使用的方法

  • Object invoke(Object obj,object args) 使用獲得的Method對象調用方法,obj是類的已經構造好的對象,若是是靜態方法直接寫null,由於靜態方法的調用不須要對象,返回值是Object類型的,若是接受返回值,須要使用強制轉換成相應的類型,args是傳入的參數,若是有多個參數,那麼能夠直接在後面用逗號添加或者直接建立數組new Object[]{22,"chenjiabing"}好比:method.invoke(test,22,"chenjiabing") method.invoke(test,new Object[]{22,"chenjiabing"})注意:若是調用的private類型的方法,那麼須要在前面設置訪問的權限,method.setAccessible(true)

  • String getName() 返回此方法的名字(display)

  • Modifier getModifiers() 返回此方法的修飾符的類型表示的整數(public,private...),可使用Modifier.toString()轉換成字符串形式

  • Class getReturnType() 返回這個方法的返回類型

  • String toString() 返回這個方法表示的字符串的形式

Field

主要提供對類的成員變量的操做

經常使用方法

  • String getName() 返回變量名字

  • Object get(Object obj) 返回此變量在指定對象中的值,由於在構造對象的時候每個傳入的變量的值都不同,所以須要使用對象obj。obj表示傳入的對象,返回的Object類型,所以須要強制轉換

  • void set(Object obj,Object value) 改變obj對象上的變量的值爲value

  • Modifier getModifiers() 返回整數表示修飾的類型

  • String getType() 獲取變量的類型(int,String,double float.....)

Modifier

Modifier 類提供了 static 方法和常量,對類和成員訪問修飾符進行解碼。修飾符集被表示爲整數,用不一樣的位位置 (bit position) 表示不一樣的修飾符。

經常使用的方法

  • static String toString(int mode) 將表明修飾符的整數形式轉換爲字符串形式的修飾符,好比將1轉換成public

  • static isInterface(int mode) 若是整數參數包括 interface 修飾符,則返回 true,不然返回 false

  • static isStatic(int mode)

  • static isPrivate(int mode)

  • static isPublic(int mode)

  • static isAbstract(int mode)

實例

Modifier.toString(Test.class.getModifiers())    //獲得Test類的修飾符

使用

有了上面的鋪墊,咱們就可使用上面的這些類進行操做了,在進行操做以前,咱們須要先定義一個類Test,放在demo包下,內容以下

package demo;

import java.util.jar.Attributes.Name;

import javax.print.attribute.standard.MediaSize.NA;

public class Test {
    public String name;
    private int age;

    public Test() {
        this.name = "陳加兵";
        this.age = 23;
    }

    public Test(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void display() {
        System.out.println("name=" + this.name + "----age=" + this.age);
    }

    public void set(String name, int age) {
        this.name = name;
        this.age = age;
    }

    private int getAge() {
        return this.age;
    }

}

實例化對象

  • 使用Class默認的構造newInstance()

Class class1=Class.forName("demo.Test");  //靜態加載Class
        Test test=(Test)class1.newInstance();  //調用默認的構造方法(public Test())實例化對象,因爲沒有使用泛型,所以須要強轉
        test.display();    //調用display方法
  • 使用Class中的getConstructor()方法構造對象,須要注意的使用private類型構造方法時必定要先設置訪問權限爲true-constructor.setAccessible(true);

/*
         *調用public Test(String name,int age)獲得Constructor的兩種形式
         *   1.Constructor constructor=class1.getConstructor(new Class[]{String.class,int.class});
         *   2.Constructor constructor=class1.getConstructor(String.class,int.class);這個和上面的是同樣的,就是使用的參數形式不同
         * 
         * 
         * 
         * 
         *使用newInstance()構造對象的兩種方式
         *   1.Test test=(Test)constructor.newInstance(new Object[]{"chenjiabing",22});
         *     2.Test test=(Test)constructor.newInstance("chenjiabing",22); 只是形式不一樣而已,不過我仍是喜歡上面的形式
         *
         */
        
        
        
        
        /*
         * 調用public Test(String name,int age)
         *         Class.getConstructor()獲得的是公共的構造方法,若是有私有的構造方法,那麼就會報錯,這時就要使用getDeclaredConstructor(Class<?>... parameterTypes)
         *         Test test=(Test)constructor.newInstance("陳加兵",22);
         * 
         * 
         * 調用public Test() 
         *      Constructor constructor=class1.getConstructor(null);
         *      Test test=(Test)constructor.newInstance(null);
         * 
         * 
         * 調用private Test(int age)
         *         Constructor constructor=class1.getDeclaredConstructor(new Class[]{int.class});
                constructor.setAccessible(true);   //由於private類型是不能夠直接訪問的,所以須要設置訪問權限爲true
                Test test=(Test)constructor.newInstance(new Object[]{1000});
        */
        
        
        
        Class class1=Class.forName("demo.Test");
        //訪問public Test(String name,int age)
//        Constructor constructor=class1.getConstructor(new Class[]{String.class,int.class});
//        Test test=(Test)constructor.newInstance("陳加兵",22);
        
        //訪問默認的構造方法
//        Constructor constructor=class1.getConstructor(null);
//        Test test=(Test)constructor.newInstance(null);

        //訪問private類型的構造方法
        Constructor constructor=class1.getDeclaredConstructor(new Class[]{int.class});
        constructor.setAccessible(true);
        Test test=(Test)constructor.newInstance(new Object[]{1000});
        test.display();

成員方法的操做

使用Class.getMethod()Class.getDeclaredMethod()方法獲取方法,這兩個方法的區別前面已經說過了,注意的是調用私有成員方法的以前必定要設置訪問權限(method.setAccessible(true))

Method類中的其餘方法前面也已經說過了,詳細使用請本身嘗試

/*
         * 獲取Method對象的兩種方式:
         *         1.Method method_set=class1.getMethod("set", new Class[]{String.class,int.class});
         *         2.Method method_set=class1.getMethod("set", String.class,int.class);
         * 
         * 
         * 使用Method.invoke()調用方法的兩種方式
         *         1.Object o=method_set.invoke(test, new Object[]{"陳加兵",200});
         *         2.Object object=method_set.invoke(test, "陳加兵",2000);
         */
        
        
        
        
        /*
         * 獲取公共方法(public):
         *         1.Method method=class1.getMethod("display",null);  //public void display()
         *         2.Method method_set=class1.getMethod("set", new Class[]{String.class,int.class});  //獲取public void set(String name,int age)
         * 
         * 
         * 獲取私有方法(private,protected)
         *         1.Method method_getAge=class1.getDeclaredMethod("getAge", null);
         */
        
        
        //使用構造方法構造一個Test對象
        Class class1 =Class.forName("demo.Test");
        Constructor<Test> constructor=class1.getDeclaredConstructor(new Class[]{String.class,int.class});
        Test test=constructor.newInstance(new Object[]{"陳加兵",22});
        
        
        Method method=class1.getMethod("display",null);   //獲取public void display()方法的Method對象
        Object obj=method.invoke(test, null);    //調用方法display
        
        //獲取public void set(String name,int age)
//        Method method_set=class1.getMethod("set", new Class[]{String.class,int.class});
        Method method_set=class1.getMethod("set", String.class,int.class);
        
//        Object o=method_set.invoke(test, new Object[]{"陳加兵",200});
        Object object=method_set.invoke(test, "陳加兵",2000);
        test.display();
        
        
        //獲取私有方法private int getAge()
        Method method_getAge=class1.getDeclaredMethod("getAge", null);
        method_getAge.setAccessible(true);   //必須設置訪問權限爲true
        //判斷返回值類型是否爲int類型的
        if("int".equals(method_getAge.getReturnType().toString()))
        {
            int ReturnData=(int) method_getAge.invoke(test, null);   //調用而且獲取返回值
            System.out.println(ReturnData);
        }

成員變量的操做

主要使用的Field類,前面已經詳細的說過了

/*
         * 獲取public修飾的成員變量:
         *         1.Field field=class1.getField("name"); //獲取public的成員變量name的Filed對象
         * 
         * 獲取private,protected修飾的成員變量:
         *         1.    Field field2=class1.getDeclaredField("age");
         */
         
         
        Class class1=Class.forName("demo.Test");
        Test test=new Test("陳加兵",1000);
        Field field=class1.getField("name"); //獲取public的成員變量name的Filed對象
        System.out.println(field.get(test));   //得到test對象中的name屬性的值
        
        //獲取private int age的Field對象
        Field field2=class1.getDeclaredField("age");
        field2.setAccessible(true);  //設置訪問權限
        System.out.println(field2.get(test));

參考文章

相關文章
相關標籤/搜索