反射允許對成員變量、成員方法和構造器的信息進行編程訪問。
補充:暴力反射,非public修飾需要打開權限
setAccessible(boolean)
反射都是從class字節碼文件中獲取的內容。
代碼演示:
package com.liming.myreflect;public class ReflectDemo01 {public static void main(String[] args) throws ClassNotFoundException {/** 獲取class對象的三種方式* 1、Class.forName("全類名");* 2、類名.class* 3、對象.getClass();* *///1、方式一//全類名:包名+類名//最為常用的Class clazz1 = Class.forName("com.liming.myreflect.Student01");//2、方式二//一般更多的是當做參數進行傳遞Class clazz2 = Student01.class;//3、方式三//當我們已經有了這個類的對象時,才可以使用Student01 stu = new Student01();Class clazz3 = stu.getClass();System.out.println(clazz1 == clazz2);System.out.println(clazz2 == clazz3);} } package com.liming.myreflect;public class Student01 {private String name;private int age;public String gender;public Student01() {}public Student01(String name, int age, String gender) {this.name = name;this.age = age;this.gender = gender;}/*** 獲取* @return name*/public String getName() {return name;}/*** 設置* @param name*/public void setName(String name) {this.name = name;}/*** 獲取* @return age*/public int getAge() {return age;}/*** 設置* @param age*/public void setAge(int age) {this.age = age;}public String toString() {return "Student01{name = " + name + ", age = " + age + "}";}/*** 獲取* @return gender*/public String getGender() {return gender;}/*** 設置* @param gender*/public void setGender(String gender) {this.gender = gender;} }規則:
? 1、get表示獲取
? 2、Declared表示私有
? 3、最后的s表示所有,復數形式
? 4、如果當前獲取到的是私有的,必須要臨時修改訪問權限,否則無法使用
代碼演示:
涉及到的方法:newInstance
代碼演示:
//首先要有一個javabean類 public class Student {private String name;private int age;public Student() {}public Student(String name) {this.name = name;}private Student(String name, int age) {this.name = name;this.age = age;}/*** 獲取* @return name*/public String getName() {return name;}/*** 設置* @param name*/public void setName(String name) {this.name = name;}/*** 獲取* @return age*/public int getAge() {return age;}/*** 設置* @param age*/public void setAge(int age) {this.age = age;}public String toString() {return "Student{name = " + name + ", age = " + age + "}";} }//測試類中的代碼: //需求1: //獲取空參,并創建對象//1.獲取整體的字節碼文件對象 Class clazz = Class.forName("com.liming.myreflect.Student"); //2.獲取空參的構造方法 Constructor con = clazz.getConstructor(); //3.利用空參構造方法創建對象 Student stu = (Student) con.newInstance(); System.out.println(stu);System.out.println("=============================================");//測試類中的代碼: //需求2: //獲取帶參構造,并創建對象 //1.獲取整體的字節碼文件對象 Class clazz = Class.forName("com.liming.myreflect.Student"); //2.獲取有參構造方法 Constructor con = clazz.getDeclaredConstructor(String.class, int.class); //3.臨時修改構造方法的訪問權限(暴力反射) con.setAccessible(true); //4.直接創建對象 Student stu = (Student) con.newInstance("zhangsan", 23); System.out.println(stu);規則:
? 1、get表示獲取
? 2、Declared表示私有
? 3、最后的s表示所有,復數形式
? 4、如果當前獲取到的是私有的,必須要臨時修改訪問權限,否則無法使用
void set(Object obj, Object value) | 賦值 |
Object get(Object obj) | 獲取值 |
規則:
? 1、get表示獲取
? 2、Declared表示私有
? 3、最后的s表示所有,復數形式
? 4、如果當前獲取到的是私有的,必須要臨時修改訪問權限,否則無法使用
Object invoke(Object obj, Object… args) :運行方法
參數一:用obj對象調用該方法
參數二:調用方法的傳遞的參數(如果沒有就不寫)
返回值:方法的返回值(如果沒有就不寫)
代碼演示:
package com.liming.myreflect;import java.lang.reflect.Method; import java.lang.reflect.Parameter;public class ReflectDemo03 {public static void main(String[] args) throws Exception {//1、獲取class字節碼文件對象Class clazz = Class.forName("com.liming.myreflect.Student02");//2、獲取所有公共的成員方法(包含父類中所有的公共方法)Method[] methods = clazz.getMethods();for (Method method : methods) {System.out.println(method);}System.out.println("======================================");//獲取所有的成員方法(不包含父類)Method[] declaredMethods = clazz.getDeclaredMethods();for (Method method : declaredMethods) {System.out.println(method);}System.out.println("======================================");//獲取單個公共的成員方法Method sleep = clazz.getMethod("sleep");System.out.println(sleep);System.out.println("======================================");//獲取單個成員方法Method eat = clazz.getDeclaredMethod("eat", String.class);System.out.println(eat);System.out.println("======================================");//獲取方法的修飾符int modifiers = eat.getModifiers();System.out.println(modifiers);//獲取方法的名字String name = eat.getName();System.out.println(name);//獲取方法的形參Parameter[] parameters = eat.getParameters();for (Parameter parameter : parameters) {System.out.println(parameter);}//獲取方法拋出的異常Class[] exceptionTypes = eat.getExceptionTypes();for (Class exceptionType : exceptionTypes) {System.out.println(exceptionType);}//方法運行//參數一:用obj對象調用該方法//參數二:調用方法傳遞的參數(沒有就不寫)//返回值:方法的返回值(沒有就不寫)Student02 stu = new Student02();eat.setAccessible(true);eat.invoke(stu,"雞腿");} } package com.liming.myreflect;public class Student02 {private String name;private int age;public Student02() {}public Student02(String name, int age) {this.name = name;this.age = age;}/*** 獲取* @return name*/public String getName() {return name;}/*** 設置* @param name*/public void setName(String name) {this.name = name;}/*** 獲取* @return age*/public int getAge() {return age;}/*** 設置* @param age*/public void setAge(int age) {this.age = age;}public void sleep(){System.out.println("睡覺");}private void eat(String something){System.out.println("在吃"+something);}public String toString() {return "Student02{name = " + name + ", age = " + age + "}";} }你覺得反射好不好?好,有兩個方向
第一個方向:無視修飾符訪問類中的內容。但是這種操作在開發中一般不用,都是框架底層來用的。
第二個方向:反射可以跟配置文件結合起來使用,動態的創建對象,動態的調用方法。
?
集合中的泛型只在java文件中存在,當編譯成class文件之后,就沒有泛型了。
代碼演示:
public class ReflectDemo03 {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {//1.創建集合對象ArrayList<Integer> list = new ArrayList<>();list.add(123);//list.add("asd");//2.利用反射運行add方法去添加字符串//因為反射使用的是class字節碼文件//獲取class對象Class clazz = list.getClass();//獲取add方法對象Method add = clazz.getMethod("add", Object.class);//運行方法add.invoke(list,"asd");//打印集合System.out.println(list);} }字符串不可以修改的原因?
字符串,在底層是一個byte類型的字節數組,名字叫做value
真正不能被修改的原因:final和private
final修飾value表示value記錄的地址值不能修改。
private修飾value而且沒有對外提供getvalue和setvalue的方法。所以,在外界不能獲取或修改value記錄的地址值。
如果要強行修改可以用反射:
代碼演示:
public class ReflectDemo04 {public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {String s = "abc";String ss = "abc";// private final byte[] value= {97,98,99};// 沒有對外提供getvalue和setvalue的方法,不能修改value記錄的地址值// 如果我們利用反射獲取了value的地址值,也是可以修改的// final修飾的value真正不可變的value數組的地址值,里面的內容利用反射還是可以修改的,比較危險//1.獲取class對象Class clazz = s.getClass();//2.獲取value成員變量(private)Field field = clazz.getDeclaredField("value");//JDK高版本已經屏蔽了這種操作,低版本還是可以的field.setAccessible(true);//臨時修改權限//3.獲取value記錄的地址值byte[] value = (byte[]) field.get(s);value[0] = 100;System.out.println(s);System.out.println(ss);} }需求: 利用反射根據文件中的不同類名和方法名,創建不同的對象并調用方法。
分析:
①通過Properties加載配置文件
②得到類名和方法名
③通過類名反射得到Class對象
④通過Class對象創建一個對象
⑤通過Class對象得到方法
⑥調用方法
代碼演示:
properties配置文件:
需求:對于任意一個對象,都可以把對象所有的字段名和值,保存到文件中去
代碼演示:
public class ReflectDemo02 {public static void main(String[] args) throws IOException, IllegalAccessException {/* 對于任意一個對象,都可以把對象所有的字段名和值,保存到文件中去 */Student01 stu = new Student01("張三", 23, '男', 182.3, "學習");Teacher teacher = new Teacher("賴桑", 20000.0);saveObject(stu);saveObject(teacher);}public static void saveObject(Object obj) throws IllegalAccessException, IOException {//1.獲取字節碼文件的對象Class clazz = obj.getClass();//2. 創建IO流BufferedWriter bw = new BufferedWriter(new FileWriter("day15" + File.separator + "a.txt", true));//3. 獲取所有的成員變量Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);//獲取成員變量的名字String name = field.getName();//獲取成員變量的值Object value = field.get(obj);//寫出數據bw.write(name + "=" + value);bw.newLine();}bw.close();} }運行結果: 在a.txt文件中
name=賴桑 salary=20000.0 name=張三 age=23 gender=男 height=182.3 hobby=學習 name=賴桑 salary=20000.0本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...
在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...
在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...
炫彩寶石如何鑲嵌?QQ炫舞七彩寶石,使用方法如下:1.七彩寶石是增加七彩值,讓游戲角色進場的道具。打開【背包】,點擊道路工具中的寶石,右鍵升級寶石。五個可以升級一次(需要碰運氣),等級越高,獲得入門動作的幾率越高。2、可以在商城買,集券買,不能用券;還可以為音樂盒,每天50的活動,可能送5到100。3.找到一個可以鑲嵌寶石的物品,右擊該物品,選擇鑲嵌/移除寶石,點擊七彩寶石下的鑲嵌。效果如下:QQ...
蘋果手機屏幕顯示已中病毒?你好;手機有病毒,可以用騰訊手機管家殺毒。騰訊手機管家獨有的雙核查殺引擎,可以有效檢測手機病毒。使用云端智能查殺技術,查殺病毒木馬,以及強大的軟件一鍵分析,刪除多余的系統程序,并可隨時恢復。隱私保護支持圖案解鎖,不再像數字那樣單調。謝謝你。蘋果手機怎么殺毒和清理手機內存?1.進入對應的APP,在設置里找到清除緩存,然后清除。如果你自己下載了一些東西,自己刪除不必要的文件。...
淘寶上傳圖片怎么是黑色?淘寶上傳的主圖顏色變成灰黑是因為像素沒調好,設置沒做好。淘寶怎么調成夜間模式?淘寶切換到夜間模式的方法如下1.單擊設置菜單中的[顯示]。2.單擊[黑暗模式]。3.單擊[更多黑暗模式設置]。4.打開淘寶右邊的開關。淘寶夜間模式怎么設置?淘寶夜間模式設置方法如下:1.在設置菜單中輸入[顯示]。2.單擊[黑暗模式]。3.單擊[更多黑暗模式設置]。4.打開淘寶右邊的開關就可以了。怎...