Java 異常與反射 總結

      1.異常  

        異常,簡單來講,就是一個程序執行過程當中發生的不正常狀況的事件。它發生在程序的運行期間,干擾了正常的指令流程。若是沒有處理異常,那麼出現異常以後,程序會中止運行。異常分爲運行異常和非運行異常。非運行異常也叫編譯異常。對於編譯異常編譯器要求必須處理。不然沒法運行。運行時異常編譯器不要求強制處理。運行時異常通常是由程序邏輯錯誤引發的,程序應該從邏輯角度儘量避免這類異常的發生。它們都繼承於Exception類。運行異常和非運行異常也下分各種異常。異常發生的緣由是程序錯誤或偶然的外在因素致使的通常性問題。html

繼承關係如圖java

若是一個方法內拋出異常,該異常會被拋到調用方法中。若是異常沒有在調用方法中處理,它繼續被拋給這個方法的調用者。這個過程將一直繼續下去,直到異常被處理。這一過程稱爲捕獲異常。api

2.反射

在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;框架

對於任意一個對象,都可以調用它的任意一個方法和屬性;ide

這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。函數

反射的思惟導圖以下工具

 

 

      當使用反射時候,首先須要獲取到Class類的對象,獲得了這個類以後,就能夠獲得class文件裏面的全部內容。google

如下是具體的反射應用方式spa

1.類型轉換:將Map轉成Person的示範

Person類是一個普通的實體類,裏面包含三個私有的成員屬性及它們的Set和Get函數。Map是集合框架裏使用的Map類型框架,裏面能夠加入泛型。具體轉換代碼以下3d

 1 //param1:要轉化的數據類型Person.class        String.class
 2 public static Object toBean(Class<?> type,Map<String,? extends Object> map) throws Exception{
 3     
 4     //Introspector專門處理Bean的工具類。好比獲取Class的屬性或者方法或構造
 5     BeanInfo beanInfo = Introspector.getBeanInfo(type);//參數傳遞的就是類的類型
 6     //調用newInstance方法建立這個類
 7     Object o = type.newInstance();
 8     //獲取o的方法
 9     PropertyDescriptor[] ps = beanInfo.getPropertyDescriptors();
10     for (int i = 0; i < ps.length; i++) {
11 
12         PropertyDescriptor p = ps[i];
13         //獲取方法描述的名稱(屬性名稱)若是是Person --->name(name,age,sex)
14         String name = p.getName();
15         //name是否就是map中的key?
16         if(map.containsKey(name)){
17             //經過key獲取map的值
18             Object value = map.get(name);
19             //經過反射,value賦給o
20             //p.getWriteMethod();//set方法
21             //p.getReadMethod();//get方法
22             p.getWriteMethod().invoke(o, value);
23         }
24     }
25     //獲取map中的key的值,以及value的值
26     return o;
27 }
28 public static void main(String[] args) throws Exception {    
29     Map pMap = new HashMap();
30     pMap.put("name", "張三");
31     pMap.put("age", 1);
32     pMap.put("sex", 2);
33     //Map--->Object
34     Person p = new Person("張三");
35     p.setAge(1);
36     p.setSex(2);
37     Person o = (Person)toBean(Person.class,pMap);
38     System.out.println(" "+o.toString());
39 }

        以上代碼的思想就是,建立一個相對於想要的類的BeanInfo,而後經過這個BeanInfo對象獲得全部的屬性名稱(對應到Map裏就是全部鍵值對的鍵),而後判斷Map裏是否有與獲取的鍵名稱同名的鍵,若是有的話就經過Map獲取那個鍵的值,而後經過PropertyDescriptor對象獲取須要的對象的set方法,將值賦值給相應的屬性,最後返回相應的類型的對象。

2.Java中五種建立新對象的方法

 1>直接用new調用該類的構造函數

new Person("張三");

2>使用class類中的newInstance方法建立對象,調用構造函數

