1. <nobr id="easjo"><address id="easjo"></address></nobr>

      <track id="easjo"><source id="easjo"></source></track>
      1. 
        

      2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
      3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>
          貴州做網站公司
          貴州做網站公司~專業!靠譜!
          10年網站模板開發經驗,熟悉國內外開源網站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等網站程序,可為您提供網站建設,網站克隆,仿站,網頁設計,網站制作,網站推廣優化等服務。我們專注高端營銷型網站,企業官網,集團官網,自適應網站,手機網站,網絡營銷,網站優化,網站服務器環境搭建以及托管運維等。為客戶提供一站式網站解決方案?。?!

          Java 反射詳解

          來源:互聯網轉載 時間:2023-09-03 18:45:43

          一、反射

          1、什么是反射

          反射允許對成員變量、成員方法和構造器的信息進行編程訪問。
          補充:暴力反射,非public修飾需要打開權限
          setAccessible(boolean)

          2、反射的作用

          • 利用反射創建的對象可以無視修飾符調用類里面的內容
          • 可以跟配置文件結合起來使用,把要創建的對象信息和方法寫在配置文件中。
            讀取到什么類,就創建什么類的對象
            讀取到什么方法,就調用什么方法
            此時當需求變更的時候不需要修改代碼,只要修改配置文件即可。
            簡單記憶:1、獲取任意一個類中的所有信息、2、結合配置文件動態創建對象。

          3、學習反射到底學習什么

          反射都是從class字節碼文件中獲取的內容。

          • 如何獲取class字節碼文件的對象
          • 利用反射如何獲取構造方法(創建對象)
          • 利用反射如何獲取成員變量(賦值,獲取值)
          • 利用反射如何獲取成員方法(運行)

          4、獲取字節碼文件對象的三種方式

          • Class這個類里面的靜態方法forName(“全類名”)(最常用)
          • 通過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;} }

          5、獲取構造方法

          規則:

          ? 1、get表示獲取

          ? 2、Declared表示私有

          ? 3、最后的s表示所有,復數形式

          ? 4、如果當前獲取到的是私有的,必須要臨時修改訪問權限,否則無法使用


          代碼演示:

          public class ReflectDemo2 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {//1.獲得整體(class字節碼文件對象)Class clazz = Class.forName("com.liming.myreflect.Student01");//2.獲取構造方法對象//獲取所有構造方法(public)Constructor[] constructors1 = clazz.getConstructors();for (Constructor constructor : constructors1) {System.out.println(constructor);}System.out.println("=======================");//獲取所有構造(帶私有的)Constructor[] constructors2 = clazz.getDeclaredConstructors();for (Constructor constructor : constructors2) {System.out.println(constructor);}System.out.println("=======================");//獲取指定的空參構造Constructor con1 = clazz.getConstructor();System.out.println(con1);Constructor con2 = clazz.getConstructor(String.class,int.class);System.out.println(con2);System.out.println("=======================");//獲取指定的構造(所有構造都可以獲取到,包括public包括private)Constructor con3 = clazz.getDeclaredConstructor();System.out.println(con3);//了解 System.out.println(con3 == con1);//每一次獲取構造方法對象的時候,都會新new一個。Constructor con4 = clazz.getDeclaredConstructor(String.class);System.out.println(con4);} }

          5.1、獲取構造方法并創建對象

          涉及到的方法: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);

          6、獲取成員變量

          規則:

          ? 1、get表示獲取

          ? 2、Declared表示私有

          ? 3、最后的s表示所有,復數形式

          ? 4、如果當前獲取到的是私有的,必須要臨時修改訪問權限,否則無法使用

          獲取成員變量并獲取值和修改值

          方法說明
          void set(Object obj, Object value)賦值
          Object get(Object obj)獲取值
          package com.liming.myreflect;import java.lang.reflect.Field;public class ReflectDemo03 {public static void main(String[] args) throws Exception {//1、獲取類的字節碼文件Class<?> clazz = Class.forName("com.liming.myreflect.Student01");//2、獲取所有公共的成員變量Field[] fields1 = clazz.getFields();for (Field field : fields1) {System.out.println(field);}//獲取所有的成員變量Field[] fields2 = clazz.getDeclaredFields();for (Field field : fields2) {System.out.println(field);}//獲取單個公共成員變量Field gender = clazz.getField("gender");System.out.println(gender);//獲取單個成員變量(所有權限)Field name = clazz.getDeclaredField("name");System.out.println(name);//獲取權限修飾符int modifiers = name.getModifiers();System.out.println(modifiers);//獲取成員變量的名字String n = name.getName();System.out.println(n);//獲取成員變量的數據類型Class<?> type = name.getType();System.out.println(type);//獲取成員變量記錄的值Student01 stu = new Student01("zhangsan", 23, "男");name.setAccessible(true);String value = (String) name.get(stu);System.out.println(value);//修改對象里面記錄的值name.set(stu, "lisi");System.out.println(stu);} }

          7、獲取成員方法

          規則:

          ? 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 + "}";} }

          8、四道面試題

          你覺得反射好不好?好,有兩個方向

          第一個方向:無視修飾符訪問類中的內容。但是這種操作在開發中一般不用,都是框架底層來用的。
          第二個方向:反射可以跟配置文件結合起來使用,動態的創建對象,動態的調用方法。
          ?

          8.1、泛型擦除

          集合中的泛型只在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);} }

          8.2、修改字符串的內容

          字符串不可以修改的原因?
          字符串,在底層是一個byte類型的字節數組,名字叫做value

          private final 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);} }

          8.3、反射和配置文件結合動態獲取的練習(重點)

          需求: 利用反射根據文件中的不同類名和方法名,創建不同的對象并調用方法。

          分析:

          ①通過Properties加載配置文件

          ②得到類名和方法名

          ③通過類名反射得到Class對象

          ④通過Class對象創建一個對象

          ⑤通過Class對象得到方法

          ⑥調用方法

          代碼演示:
          properties配置文件:

          classname=com.liming.mytest.Student methodname=sleep public class ReflectDemo01 {public static void main(String[] args) throws Exception{//1.讀取配置文件的信息Properties prop = new Properties();FileInputStream fis = new FileInputStream("day15\\prop.properties");prop.load(fis);fis.close();System.out.println(prop);String classname = prop.get("classname") + "";String methodname = prop.get("methodname") + "";//2.獲取字節碼文件對象Class clazz = Class.forName(classname);//3.獲取構造器創建這個類的對象Constructor constructor = clazz.getDeclaredConstructor();constructor.setAccessible(true);Object o = constructor.newInstance();System.out.println(o);//4.獲取方法的對象Method sleep = clazz.getDeclaredMethod(methodname);sleep.setAccessible(true);//5.運行方法sleep.invoke(o);} }

          8.4、利用發射保存對象中的信息(重點)

          需求:對于任意一個對象,都可以把對象所有的字段名和值,保存到文件中去

          代碼演示:

          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.打開淘寶右邊的開關就可以了。怎...

          TOP
          国产初高中生视频在线观看|亚洲一区中文|久久亚洲欧美国产精品|黄色网站入口免费进人
          1. <nobr id="easjo"><address id="easjo"></address></nobr>

              <track id="easjo"><source id="easjo"></source></track>
              1. 
                

              2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
              3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>