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

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

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

      淺談Java的反射原理

      Java的編譯過程

      談及反射,不得不先了解一下,java的整個編譯過程,整體的java編譯過程可以參考 之前的一篇 一個java文件被執行的歷程 

      這里我們只針對 對象這一層級來討論,一個java文件,我們經過編譯,會得出 一個 字節碼文件(.class),這時候,進入解釋階段,編譯器會將這個.class加載進內存中,此時,它首先會生成一個 Class對象。

      Class對象與對象形成的過程

       Class對象

      在java世界里,一切皆對象。從某種意義上來說,java有兩種對象:實例對象和Class對象。對于每個類而言,JRE 都為其保留一個不變的 Class 類型的對象。

      Class對象會有以下幾個特點:
      1. Class 對象只能由系統建立對象
      2. 一個類在 JVM 中只會有一個Class實例
      3. –每個類的實例都會記得自己是由哪個 Class 實例所生成

      class對象包含的信息有:

      • 數據成員名
      • 內部方法
      • 構造方法
      • 集成自哪個接口、類

       對象的形成過程

      我們的實例對象是通過Class對象來創建的。

      每一個類都有一個Class對象,每當編譯一個新類就產生一個Class對象,基本類型 (boolean, byte, char, short, int, long, float, and double)有Class對象,數組有Class對象,就連關鍵字void也有Class對象(void.class)。Class對象對應著java.lang.Class類,如果說類是對象抽象和集合的話,那么Class類就是對類的抽象和集合。

      Class類沒有公共的構造方法,Class對象是在類加載的時候由Java虛擬機以及通過調用類加載器中的 defineClass 方法自動構造的,因此不能顯式地聲明一個Class對象。

      在類加載階段,類加載器首先檢查這個類的Class對象是否已經被加載。如果尚未加載,默認的類加載器就會根據類的全限定名查找.class文件。在這個類的字節碼被加載時,它們會接受驗證,以確保其沒有被破壞,并且不包含不良java代碼。一旦某個類的Class對象被載入內存,我們就可以它來創建這個類的所有對象。

      反射的本質及應用

        上面的基礎了解完畢,我們進入今天的主體,何為反射。

      所謂反射,官方的定義是: 指計算機程序在運行時(runtime) 可以訪問、檢測和修改它本身狀態或行為的一種能力。通俗說,反射就是程序在運行的時候能夠“觀察”并且修改自己的行為,是程序對自身的反思、自檢、修改。

        理解反射,首先得知道它的對立面,“正射”

      “正射”

      前面說到了Class對象,每個類的運行時的類型信息就是用Class對象表示的。系統會自動創建唯一一個Class對象,它包含了與類有關的信息。此時的java文件(一個類)處于一個中間狀態,并不是我們使用的對象,只有當我們使用  “ new  Object()”時,才會在JVM堆中根據這個Class對象來產生真正供我們使用的實例對象。其實也就是上面部分的對象的形成過程。

      正射的使用意義是,我事先定義了一個對象的某些東西,然后當我需要的時候,我會通知內存去創建這個對象,然后我事先知道這個對象有什么,所以我會精準的調用它的某個方法,某個成員變量。

      用一個我們習以為常的demo來舉一下例:

      class Human {
          String name;
          int age;
          String nation;
          Human(String name,int age,String nation) {
              this.name=name;
              this.age=age;
              this.nation=nation;
          }
          void changeName(String name){
              this.name=name;
          }
      }
      public class Main {
          public static void main(String[] args){
              Human human=new Human("張三",22,"中國");
              human.changeName("李四");
          }
      }

      在上面Main類的main方法中,我之所以可以寫human.changeName(“張三”) 是因為Human類也是我自己寫的,我清楚的知道,human作為Human的實例對象,可以調用changeName方法,如果我手抖寫了調用changeNamee方法,我也會立即改回來,因為我知道Human里沒有這個方法。假如我不知道Human里有沒有一個改名字的方法,即Human類對我來說是不透明的第三方類,我嘗試性的在程序中調用了一個newName方法,保存、編譯。這時候編譯器會通知我,這樣寫程序是不對的,Human里沒有一個叫newName的方法,編譯失敗。

      反射

      假如此時我只想使用對象某一個方法,某一個成員變量,而不想用其他的部分,這時候如果用“正射”(走正常的對象創建過程,new一下),就會被迫創建一個完整的該對象(有一說一,有點浪費),此時我可以根據類的全路徑+名稱,去內存中拿出這個類的Class對象,根據這個Class對象,靈活的去獲取這個類片面的信息。這種在運行時訪問、修改對象的狀態和行為,可以給程序帶來極大的靈活性。這便是反射

      反射可提供的功能

      1. 在運行時判斷任意一個對象所屬的類。

      2. 在運行時構造任意一個類的對象。

      3. 在運行時判斷任意一個類所具有的成員變量和方法。

      4. 在運行時調用任意一個對象的方法。

      5. 生成動態代理。

      詳細的API使用,可以查閱java的官方文檔。

      反射的使用

        使用Java注解配合反射可以開發出各種工具、框架。例如,Spring中的注解、工廠模式中創建對象的方式等

      這里實現一個用自定義注解 @AutoField 實現為屬性賦值。

      定義注解@AutoField 

      @Target({ElementType.FIELD})
      @Retention(RetentionPolicy.RUNTIME)
      public @interface AutoField {
          String value() default "";
      }

      編寫解析類。BeanFactory中的createBean方法通過反射拿到注解 @AutoField的值并賦給對象。

      public class BeanFactory {
          public static <T> T createBean(Class<T> clazz) {
              T o = null;
              try {
                  o = clazz.newInstance();
              } catch (InstantiationException e) {
                  throw new RuntimeException(e);
              } catch (IllegalAccessException e) {
                  throw new RuntimeException(e);
              }
              Field[] declaredFields = clazz.getDeclaredFields();
              for (Field declaredField : declaredFields) {
                  if (declaredField.isAnnotationPresent(AutoField.class)) {
                      AutoField AutoField = declaredField.getAnnotation(AutoField.class);
                      if (!declaredField.isAccessible())
                          declaredField.setAccessible(true);
                      try {
                          if (declaredField.getType().getSimpleName().equals("String"))
                              declaredField.set(o, AutoField.value());
                          else if (declaredField.getType().getSimpleName().equals("byte"))
                              declaredField.set(o, Byte.parseByte(AutoField.value()));
                          else if (declaredField.getType().getSimpleName().equals("short"))
                              declaredField.set(o, Short.parseShort(AutoField.value()));
                          else if (declaredField.getType().getSimpleName().equals("int"))
                              declaredField.set(o, Integer.parseInt(AutoField.value()));
                          else if (declaredField.getType().getSimpleName().equals("long"))
                              declaredField.set(o, Long.parseLong(AutoField.value()));
                          else if (declaredField.getType().getSimpleName().equals("float"))
                              declaredField.set(o, Float.parseFloat(AutoField.value()));
                          else if (declaredField.getType().getSimpleName().equals("double"))
                              declaredField.set(o, Double.parseDouble(AutoField.value()));
                          else if (declaredField.getType().getSimpleName().equals("long"))
                              declaredField.set(o, Long.parseLong(AutoField.value()));
                          else if (declaredField.getType().getSimpleName().equals("boolean"))
                              declaredField.set(o, Boolean.parseBoolean(AutoField.value()));
                          else
                              throw new RuntimeException(declaredField.getName() + " of " + clazz.getName() + " is not a value field");
                      } catch (IllegalAccessException e) {
                          throw new RuntimeException(e);
                      }
      
                  }
              }
              return o;
          }
      }

        定義實體類

      public class Teacher {
      
        @AutoField("12223")
        private int id;
      
        @AutoField("Zhang")
        private String name;
      
        @AutoField("20")
        private int age;
      
        @AutoField("false")
        private boolean isProfessor;
      
        @AutoField("G")
        private String sex;
      
        @AutoField("CQU")
        private String school;
      
        public int getId() {
          return id;
        }
      
        public String getName() {
          return name;
        }
      
        public int getAge() {
          return age;
        }
      
        public boolean isProfessor() {
          return isProfessor;
        }
      
        public String getSex() {
          return sex;
        }
      
        public String getSchool() {
          return school;
        }
      
        public void setId(int id) {
          this.id = id;
        }
      
        public void setName(String name) {
          this.name = name;
        }
      
        public void setAge(int age) {
          this.age = age;
        }
      
        public void setProfessor(boolean professor) {
          isProfessor = professor;
        }
      
        public void setSex(String sex) {
          this.sex = sex;
        }
      
        public void setSchool(String school) {
          this.school = school;
        }
      
        @Override
        public String toString() {
          return "Teacher{" +
            "id=" + id +
            ", name='" + name + '\'' +
            ", age=" + age +
            ", isProfessor=" + isProfessor +
            ", sex=" + sex +
            ", school='" + school + '\'' +
          '}';
        }
      }

       

      測試

      public class Main {
          public static void main(String[] args) {
              Teacher teacher = BeanFactory.createBean(Teacher.class);
              System.out.println(teacher);
          }

       

       

       

        

      posted @ 2021-03-13 11:45  糖拌西紅柿  閱讀(639)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 在线一区二区中文字幕| 亚洲第四色在线中文字幕| 伦伦影院午夜理论片| 九九在线精品国产| 国产亚洲精品自在久久vr| 忘忧草日本在线播放www| 国产人妇三级视频在线观看| 男人一天堂精品国产乱码| 午夜福利精品国产二区| 欧美熟妇乱子伦XX视频| 亚洲高清国产拍精品熟女| 台湾佬自拍偷区亚洲综合| 国产精品自拍中文字幕| 国产午夜福利不卡在线观看| 国产亚洲中文字幕久久网| 18av千部影片| 国产亚洲精品自在久久vr| 日韩一区二区三区在线观院| 国产区二区三区在线观看| 亚洲一区二区三区啪啪| 人妻av中文字幕无码专区| 青青热在线精品视频免费观看| 国产亚洲一二三区精品| 女人喷水高潮时的视频网站| 无码专区 人妻系列 在线| 粗壮挺进人妻水蜜桃成熟| 亚洲国产美女精品久久久久| 日韩国产成人精品视频| 欧美性xxxxx极品少妇| 国产真人无遮挡免费视频| 免费人成网站免费看视频| 国产综合久久久久鬼色| 韩国午夜福利片在线观看| 国产乱码精品一区二区三上| 日韩蜜桃AV无码中文字幕不卡高清一区二区 | 亚洲中文字幕久久精品码| 亚洲国产一区二区三区| 中文字幕无码免费不卡视频| 中文国产不卡一区二区| 色午夜一av男人的天堂| 好日子在线观看视频大全免费动漫|