1 public static void test1() throws ClassNotFoundException, InstantiationException, IllegalAccessException{
2         //一、獲取Class類的對象    
3         Class c = Class.forName("com.Person");
4         //二、經過Class類中的newInstance方法建立Person對象
5         Person p = (Person)c.newInstance();
6         //三、檢測一下
7         p.setName("張三");
8         System.out.println(p.getName());
9     }

3>使用class類型中的構造函數中的newInstance方法

public static void test2() throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
        //一、獲取Person類型
        Constructor c = Person.class.getConstructor();
        //二、建立方法
        Person p = (Person)c.newInstance();
        //三、檢測
        p.setName("張三");
        System.out.println(p.getName());
    }

4>經過clone方法建立。前提是須要在實體類裏重寫clone()方法

/** *實體類 **/
public class Person implements Cloneable{ private String name; private int age; private int sex; @Override protected Person clone() throws CloneNotSupportedException { Person person = null; person = (Person)super.clone(); return person; } } /** *功能類中clone功能函數 **/
public static void test3(){ //須要重寫clone方法,重寫cloneable接口。很是特殊 //在Person類裏實現cloneable接口
        Person p1 =new Person("王五"); //調用clone方法建立一個新的對象p2
        Person p2 = null; try { p2 = p1.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block
 e.printStackTrace(); } System.out.println(p1==p2); }

5>序列化和反序列化的方法,經過這種方法能夠將對象轉換爲字節序列的方式,把對象傳輸到另外一臺機器上。

3.經過反射獲取方法和操做屬性

1>經過反射獲取方法

經過反射獲取方法的方式是先申明一個Class對象,而後經過該對象的getDeclaredMethod方法建立Method對象,經過Method對象的invoke方法調用獲取到的方法實現功能。具體示例代碼以下

 1 public static void test5() {
 2         try { 
 3             Class c = Class.forName("com.hpe.ref.Person");
 4             //獲取方法        Person setName  getName
 5             //param1:方法名的String類型
 6             //param2:方法的參數類型
 7             Method m = c.getDeclaredMethod("setName", String.class);
 8             //建立Object對象
 9             Object obj = c.newInstance();
10             //invoke調用方法(反射的方式調用方法)
11             //param1:反射的類,param2:m方法的值
12             m.invoke(obj, "張三");
13             //驗證
14             Method gM =c.getDeclaredMethod("getName");
15             System.out.println(gM.invoke(obj));
16         } catch (Exception e) {
17             // TODO Auto-generated catch block
18             e.printStackTrace();
19         }
20     }

2>經過反射獲取屬性

        經過反射獲取屬性的方法是經過Class獲取該對象的Class對象形式,以後經過Field以字符串的形式獲取類中的屬性,而後經過Field對象來操做該屬性。具體代碼以下。

public static void test4(){
        //經過反射,在運行階段建立這個person對象
        try {
            Class c = Class.forName("com.hpe.ref.Person");
            
            Field field = c.getDeclaredField("name");
            //經過字符串的形式獲取類中的屬性。
            Field[] fs = c.getDeclaredFields();
            //設置對屬性,若是是私有的,能夠有權限訪問
            field.setAccessible(true);
            Object o  =c.newInstance();
            //set方法----操做屬性的方式
            field.set(o, "張三");
            System.out.println(field.get(o));
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

3.小注:分析下列代碼功能

段代碼的功能分析

public int indexOf(int ch)

返回指定字符第一次出現的字符串內的索引。 若是與值的字符ch在此表示的字符序列發生String第一事件發生之對象,則索引(在Unicode代碼單元)被返回。

public StringBuffer insert(int offset, char c)

在此序列中插入char參數的字符串表示形式。

整體效果就好像第二個參數經過方法String.valueOf(char)轉換爲一個字符串,而且該字符串中的字符而後是inserted到指定的偏移量的這個字符序列。

offset參數必須大於或等於0 ,小於或等於該序列的length

因此它的功能是,以小數點爲界,每往前數三位,就在str字符串裏插入一個逗號。以達到計算數字的位數效果。

相關文章
相關標籤/搜索