java 反射基礎知識與實踐

本篇重點講解java基礎知識與系統提供api的運用

java class類

java中某個類無論生成多少個對象,這些對象都會對應同一個Class對象,這個Class對象由JVM生成,通過它可以獲悉整個類的結構,包括方法、屬性等等。

原理

所有的java類都是繼承Object,在object類中有一個getClass方法,這個方法是用來取得該類已經被實例化的對象的引用,這個引用指向的class類的對象,我們自己無法生成一個class對象(構造函數爲private),這個class類的對象在各類被調用時,有JVM虛擬機自動創建Class對象,或通過各類裝載器中的defineClass方法生成,

Class方法:

Class.forName("java.lang.string");、Class class = 類.class;、Class class = 對象.class

以上三種方式都可獲得class對象,三種方法得到的結果也是一樣的

在運行期間,如果我們要產生某個類的對象,java虛擬機(JVM)會檢查該類型的class對象是否已被加載,如果沒有被加載,JVM會根據類的名字找到.class對象並加載它,一旦某個類的對象被加載到內存中,就可以用來產生所有類的對象,虛擬機只會產生一份字節碼,用這份字節碼可以產生多個實例對象。

Class.isPrimitive()

Class.isPrimitive():判斷指定Class對象是否表示一個java基本數據類型;boolean、char、int、short、long、float、double、byte;返回boolean類型,true表示是基本數據類型,false表示不是基本數據類型

Class.forName()

Class.forName():要求JVM查找並加載指定類,作用是加載指定靜態模塊,加載了之後進行初始化操作才能正常使用該類,類的初始化操作就是執行一遍靜態語句,包括靜態變量的聲明和靜態代碼塊

 使用Class.forName( )靜態方法的目的是爲了動態加載類。在加載完成後,一般還要調用Class下的newInstance( )靜態方法來實例化對象以便操作。因此,單單使用Class.forName( )是動態加載類是沒有用的,其最終目的是爲了實例化對象。

Class.forName()的作用是要求JVM查找並加載指定的類,首先要明白,java裏面任何class都要裝載在虛擬機上才能運行,而靜態代碼是和class綁定的,class裝載成功就表示執行了你的靜態代碼了,而且以後不會再走這段靜態代碼了。

Class.getField、Class.getDeclaredField返回成員變量

Class.getField()返回已加載類聲明的所有public成員變量的Field對象,包括從父類繼承過來的成員變量,參數name指定成員變量的名稱。

Class.getDeclaredField()返回當前類所有成員變量。

如果想要獲取父類的所有成員變量(主要是爲了拿到私有成員變量,只想獲取公有成員變量可以直接使用getField),可以通過取得當前類的父類的class對象再調用getDeclaredField方法。

Class.getMethod、Class.getDeclaredMethods返回method對象

Class.getMethod():獲取當前類以及所有集成的父類的public修飾的方法,僅包含public

Class.getDeclaredMethods:獲取當前類的所有方法,包括public/private/protected/default

java反射湖獲取某個類的全部屬性

1. forName()   返回給定串名相應的Class對象。

2. getDeclaredFields()  返回當前Class對象表示的類或接口的所有已說明的域對象數組。

3. getFields()   返回當前Class對象表示的類或接口的所有可訪問的公有域對象數組。

4. getModifiers()  返回該類或接口的Java語言修改器代碼。

5. getName()   返回Class對象表示的類型(類、接口、數組或基類型)的完整路徑名字符串。

  要反射的類

package com.my.javahookdemo.test;

public class Father {

    public String name;

    public String sex;

    private String adds;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAdds() {
        return adds;
    }

    public void setAdds(String adds) {
        this.adds = adds;
    }
}

反射方法:

