標籤:clone() 對象傳輸 unicode 函數 性問題 運行時異常 事件 關係 contains
1.異常
異常,簡單來說,就是一個程式執行過程中發生的不正常情況的事件。它發生在程式的運行期間,幹擾了正常的指令流程。如果沒有處理異常,那麼出現異常之後,程式會停止運行。異常分為運行異常和非運行異常。非運行異常也叫編譯異常。對於編譯異常編譯器要求必須處理。否則無法運行。運行時異常編譯器不要求強制處理。運行時異常一般是由程式邏輯錯誤引起的,程式應該從邏輯角度儘可能避免這類異常的發生。它們都繼承於Exception類。運行異常和非運行異常也下分各類異常。異常發生的原因是程式錯誤或偶然的外在因素導致的一般性問題。
繼承關係
如果一個方法內拋出異常,該異常會被拋到調用方法中。如果異常沒有在調用方法中處理,它繼續被拋給這個方法的調用者。這個過程將一直繼續下去,直到異常被處理。這一過程稱為捕獲異常。
2.反射
在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;
對於任意一個對象,都能夠調用它的任意一個方法和屬性;
這種動態擷取的資訊以及動態調用對象的方法的功能稱為java語言的反射機制。
反射的思維導圖如下
當使用反射時候,首先需要擷取到Class類的對象,得到了這個類之後,就可以得到class檔案裡面的所有內容。
以下是具體的反射應用方式
1.類型轉換:將Map轉成Person的示範
Person類是一個普通的實體類,裡麵包含三個私人的成員屬性及它們的Set和Get函數。Map是集合架構裡使用的Map類型架構,裡面可以加入泛型。具體轉碼如下
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賦給o20 //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--->Object34 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 //1、擷取Class類的對象 3 Class c = Class.forName("com.Person");4 //2、通過Class類中的newInstance方法建立Person對象5 Person p = (Person)c.newInstance();6 //3、檢測一下7 p.setName("張三");8 System.out.println(p.getName());9 }
3>使用class類型中的建構函式中的newInstance方法
public static void test2() throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ //1、擷取Person類型 Constructor c = Person.class.getConstructor(); //2、建立方法 Person p = (Person)c.newInstance(); //3、檢測 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 block18 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字串裡插入一個逗號。以達到計算數位位元效果。
Java 異常與反射 總結