反射(reflect)
×
× 反射中類類型(ClassType)、類(class)、實例對象(Instance)的關系
× 動態加載類
1 try { 2 Class c = Class.forName("className");//驅動加載也是長這樣的 3 } catch (ClassNotFoundException e) { 4 e.printStackTrace(); 5 }
一、類類型(Class)的三種表現形式(一個類[class]只能有一個類類型對象[ClassType])
1 Class c = className.class; 2 Class c = classNameInstence.getClass;3 Class c = Class.forName("類的全稱[packageName.className]");
二、通過獲取到的類類型對象進行實例創建(所創建的對象為class的實例,Class的實例)
className instance = (className) c.newInstance();
三、獲取方法信息(函數的反射) -— java.lang.reflect.Method類
相關函數 (c:類的類類型;getDeclaredXxx():不包括父類繼承而來,且自己聲明、不問訪問權限的成員)
1. Method method = c.getMethod("methodName", parameterTypes); // 返回類中指定的public函數 。包括父類繼承而來的
Method method = c.getDeclaredMethod(); //返回類中指定的自身聲明的函數,不包括父類繼承而來的
2. Method[ ] method = c.getMethods(); // 獲取該類中所有public的方法,包括父類繼承而來的。
Method[ ] method = c.getDeclaredMethods(); 獲取該類中所有該類自己聲明的方法,不問訪問權限。
演示代碼
1 // Class c = className.class 2 // Class c = Class.forName(""); 3 Class c = instance.getClass();// 獲取類類型對象 4 System.out.println("類名稱:" + c.getName()); 5 Method[] mets = c.getMethods();// 獲取所有方法 6 for (int i = 0; i < mets.length; i++) { 7 Class returnType = mets[i].getReturnType();//返回值類型的類類型 8 System.out.print(returnType.getName() + " ");// 獲取並輸出返回值類型 9 System.out.print(mets[i].getName() + "( ");// 獲取並輸出方法名稱 10 11 // 獲取參數類型 12 Class[] paramTypes = mets[i].getParameterTypes();// 返回參數列表的類型的類類型 13 for (int j = 0; j < paramTypes.length; j++) { 14 if (i == (paramTypes.length - 1)) { 15 System.out.print(paramTypes[j].getName()); 16 } else { 17 System.out.print(paramTypes[j].getName() + ","); 18 } 19 } 20 System.out.println(")"); 21 }
四、獲取變量信息(變量)
1 // Class c = className.class 2 // Class c = Class.forName(""); 3 Class c = obj.getClass(); 4 /* 5 * 成員變量也是對象 6 * java.lang.reflect.Field 7 * Field類封裝了關於成員變量的操作 8 * getFields()方法獲取的是所有的public的成員變量的信息 9 * getDeclaredFields獲取的是該類自己聲明的成員變量的信息 10 */ 11 //Field[] fs = c.getFields(); 12 Field[] fs = c.getDeclaredFields(); 13 for (Field field : fs) { 14 //得到成員變量的類型的類類型 15 Class fieldType = field.getType(); 16 String typeName = fieldType.getName(); 17 //得到成員變量的名稱 18 String fieldName = field.getName(); 19 System.out.println(typeName+" "+fieldName); 20 }
五、獲取構造函數信息
1 // Class c = className.class 2 // Class c = Class.forName(""); 3 Class c = obj.getClass(); 4 /* 5 * 構造函數也是對象 6 * java.lang. Constructor中封裝了構造函數的信息 7 * getConstructors獲取所有的public的構造函數 8 * getDeclaredConstructors得到所有的構造函數 9 */ 10 //Constructor[] cs = c.getConstructors(); 11 Constructor[] cs = c.getDeclaredConstructors(); 12 for (Constructor constructor : cs) { 13 System.out.print(constructor.getName()+"("); 14 //獲取構造函數的參數列表--->得到的是參數列表的類類型 15 Class[] paramTypes = constructor.getParameterTypes(); 16 for (Class class1 : paramTypes) { 17 System.out.print(class1.getName()+","); 18 } 19 System.out.println(")"); 20 }
六、方法的反射操作
1 method.invoke("對象",{參數列表}); //沒錯,就這樣... 2 //Object o = m.invoke(a1,new Object[]{10,20}); 3 Object o = m.invoke(a1, 10,20);
通過反射機制了解泛型
* c1==c2結果返回true說明編譯之後集合的泛型是去泛型化的
* Java中集合的泛型,是防止錯誤輸入的,只在編譯階段有效,繞過編譯就無效了
* 驗證:我們可以通過方法的反射來操作,繞過編譯
* 結論:泛型盡在編譯時起作用,防止錯誤操作,與序列化有些相似
反射(reflect)