1. 程式人生 > 實用技巧 >使用CrashHandler獲取應用crash資訊

使用CrashHandler獲取應用crash資訊

反射:框架設計的靈魂

名詞解釋:
    * 框架:半成品軟體。可以在框架的基礎上進行軟體開發,簡化編碼
    * 反射:將類的各個組成部分封裝為其他物件,這就是反射機制        
使用反射優點:
        1. 可以在程式執行過程中,操作這些物件。
        2. 可以解耦,提高程式的可擴充套件性。

獲取Class物件的方式

1. Class.forName("全類名"):將位元組碼檔案載入進記憶體,返回Class物件
      * 多用於配置檔案,將類名定義在配置檔案中。讀取檔案,載入類
2. 類名.class:通過類名的屬性class獲取
      * 多用於引數的傳遞
3. 物件.getClass():getClass()方法在Object類中定義著。 * 多用於物件的獲取位元組碼的方式

三種方式獲取Class物件程式碼

 1 package demo14.reflect;
 2 
 3 public class demo01 {
 4     public static void main(String[] args) throws ClassNotFoundException {
 5         // 1 Class.forName("全類名")
 6         Class aClass = Class.forName("demo14.reflect.Person");
7 System.out.println(aClass); 8 9 // 2 類名.class 10 Class bClass = Person.class; 11 System.out.println(bClass); 12 13 // 3 物件.getClass() 14 Person person = new Person(); 15 Class cClass = person.getClass(); 16 System.out.println(cClass);
17 18 //檢查三種方式獲取的Class物件是否一致 19 System.out.println(aClass == bClass); 20 System.out.println(bClass == cClass); 21 22 } 23 }

執行結果

# 注:同一個位元組碼檔案(*.class)在一次程式執行過程中,只會被載入一次,不論通過哪一種方式獲取的Class物件都是同一個。

Class物件功能

1. 獲取成員變數們
     * Field[] getFields() :獲取所有public修飾的成員變數
     * Field getField(String name)   獲取指定名稱的 public修飾的成員變數

     * Field[] getDeclaredFields()  獲取所有的成員變數,不考慮修飾符
     * Field getDeclaredField(String name)  
2. 獲取構造方法們
     * Constructor<?>[] getConstructors()  
     * Constructor<T> getConstructor(類<?>... parameterTypes)  

     * Constructor<T> getDeclaredConstructor(類<?>... parameterTypes)  
     * Constructor<?>[] getDeclaredConstructors()  
3. 獲取成員方法們:
     * Method[] getMethods()  
     * Method getMethod(String name, 類<?>... parameterTypes)  

     * Method[] getDeclaredMethods()  
     * Method getDeclaredMethod(String name, 類<?>... parameterTypes)  

4. 獲取全類名    
     * String getName()  
Field:成員變數
    * 操作:
       1. 設定值
          * void set(Object obj, Object value)  
       2. 獲取值
          * get(Object obj) 
       3. 忽略訪問許可權修飾符的安全檢查
          * setAccessible(true):暴力反射

Constructor:構造方法
    * 建立物件:
        * T newInstance(Object... initargs)  
        * 如果使用空引數構造方法建立物件,操作可以簡化:Class物件的newInstance方法

Method:方法物件
     * 執行方法:
        * Object invoke(Object obj, Object... args)  
     * 獲取方法名稱:
        * String getName:獲取方法名

Class物件獲取成員變數、對成員變數值進行獲取與設定程式碼示例

 1 package demo14.reflect;
 2 
 3 import java.lang.reflect.Field;
 4 
 5 public class demo02 {
 6     public static void main(String[] args) throws Exception {
 7         /*
 8          * Field[] getFields() :獲取所有public修飾的成員變數
 9          * Field getField(String name)   獲取指定名稱的 public修飾的成員變數
10 
11          * Field[] getDeclaredFields()  獲取所有的成員變數,不考慮修飾符
12          * Field getDeclaredField(String name)  獲取指定名稱的成員變數 不考慮修飾符
13          */
14 
15         // 1 獲取Class物件
16         Class cls = Class.forName("demo14.reflect.Person");
17 
18         // 2 獲取成員變數方法
19         // 2.1 獲取所有的public修飾的成員變數
20         Field[] fields = cls.getFields();
21         for (Field field : fields) {
22             System.out.println(field);
23         }
24         // 2.2 獲取指定的public修飾的成員變數
25         Field a = cls.getField("a");
26         System.out.println(a);
27         //2.2.1獲取和設定Field值
28         Person person = new Person();
29         Object o = a.get(person);
30         System.out.println(o);
31         a.set(person, "kelvin");
32         System.out.println(person);
33 
34         // 2.3 獲取所有的成員變數
35         Field[] declaredFields = cls.getDeclaredFields();
36         for (Field field : declaredFields) {
37             System.out.println(field);
38         }
39 
40         // 2.4 獲取指定的成員變數
41         Field d = cls.getDeclaredField("d");
42         System.out.println(d);
43         //忽略訪問許可權修飾符的安全檢查(暴力反射)
44         d.setAccessible(true);
45         //2.4.1獲取和設定非public修飾的Field值
46         Person person1=new Person();
47         Object o1 = d.get(person1);
48         System.out.println(o1);
49         d.set(person1,"jack");
50         System.out.println(person1);
51     }
52 }

Class物件獲取構造方法,並根據構造方法建立物件

 1 package demo14.reflect;
 2 
 3 import java.lang.reflect.Constructor;
 4 import java.util.Arrays;
 5 
 6 public class demo03 {
 7     public static void main(String[] args) throws Exception {
 8         /*
 9          Constructor<?>[] getConstructors()
10          Constructor<T> getConstructor(類<?>... parameterTypes)
11 
12          Constructor<T> getDeclaredConstructor(類<?>... parameterTypes)
13          Constructor<?>[] getDeclaredConstructors()
14 
15         建立物件:
16         T newInstance(Object... initargs)
17         如果使用空引數構造方法建立物件,操作可以簡化:Class物件的newInstance方法
18 
19          */
20 
21         Class cls = Class.forName("demo14.reflect.Person");
22         // 1 獲取所有public修飾的構造方法
23         Constructor[] constructors = cls.getConstructors();
24         System.out.println(Arrays.toString(constructors));
25 
26         // 2 獲取指定的引數的構造方法
27         Constructor constructor = cls.getConstructor(String.class, int.class);
28         System.out.println(constructor);
29         // 2.1 使用有參構造方法建立物件
30         Object kelvin = constructor.newInstance("kelvin", 23);
31         System.out.println(kelvin);
32 
33         // 3 獲取無參構造方法
34         Constructor constructor1 = cls.getConstructor();
35         System.out.println(constructor1);
36         // 3.1 使用無參構造方法建立物件
37         // 方式一
38         Object o = constructor1.newInstance();
39         System.out.println(o);
40         // 方式二
41         Object o1 = cls.newInstance();
42         System.out.println(o1);
43 
44 
45     }
46 }

Class獲取成員方法並執行

 1 package demo14.reflect;
 2 
 3 import java.lang.reflect.Method;
 4 import java.util.Arrays;
 5 
 6 public class demo04 {
 7     public static void main(String[] args) throws Exception {
 8         /*
 9           Method[] getMethods()
10           Method getMethod(String name, 類<?>... parameterTypes)
11 
12           Method[] getDeclaredMethods()
13           Method getDeclaredMethod(String name, 類<?>... parameterTypes)
14 
15           執行方法:
16             Object invoke(Object obj, Object... args)
17           獲取方法名稱:
18             String getName:獲取方法名
19 
20          */
21         Class cls = Class.forName("demo14.reflect.Person");
22 
23         // 1 獲取所有的public成員方法
24         Method[] methods = cls.getMethods();
25         System.out.println(Arrays.toString(methods));
26         // 2 獲取指定的public成員帶參方法
27         Person person = new Person();
28         Method run = cls.getMethod("run", String.class);
29         run.invoke(person, "kelvin");
30         // 3 獲取指定的public修飾無參成員方法
31         Method run1 = cls.getMethod("run");
32         run1.invoke(person);
33 
34         // 4 獲取private修飾的成員方法
35         Method eat = cls.getDeclaredMethod("eat");
36         // 暴力反射
37         eat.setAccessible(true);
38         eat.invoke(person);
39     }
40 }

反射應用例項

藉助配置檔案,配置檔案可以配置類和方法。

 1 package demo14.reflect;
 2 
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.lang.reflect.Method;
 6 import java.util.Properties;
 7 
 8 public class demotest {
 9     /*
10     不能改變該類的任何程式碼。可以建立任意類的物件,可以執行任意方法
11     */
12     public static void main(String[] args) throws Exception {
13         Properties pro = new Properties();
14 
15         ClassLoader classLoader = demotest.class.getClassLoader();
16         InputStream resourceAsStream = classLoader.getResourceAsStream("demo14/reflect/pro.properties");
17         pro.load(resourceAsStream);
18 
19         String className = pro.getProperty("className");
20         String classMethod = pro.getProperty("classMethod");
21 
22         Class cls = Class.forName(className);
23         Method method = cls.getMethod(classMethod);
24 
25         Object o = cls.newInstance();
26         method.invoke(o);
27     }
28 }

配置檔案

className=demo14.reflect.Student
classMethod=study