反射作用
獲取字節碼文件里面的所有信息,包括構造方法、成員、成員方法,以及修飾他們的修飾符、類型和方法的返回值等等,只要是類里面的內容都能獲取,獲取之后可以動態的調用方法,動態的創建對象
獲取類字節碼文件對象
通過該對象可進行獲取構造方法、成員、成員方法等操作?
//獲取Class對象的三種方法//方法一:通過調用Class類里面的靜態方法獲取(包名 + 類名)Class<?> class1 = Class.forName("a01CreatReflect.Student");System.out.println(class1);//方法二:通過字節碼文件獲取Class<Student> class2 = Student.class;System.out.println(class2);//方法三:通過類實例化后通過實列化對象獲取ClassStudent student = new Student();Class<? extends Student> class3 = student.getClass();System.out.println(class3);
?獲取構造方法?
declare可以獲取到所有(包括私有)的構造方法,而沒有declare修飾的只能獲取公共的?
?獲取成員
?
declare可以獲取到所有(包括私有)的成員,而沒有declare修飾的只能獲取公共的??
獲取成員方法?
?
declare修飾的將獲取該類的所有方法(包括權限不夠大的方法)?
?
沒有declare修飾的連該類繼承的父類,以及實現的接口的公共方法都能獲取到?
?應用場景
?獲取一個實例化對象的所有信息,并將他存進文件
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, IOException {//練習1:獲取字節碼文件里面的成員信息并保存進文件Student s = new Student("zhangsan", 19, "睡覺");Teacher t = new Teacher("niubi", 26);//獲取字節碼文件對象saveObj(s);}public static void saveObj(Object o) throws ClassNotFoundException, IllegalAccessException, IOException {//獲取當前對象的字節碼文件對象Class<?> aClass = o.getClass();//創建高級字符輸出流對象BufferedWriter bw = new BufferedWriter(new FileWriter("Reflect\\a.txt"));//字符串對象//通過字節碼文件對象獲取該字節碼里面的所有成員變量并保存進文件Field[] fields = aClass.getDeclaredFields();for (Field field : fields) {StringBuilder sb = new StringBuilder();field.setAccessible(true);//獲取成員變量的名字String name = field.getName();//獲取成員變量的值Object value = field.get(o);StringBuilder append = sb.append(name + "=" + value);bw.write(append.toString());bw.newLine();}bw.close();}
?無需修改源碼,實現調用不同類的方法
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//練習2:不用修改代碼,只需修改配置文件實現運行其他類的方法//反射:從文件中獲取內容進行操作Properties p = new Properties();//把文件內容全部加載進集合pp.load(new InputStreamReader(new FileInputStream("Reflect\\a.txt")));System.out.println(p);//獲取配置文件中的類名和方法名String method = p.getProperty("method");String classname = p.getProperty("Classname");System.out.println(method);System.out.println(classname);//創建字節碼文件對象Class aClass = Class.forName(classname);//通過字節碼文件創建對象//1.獲取空參構造Constructor con = aClass.getDeclaredConstructor();//暴力反射:臨時將構造方法的權限擴至最大con.setAccessible(true);//2.通過空參構造創建該類對象Object o = con.newInstance();//3.該對象調用方法(獲取要調用的方法)Method m = aClass.getDeclaredMethod(method);//暴力反射:臨時將方法的權限擴至最大m.setAccessible(true);m.invoke(o);}
?動態代理
當一個項目已經上線運營時,而需求發生變化,需要新功能,若直接修改源碼(侵入式修改)需要重新測試,發布新版本等等操作很老告,?而動態代理的可以省去一堆繁瑣的步驟
動態代理步驟:創建代理對象,代理對象調用要代理的方法
?
?