Java反射總結
阿新 • • 發佈:2018-06-10
tac tostring ++ random exception 類信息 cat pes ets
反射(java.lang.reflect)用於分析類能力
(一)Class類
1.定義
Java運行時為每一個對象都維護的一個類型標識,用於跟蹤對象所屬的類提供給虛擬機分析調用,而保存這些信息的類就是Class類
(一個Class類對象可以理解為一個類型,這個類型可以是類或基本數據類型int等)
2.作用
通過對象所屬的Class類,我們可以獲取對象類型的數據域,方法,父類等一切類信息,還可以用它來創建實例對象
獲得父類
//2.獲取父類 Class superc1=c1.getSuperclass();
創建實例
//利用反射創建一個實例對象Class myClass=Class.forName("java.util.Random"); Random random=(Random)myClass.newInstance();
3.獲得Class類的3種途徑
調用Class的靜態方法獲取:Class.forName(String className)
對象調用getClass()方法獲取Class
通過類型名.class獲取,如T.class,T可以是基本數據類型int等,也可以是具體的類如Random.class
Class myClass=Class.forName("java.util.Random"); myClass=new Random().getClass(); myClass=Random.class;
(二)用於描述一個class的三個類:Field,Method,Constructor
Field類代表一個class中的數據域
Method類代表一個class中的方法
Constructor類代表一個class中的構造器
這三個類都繼承Accessible
1.獲取一個類中的Field,Method,Constructor
Class類調用getDeclaredFields()方法獲得該類的所有數據域
Class類調用getDetclaredMethods()方法獲得該類的所有方法
Class類調用getDetclaredConstructors()方法獲得該類的構造器
2.獲得一個Class|Field|Method|Constructor的修飾符
//Modifier.toString()能夠獲取c1的修飾符public final String modifiers=Modifier.toString(c1.getModifiers());
調用這四個類的getModifiers()方法可以返回一個int,作為參數傳入Modifier.toString(),該方法會根據int判斷出修飾符
3.獲得Field數據域的類型(Class)與Field的名臣
Class classType=f.getType();
String name=f.getName();
4.獲取Method的返回類型,Method名稱,Method參數類型
String returnType=methods[j].getReturnType().getName(); String methodName=methods[j].getName(); Class[] paraTypes=methods[j].getParameterTypes();
5.打印一個類的具體信息
package Reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; /** * @ClassName ReFlectionTest * @Description 利用反射打印Double類的所有方法 * @Author cherry * @Date 2018/6/9 21:22 * @Update 2018/6/9 21:22 **/ public class ReFlectionTest{ public static void main(String[] argv){ String className="java.lang.Double"; try{ //1.獲取Class Class c1=Class.forName(className); //2.獲取父類 Class superc1=c1.getSuperclass(); //3.Modifier.toString()能夠獲取c1的屬性public final String modifiers=Modifier.toString(c1.getModifiers()); //4.打印c1的屬性 if(modifiers.length()>0)System.out.print(modifiers+" "); //5.打印c1的類名 System.out.print("class "+className); //6.若有繼承則打印 if(superc1!=null&&superc1!=Object.class)System.out.print("extends " +superc1.getName()); //7.打印中括號 System.out.print("\n{\n"); //8.打印域 printFields(c1); //9.打印構造器 printConstructors(c1); //10.打印方法 printMethods(c1); //11.打印中括號 System.out.print("\n}\n"); }catch(ClassNotFoundException e){ e.printStackTrace(); } } /** * 打印域 * @param c1 */ public static void printFields(Class c1){ //1.獲得所有域 Field[] fields=c1.getFields(); //2.遍歷打印 for(Field f:fields){ Class classType=f.getType(); String name=f.getName(); //3.打印進位符 System.out.print(" "); //4.打印屬性 String modifiers=Modifier.toString(f.getModifiers()); if(modifiers.length()>0)System.out.print(modifiers+" "); System.out.println(classType+" "+name+";"); } System.out.println(); } /** * 打印傳入類的構造器 * @param c1 */ public static void printConstructors(Class c1){ //1.獲取所有構造器 Constructor[] constructors=c1.getConstructors(); //2.遍歷打印 for(Constructor c:constructors){ //3.打印tab占位符 System.out.print(" "); //4.獲取構造器的屬性 String modifier=Modifier.toString(c.getModifiers()); if(modifier.length()>0)System.out.print(modifier+" "); //5.打印構造器名 String conName=c.getName(); System.out.print(conName+"("); //6.打印參數 Class[] paraTypes=c.getParameterTypes(); for(int j=0;j<paraTypes.length;j++){ if(j>0)System.out.print(", "); System.out.print(paraTypes[j].getName()); } System.out.print(");\n"); } System.out.print("\n"); } /** * 打印方法 * @param c1 */ public static void printMethods(Class c1){ //1.獲取所有的方法 Method[] methods=c1.getMethods(); //2.遍歷打印 for(int j=0;j<methods.length;j++){ //3.打印占位符 System.out.print(" "); //4.打印方法屬性 String modifiers=Modifier.toString(methods[j].getModifiers()); if(modifiers.length()>0)System.out.print(modifiers+" "); //5.打印返回類型 String returnType=methods[j].getReturnType().getName(); System.out.print(returnType+" "); //6.打印方法名 String methodName=methods[j].getName(); System.out.print(methodName+"("); //7.打印參數名 Class[] paraTypes=methods[j].getParameterTypes(); for(int i=0;i<paraTypes.length;i++){ if(i>0)System.out.print(","); System.out.print(paraTypes[i].getName()); } if(j+1!=methods.length) System.out.print(")\n"); } } }
(三)運行時獲取一個對象的數據域的具體值
Student student=new Student(18); //創建student對象 Class studentClass=student.getClass(); //獲取Student的Class Field field=studentClass.getDeclaredField("age"); //得到age域 field.setAccessible(true); //設置可訪問private域 System.out.println(field.get(student)); //訪問age域的值
(四)調用一個對象的方法
Student student=new Student(18); //創建student對象 Class studentClass=student.getClass(); //獲取Student的Class Method setAgeMethod=studentClass.getMethod("setAge", int.class); //獲取方法 setAgeMethod.invoke(student,20); //訪問age域的值 System.out.println(student.getAge()); //返回20
(五)實現一個泛型數組操作方法
/** * 用於擴展已經填滿的數組 * @param a * @param newLength * @return */ public static Object goodCopyOf(Object a,int newLength){ Class c1=a.getClass(); //獲取傳入的a的Class if(!c1.isArray())return null; //若不是數組類型直接返回null Class compomentType=c1.getComponentType(); //獲取數組元素類型 int length=Array.getLength(a); //獲取傳入的數組的長度 Object newArray=Array.newInstance(compomentType,newLength); //Array.newInstance()根據元素類型與長度新建一個相同類型數組且長度擴大 System.arraycopy(a,0,newArray,0,Math.min(length,newLength)); //將原數組的值賦予新數組 return newArray; }
參考《Java核心技術 卷I》p190
Java反射總結