JAVASE-14-Java反射

Table of Contents

1:創建Class

1.1: getClass方法

1.2:Class.forName

1.3:類名.class

1.4:Class對象.getSuperclass()獲取到父類

2:獲取構造方法

1:.getDeclaredConstructors():獲取所有的構造方法

2:getConstructors():獲取共有的構造方法

3:獲取特定的構造方法

4:利用構造方法反射創建對象

5:調用類的私有構造方法

3:對類中方法的操作

1:getDeclaredMethods():獲取所有的方法對象,包括私有的和實現接口的,但不包括父類的;

2:getDeclaredMethod():獲取指定方法

3:.getMethod():獲取public的方法包括父類的和實現接口的

4:meth1.invoke():指定特定的方法

4:通過Field類,爲對象設置字段值


相信很多人都知道反射可以說是Java中最強大的技術了,它可以做的事情太多太多,很多優秀的開源框架都是通過反射完成的,比如最初的很多註解框架,後來因爲java反射影響性能,所以被運行時註解APT替代了,java反射有個開源框架jOOR相信很多人都用過,不過我們還是要學習反射的基礎語法,這樣才能自己寫出優秀的框架,當然這裏所講的反射技術,是學習Android插件化技術、Hook技術等必不可少的!
 

1:創建Class

1.1: getClass方法

        String str = "Hello";
        Class aClass = str.getClass();
        System.out.println(""+aClass.getName());//java.lang.String
        User user = new User();
        Class calss2 = user.getClass();
        System.out.println(""+calss2.getName());//com.wkl.bean.User

1.2:Class.forName

     try {
            //這裏也通過捕獲異常,因爲我們傳的這個字符串可能不合法,字符串合法命名是類的命名空間和類的名稱組成
            Class<?> aClass = Class.forName("java.lang.String");
            System.out.println(""+aClass.getName());//java.lang.String
            
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

1.3:類名.class

 Class<User> userClass = User.class;
 System.out.println(""+userClass.getName());//com.wkl.bean.User

1.4:Class對象.getSuperclass()獲取到父類

   
            Class<?> aClass = Class.forName("java.lang.String");
            System.out.println(""+aClass.getName());//java.lang.String
            String name = aClass.getSuperclass().getName();
            System.out.println(""+name);//java.lang.Object

2:獲取構造方法

當類中方法定義爲私有的時候我們能調用?不能!當變量是私有的時候我們能獲取嗎?不能!但是反射可以,比如源碼中有你需要用到的方法,但是那個方法是私有的,這個時候你就可以通過反射去執行這個私有方法,並且獲取私有變量。

public class User {
    private String name;
    private int age;
    private String sex;

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

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

    private User(int age) {
        this.age = age;
    }

}

1:.getDeclaredConstructors():獲取所有的構造方法

        Class<User> userClass = User.class;
   
        Constructor<?>[] constructors = userClass.getDeclaredConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
            System.out.println("構造器名稱:"+constructor.getName());
            System.out.println("修飾符類型:"+constructor.getModifiers());
            Parameter[] parameters = constructor.getParameters();
            System.out.println("構造器參數:"+ JSONArray.toJSONString(parameters));
            Class<?>[] parameterTypes = constructor.getParameterTypes();
            System.out.println("構造器參數類型:"+ JSONArray.toJSONString(parameterTypes));
            System.out.println("=====================================================");
        }

2:getConstructors():獲取共有的構造方法

其餘的和上邊一樣

3:獲取特定的構造方法

我們可以通過getDeclaredConstructor()方法傳參獲取特定參數類型的構造方法,

這裏注意是getDeclaredConstructor()不是  getDeclaredConstructors() ,所以返回的是一個Class對象而不是一個Class數組。

        Class<User> userClass = User.class;

        try {
            Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class);
            System.out.println(""+declaredConstructor);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

不傳參數,默認取無參構造方法

4:利用構造方法反射創建對象

        Class<User> userClass = User.class;
        try {
            Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class);
            System.out.println(""+declaredConstructor);
            User user = declaredConstructor.newInstance("123");
            System.out.println(""+user);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

結果:

5:調用類的私有構造方法

調用私有構造方法呢,和上面一樣,只是我們要設置constructors.setAccessible(true);

3:對類中方法的操作

1:getDeclaredMethods():獲取所有的方法對象,包括私有的和實現接口的,但不包括父類的;

        Class<User> userClass = User.class;
        Method[] declaredMethods = userClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("方法名:"+declaredMethod.getName());
            System.out.println("修飾符"+declaredMethod.getModifiers());
            System.out.println("參數類型:"+JSONArray.toJSONString(declaredMethod.getParameterTypes()));
            System.out.println("返回類型:"+declaredMethod.getReturnType());
            System.out.println("================");
        }
方法名:toString
修飾符1
參數類型:[]
返回類型:class java.lang.String
================
方法名:moth2
修飾符2
參數類型:[]
返回類型:class java.lang.String
================
方法名:moth1
修飾符1
參數類型:[]
返回類型:class java.lang.String
================

2:getDeclaredMethod():獲取指定方法

第一個參數是方法名,第二個參數是參數類型

        Class<User> userClass = User.class;
        try {
            //第一個參數是方法名,第二個參數是參數類型
            Method meth1 = userClass.getDeclaredMethod("moth1",String.class);
            System.out.println(""+ JSONObject.toJSONString(meth1));
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

3:.getMethod():獲取public的方法包括父類的和實現接口的

 Method meth1 = userClass.getMethod("moth1",String.class);

4:meth1.invoke():指定特定的方法

invoke需要兩個參數一個是類的實例,一個是方法參數。

        Class<User> userClass = User.class;
        try {
            User user = new User("aa");
            //第一個參數是方法名,第二個參數是參數類型
            Method meth1 = userClass.getDeclaredMethod("moth1",String.class);
            Object wkl = meth1.invoke(user, "wkl");
            System.out.println(""+wkl);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
wkl:moth1

 

4:通過Field類,爲對象設置字段值

        Class<User> userClass = User.class;
        Field name = userClass.getDeclaredField("name");
        User user = userClass.newInstance();
        //因爲屬性是私有的,所以需要設置Accessible
        name.setAccessible(true);
        name.set(user,"wkl");
        System.out.println(""+user);
User{name='wkl', age=0, sex='null'}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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