Class<?> clazz = null;
        try {
            clazz = Class.forName("com.my.javahookdemo.test.Father");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println("===============本類屬性===============");
        // 取得本類的全部屬性
        Field[] field = clazz.getDeclaredFields();
        for (int i = 0; i < field.length; i++) {
            // 權限修飾符
            int mo = field[i].getModifiers();
            String priv = Modifier.toString(mo);
            // 屬性類型
            Class<?> type = field[i].getType();
            System.out.println(priv + "---01--->>>" + type.getName() + " " + field[i].getName() + ";");
        }

        System.out.println("==========實現的接口或者父類的屬性==========");
        // 取得實現的接口或者父類的屬性
        Field[] filed1 = clazz.getFields();
        for (int j = 0; j < filed1.length; j++) {
            // 權限修飾符
            int mo = filed1[j].getModifiers();
            String priv = Modifier.toString(mo);
            // 屬性類型
            Class<?> type = filed1[j].getType();
            System.out.println(priv + "---02--->>>" + type.getName() + " " + filed1[j].getName() + ";");
        }

打印log:

12-26 17:12:45.691 26675-26675/com.my.javahookdemo I/System.out: ===============本類屬性===============
12-26 17:12:45.692 26675-26675/com.my.javahookdemo I/System.out: private---01--->>>java.lang.String adds;
12-26 17:12:45.692 26675-26675/com.my.javahookdemo I/System.out: public---01--->>>java.lang.String name;
12-26 17:12:45.693 26675-26675/com.my.javahookdemo I/System.out: public---01--->>>java.lang.String sex;
12-26 17:12:45.693 26675-26675/com.my.javahookdemo I/System.out: ==========實現的接口或者父類的屬性==========
12-26 17:12:45.693 26675-26675/com.my.javahookdemo I/System.out: public---02--->>>java.lang.String name;
12-26 17:12:45.693 26675-26675/com.my.javahookdemo I/System.out: public---02--->>>java.lang.String sex;

可以看到屬性按照意向的已經打印出來了

java通過反射實例化一個類對象

1. forName()   返回給定串名相應的Class對象。

2. newInstance()  創建類的新實例。

3. getConstructors()   返回當前Class對象表示的類的所有公有構造子對象數組。

4. getName()   返回Class對象表示的類型(類、接口、數組或基類型)的完整路徑名字符串。

user類

package com.my.javahookdemo.test;

public class User {

    private int age;
    private String name;

    public User() {
        super();
    }

    public User(String name) {
        super();
        this.name = name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User [age=" + age + ", name=" + name + "]";
    }

}
Class<?> class1 = null;
        try {
            class1 = Class.forName("com.my.javahookdemo.test.User");
            // 第一種方法,實例化默認構造方法,調用set賦值
            User user = (User) class1.newInstance();
            user.setAge(20);
            user.setName("Rollen");
            System.out.println(user);
            // 結果 User [age=20, name=Rollen]
            // 第二種方法 取得全部的構造函數 使用構造函數賦值
            Constructor<?> cons[] = class1.getConstructors();
            // 查看每個構造方法需要的參數
            for (int i = 0; i < cons.length; i++) {
                Class<?> clazzs[] = cons[i].getParameterTypes();
                System.out.print("--0->cons[" + i + "] (");
                for (int j = 0; j < clazzs.length; j++) {
                    if (j == clazzs.length - 1) {
                        System.out.print("--1->"+clazzs[j].getName());
                    } else {
                        System.out.print("--2->"+clazzs[j].getName() + ",");
                    }
                }
                System.out.println("--3->)");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

打印結果

12-26 17:30:06.241 29267-29267/com.my.javahookdemo I/System.out: User [age=20, name=Rollen]
12-26 17:30:06.242 29267-29267/com.my.javahookdemo I/System.out: --0->cons[0] (--3->)
12-26 17:30:06.242 29267-29267/com.my.javahookdemo I/System.out: --0->cons[1] (--2->int,--1->java.lang.String--3->)
12-26 17:30:06.243 29267-29267/com.my.javahookdemo I/System.out: --0->cons[2] (--1->java.lang.String--3->)

java通過反射機制獲取某個類的全部方法

1. forName()   返回給定串名相應的Class對象。

2. getMethods()  返回當前Class對象表示的類或接口的所有公有成員方法對象數組,包括已聲明的和從父類繼承的方法。

3. getModifiers()   返回該類或接口的Java語言修改器代碼。

4. getName()   返回Class對象表示的類型(類、接口、數組或基類型)的完整路徑名字符串。

package com.my.javahookdemo.test;

public class Father {

    public String name;

    public String sex;

    private String adds;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAdds() {
        return adds;
    }

    public void setAdds(String adds) {
        this.adds = adds;
    }

    private void test(){

    }
    public void testmethod(String name){

    }

    public void helloMethod(){

    }
}
Class<?> clazz = null;
            try {
                clazz = Class.forName("com.my.javahookdemo.test.Father");
    
                Method method[] = clazz.getMethods();
                for (int i = 0; i < method.length; ++i) {
                    Class<?> returnType = method[i].getReturnType();
                    Class<?> para[] = method[i].getParameterTypes();
                    int temp = method[i].getModifiers();
                    System.out.print(Modifier.toString(temp) + "--01-->>");
                    System.out.print(returnType.getName() + "--02-->>");
                    System.out.print(method[i].getName() + "--03-->>");
                    System.out.print("(");
                    for (int j = 0; j < para.length; ++j) {
                        System.out.print(para[j].getName() + " " + "arg" + j);
                        if (j < para.length - 1) {
                            System.out.print("--04-->>");
                        }
                    }
                    Class<?> exce[] = method[i].getExceptionTypes();
                    if (exce.length > 0) {
                        System.out.print(") throws ");
                        for (int k = 0; k < exce.length; ++k) {
                            System.out.print(exce[k].getName() + "--05-->>");
                            if (k < exce.length - 1) {
                                System.out.print("--06s-->>");
                            }
                        }
                    } else {
                        System.out.print(")");
                    }
                    System.out.println();
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }

打印log

System.out: public--01-->>boolean--02-->>equals--03-->>(java.lang.Object arg0)
System.out: public--01-->>java.lang.String--02-->>getAdds--03-->>()
System.out: public final--01-->>java.lang.Class--02-->>getClass--03-->>()
System.out: public--01-->>java.lang.String--02-->>getName--03-->>()
System.out: public--01-->>java.lang.String--02-->>getSex--03-->>()
System.out: public--01-->>int--02-->>hashCode--03-->>()
System.out: public--01-->>void--02-->>helloMethod--03-->>()
System.out: public final native--01-->>void--02-->>notify--03-->>()
System.out: public final native--01-->>void--02-->>notifyAll--03-->>()
System.out: public--01-->>void--02-->>setAdds--03-->>(java.lang.String arg0)
System.out: public--01-->>void--02-->>setName--03-->>(java.lang.String arg0)
System.out: public--01-->>void--02-->>setSex--03-->>(java.lang.String arg0)
System.out: public--01-->>void--02-->>testmethod--03-->>(java.lang.String arg0)
System.out: public--01-->>java.lang.String--02-->>toString--03-->>()
System.out: public final native--01-->>void--02-->>wait--03-->>() throws java.lang.InterruptedException--05-->>
System.out: public final--01-->>void--02-->>wait--03-->>(long arg0) throws java.lang.InterruptedException--05-->>
System.out: public final native--01-->>void--02-->>wait--03-->>(long arg0--04-->>int arg1) throws java.lang.InterruptedException--05-->>

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章