<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      JAVA深化篇_40—— 反射機制介紹

      反射機制介紹

      什么是反射

      Java 反射機制是Java語言一個很重要的特性,它使得Java具有了“動態性”。在Java程序運行時,對于任意的一個類,我們能不能知道這個類有哪些屬性和方法呢?對于任意的一個對象,我們又能不能調用它任意的方法?答案是肯定的!這種動態獲取類的信息以及動態調用對象方法的功能就來自于Java 語言的反射(Reflection)機制。

      反射的作用

      簡單來說兩個作用,RTTI(運行時類型識別)和DC(動態創建)。

      我們知道反射機制允許程序在運行時取得任何一個已知名稱的class的內部信息,包括其modifiers(修飾符),fields(屬性),methods(方法)等,并可于運行時改變fields內容或調用methods。那么我們便可以更靈活的編寫代碼,代碼可以在運行時裝配,無需在組件之間進行源代碼鏈接,降低代碼的耦合度;還有動態代理的實現等等;但是需要注意的是反射使用不當會造成很高的資源消耗!


      創建對象過程

      Java創建對象的三個階段

      創建對象時內存結構

      Users user = new Users();
      

      實際上,我們在加載任何一個類時都會在方法區中建立“這個類對應的Class對象”,由于==“Class對象”包含了這個類的整個結構信息==,所以我們可以通過這個“Class對象”來操作這個類。

      我們要使用一個類,首先要加載類;加載完類之后,在堆內存中,就產生了一個 Class 類型的對象(一個類只有一個 Class 對象),這個對象就包含了完整的類的結構信息。我們可以通過這個對象知道類的結構。這個對象就像一面鏡子,透過這個鏡子可以看到類的結構,所以,我們形象的稱之為:反射。 因此,“Class對象”是反射機制的核心。

      反射的具體實現

      獲取Class對象的三種方式

      • 通過getClass()方法;
      • 通過.class 靜態屬性;
      • 通過Class類中的靜態方法forName();

      創建Users類

      public class Users {
        private String username;
        private int userage;
      
      
        public String getUsername() {
          return username;
         }
      
      
        public void setUsername(String username) {
          this.username = username;
         }
      
      
        public int getUserage() {
          return userage;
         }
      
      
        public void setUserage(int userage) {
          this.userage = userage;
         }
      }
      
      
      
      
      通過getClass()方法獲取Class對象
      /*
      * 通過getClass()方法獲取該類的Class對象
      getClass()為Object類下的非靜態方法,在使用時需要先實例化對象
       */
      public class GetClass1 {
        public static void main(String[] args) {
          Users users = new Users();
          Users users1 = new Users();
          Class clazz = users.getClass();
          System.out.println(clazz);
          System.out.println(clazz.getName());
          System.out.println(users.getClass() == users1.getClass());
         }
      }
      
      
      通過forName()獲取Class對象
      /**
       * 通過Class.forName("class Name")獲取Class對象
       */
      public class GetClass3 {
        public static void main(String[] args)throws Exception {
          Class clazz = Class.forName("com.java.Users");
          Class clazz2 = Class.forName("com.java.Users");
          System.out.println(clazz);
          System.out.println(clazz.getName());
          System.out.println(clazz == clazz2);
         }
      }
      
      
      通過.class 靜態屬性獲取Class對象
      /**
       * .class靜態屬性獲取Class對象
       */
      public class GetClass2 {
        public static void main(String[] args) {
          Class clazz = Users.class;
          Class clazz2 = Users.class;
          System.out.println(clazz);
          System.out.println(clazz.getName());
          System.out.println(clazz == clazz2);
         }
      }
      
      

      獲取類的構造方法

      方法介紹

      方法名描述
      getDeclaredConstructors()返回 Constructor 對象的一個數組,這些對象反映此 Class 對象表示的類聲明的所有構造方法
      getConstructors()返回一個包含某些 Constructor 對象的數組,這些對象反映此 Class 對象所表示的類的所有公共(public)構造方法
      getConstructor(Class<?>… parameterTypes)返回一個 Constructor 對象,它反映此 Class 對象所表示的類的指定公共(public)構造方法。
      getDeclaredConstructor(Class<?>… parameterTypes)返回一個 Constructor 對象,該對象反映此 Class 對象所表示的類或接口的指定構造方法。

      方法使用

      修改Users類

      public class Users {
        private String username;
        private int userage;
        public Users(){
         }
          
        public Users(String username,int userage){
          this.username= username;
          this.userage=userage;
         }
          
        public Users(String username){
          this.username= username;
         }
          
        private Users(int userage){
          this.userage = userage;
         }
      
      
        public String getUsername() {
          return username;
         }
      
      
        public void setUsername(String username) {
          this.username = username;
         }
      
      
        public int getUserage() {
          return userage;
         }
      
      
        public void setUserage(int userage) {
          this.userage = userage;
         }
      }
      
      

      獲取構造方法

      public class GetConstructor {
        public static void main(String[] args)throws Exception {
          Class clazz = Users.class;
          Constructor[] arr = clazz.getDeclaredConstructors();
          for(Constructor c:arr){
            System.out.println(c);
           }
          System.out.println("---------------------");
            
          Constructor[] arr1 = clazz.getConstructors();
          for(Constructor c:arr1){
            System.out.println(c);
           }
          System.out.println("------------------------");
            
          Constructor c =  clazz.getDeclaredConstructor(int.class);
          System.out.println(c);
          System.out.println("------------------------");
            
          Constructor c1 =  clazz.getConstructor(null);
          System.out.println(c1);
         }
      }
      
      
      通過構造方法創建對象 newInstance()
      /**
      **通過反射實例化對象
      */
      public class GetConstructor2 {
          
          public static void main(String[] args) throws Exception{
              //創建類對象
              Class<Users> usersClass = Users.class;
              //通過類對象獲取指定的構造方法對象
              Constructor<Users> constructor = usersClass.getConstructor(String.class, int.class);
              //通過指定的構造方法對象創建對象
              Users users = constructor.newInstance("zhangsan", 20);
      		
              System.out.println(users);
          }
      }
      

      獲取類的成員變量

      方法介紹

      方法名描述
      getFields()返回Field類型的一個數組,其中包含 Field對象的所有公共(public)字段。
      getDeclaredFields()返回Field類型的一個數組,其中包含 Field對象的所有字段。
      getField(String fieldName)返回一個公共成員的Field指定對象。
      getDeclaredField(String fieldName)返回一個 Field指定對象。

      方法使用

      修改Users類

      public class Users {
        private String username;
        public int userage;
        public Users(){
         }
        public Users(String username,int userage){
          this.username= username;
          this.userage=userage;
         }
        public Users(String username){
          this.username= username;
         }
        private Users(int userage){
          this.userage = userage;
         }
      
      
        public String getUsername() {
          return username;
         }
      
      
        public void setUsername(String username) {
          this.username = username;
         }
      
      
        public int getUserage() {
          return userage;
         }
      
      
        public void setUserage(int userage) {
          this.userage = userage;
         }
      }
      
      
      
      

      獲取成員變量

      public class GetField {
          
          public static void main(String[] args) throws Exception{
              Class<Users> usersClass = Users.class;
              Field[] fields = usersClass.getFields();
              for(Field field:fields){
                  System.out.println(field);
              }
              System.out.println("===================");
              Field[] declaredFields = usersClass.getDeclaredFields();
              for(Field field:declaredFields){
                  System.out.println(field);
              }
              System.out.println("=================");
              Field userName = usersClass.getDeclaredField("userName");
              System.out.println(userName);
              System.out.println("=================");
              Field userAge = usersClass.getField("userAge");
              System.out.println(userAge);
          }
      }
      

      操作成員變量 先實例化對象

      public class GetField2 {
          public static void main(String[] args)throws Exception {
              //獲取Users類的類對象
              Class<Users> usersClass = Users.class;
              //獲取類的成員變量
              Field userAge = usersClass.getField("userAge");
              //通過構造方法實例化users對象
              Users users = usersClass.getConstructor(null).newInstance();
              //給指定成員變量賦值
              userAge.set(users,20);
              System.out.println(userAge.get(users));
          }
      }
      
      

      獲取類的方法

      方法介紹

      方法名描述
      getMethods()返回一個Method類型的數組,其中包含 所有公共(public)方法。包含父類中的(public)方法!!!!!
      getDeclaredMethods()返回一個Method類型的數組,其中包含 所有方法。
      getMethod(String name, Class<?>… parameterTypes)返回一個公共的Method方法對象。
      getDeclaredMethod(String name, Class<?>… parameterTypes)返回一個方法Method對象

      方法使用

      修改Users類

      public class Users {
          private String userName;
          public int userAge;
      
          private Users(String userName){
              this.userName = userName;
          }
          public Users(String userName, int userAge){
              this.userName = userName;
              this.userAge = userAge;
          }
      
          public Users(){
      
          }
      
          public Users(int userAge){
              this.userAge = userAge;
          }
      
      
          public String getUserName() {
              return userName;
          }
      
          public void setUserName(String userName) {
              this.userName = userName;
          }
      
          public int getUserAge() {
              return userAge;
          }
      
          public void setUserAge(int userAge) {
              this.userAge = userAge;
          }
      
      
          private void sing(){
              System.out.println("zhangsan愛唱歌");
          }
      
      
          @Override
          public String toString() {
              return "Users{" +
                      "userName='" + userName + '\'' +
                      ", userAge=" + userAge +
                      '}';
          }
      }
      
      

      獲取方法

      public class GetMethod {
          
          public static void main(String[] args) throws Exception{
              Class<Users> usersClass = Users.class;
              Method[] classMethods = usersClass.getMethods();
              for(Method method : classMethods){
                  System.out.println(method);
                  System.out.println(method.getName());
              }
              System.out.println("----------------");
              Method[] declaredMethods = usersClass.getDeclaredMethods();
              for(Method method : declaredMethods){
                  System.out.println(method);
                  System.out.println(method.getName());
              }
              System.out.println("=================");
              Method setUserAge = usersClass.getMethod("setUserAge", int.class);
              System.out.println(setUserAge.getName());
              System.out.println(setUserAge);
              System.out.println("===============");
              Method sing = usersClass.getDeclaredMethod("sing");
              System.out.println(sing);
              System.out.println(sing.getName());
          }
      }
      
      
      調用方法 invoke( )
      public class GetMethod2 {
          
          public static void main(String[] args)throws Exception {
              //實例化類對象
              Class<Users> usersClass = Users.class;
              Method setUserName = usersClass.getMethod("setUserName", String.class);
              //實例化對象
              Users users = usersClass.getConstructor(null).newInstance();
              //通過setUserName賦值
              setUserName.invoke(users,"zhangsan");
              //通過getUserName獲取值
              Method getUserName = usersClass.getMethod("getUserName");
              Object userName = getUserName.invoke(users);
              System.out.println(userName);
      
          }
      }
      
      

      獲取類的其他信息

      public class GetClassInfo {
      
          public static void main(String[] args) {
              Class<Users> usersClass = Users.class;
      
              //獲取包名
              Package usersClassPackage = usersClass.getPackage();
              System.out.println(usersClassPackage);
              System.out.println(usersClassPackage.getName());
      
              //獲取類名
              String usersClassName = usersClass.getName();
              System.out.println(usersClassName);
      
              //獲取超類
              Class<? super Users> superclass = usersClass.getSuperclass();
              System.out.println(superclass.getName());
      
              //獲取所有接口
              Class<?>[] classInterfaces = usersClass.getInterfaces();
              for(Class interfaces:classInterfaces){
                  System.out.println(interfaces.getName());
              }
          }
      }
      
      


      反射機制的效率

      由于Java反射是要解析字節碼,將內存中的對象進行解析,包括了一些動態類型,而JVM無法對這些代碼進行優化。因此,反射操作的效率要比那些非反射操作低得多!

      接下來我們做個簡單的測試來直接感受一下反射的效率。

      反射機制的效率測試

      public class Test {
          public static void main(String[] args) throws Exception{
      
              Class<?> aClass = Class.forName("com.itbaizhan.Users");
              Object o = aClass.getConstructor(null).newInstance();
              Method setUsername = aClass.getMethod("setUserName",String.class);
              long reflectStart = System.currentTimeMillis();
              for(int i =0;i<100000000;i++){
                  setUsername.invoke(o,"zhangsan");
              }
              long reflectEnd = System.currentTimeMillis();
      
              long start = System.currentTimeMillis();
              Users u =new Users();
              for(int i=0;i<100000000;i++){
                  u.setUserName("zhangsan");
              }
              long end = System.currentTimeMillis();
      
              System.out.println("反射執行時間:"+(reflectEnd-reflectStart));
              System.out.println("普通方式執行時間:"+(end-start));
          }
      }
      反射執行時間:169
      普通方式執行時間:0
      
      

      setAccessible方法

      setAccessible()方法:

      setAccessible是啟用和禁用訪問安全檢查的開關。值為 true 則指示反射的對象在使用時應該取消 Java 語言訪問檢查。值為 false 則指示反射的對象應該實施 Java 語言訪問檢查;默認值為false。

      由于JDK的安全檢查耗時較多.所以通過setAccessible(true)的方式關閉安全檢查就可以達到提升反射速度的目的。

      public class Test2 {
          public static void main(String[] args) throws Exception{
              Class<Users> usersClass = Users.class;
              Users users = usersClass.getConstructor(null).newInstance();
              Field userName = usersClass.getDeclaredField("userName");
              //忽略安全檢查
              userName.setAccessible(true);
              userName.set(users,"zhangsan");
              Object o = userName.get(users);
              System.out.println(o);
      
              Method sing = usersClass.getDeclaredMethod("sing");
              //忽略安全檢查
              sing.setAccessible(true);
              sing.invoke(users);
      
          }
      }
      

      反射總結

      • Java 反射機制是Java語言一個很重要的特性,它使得Java具有了==“動態性”。==
      • 反射機制的優點:
        • 更靈活。
        • 更開放。
      • 反射機制的缺點:
        • 降低程序執行的效率
        • 增加代碼維護的困難。
      • 獲取Class類的對象的三種方式:
        • 運用getClass()。(非靜態方法,需要先實例化)
        • 運用.class 語法
        • 運用Class.forName()(最常被使用)
      • 反射機制的常見操作
        • 動態加載類、動態獲取類的信息(屬性、方法、構造器)。
        • 動態構造對象。
        • 動態調用類和對象的任意方法。
        • 動態調用和處理屬性。
        • 獲取泛型信息。
        • 處理注解。
      posted @ 2023-11-13 07:33  Gjq-  閱讀(37)  評論(0)    收藏  舉報  來源
      主站蜘蛛池模板: 久久久精品94久久精品| 午夜国人精品av免费看| 浪潮av色综合久久天堂| 久久毛片少妇高潮| 亚洲色无码专区一区| 在线播放深夜精品三级| 四虎影院176| 青青草一区在线观看视频| 国产一区二区黄色在线观看| 公天天吃我奶躁我的在线观看| 国产伦精品一区二区三区| 强伦人妻一区二区三区| 亚洲综合色网一区二区三区| 国产精品一区二区三区黄| 国产综合色精品一区二区三区| 亚洲欧洲精品日韩av| 色窝窝免费播放视频在线| 克什克腾旗| 国产精品∧v在线观看| 亚洲亚洲人成综合网络| 99精品热在线在线观看视| 国产情侣激情在线对白| 夜夜夜高潮夜夜爽夜夜爰爰| 亚洲国产精品午夜福利| 韩日午夜在线资源一区二区| 九九热免费公开视频在线| 办公室强奷漂亮少妇视频| 国产无遮挡猛进猛出免费软件| 黑森林福利视频导航| 久久精产国品一二三产品| 亚洲婷婷综合色高清在线| 久久精品国产大片免费观看| 亚洲日本高清一区二区三区| 国产精品久久中文字幕| 夜夜添无码试看一区二区三区| 国产精品伦人视频免费看| 亚洲人妻中文字幕一区| 亚洲精品乱码久久久久久| 97se亚洲国产综合自在线观看| 国产精品欧美福利久久| 男女裸体影院高潮|