<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          淺談Java的反射原理

          共 12924字,需瀏覽 26分鐘

           ·

          2021-03-18 09:42

          點擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時間送達(dá)

            作者 |  Deep Blue

          來源 |  urlify.cn/rqU36f

          1、Java的編譯過程

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

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


          2、Class對象與對象形成的過程

              2.1Class對象

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

          Class對象會有以下幾個特點:

          1. Class 對象只能由系統(tǒng)建立對象

          2. 一個類在 JVM 中只會有一個Class實例

          3. –每個類的實例都會記得自己是由哪個 Class 實例所生成

          class對象包含的信息有:

          • 數(shù)據(jù)成員名

          • 內(nèi)部方法

          • 構(gòu)造方法

          • 集成自哪個接口、類


                2.2對象的形成過程

          我們的實例對象是通過Class對象來創(chuàng)建的。

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

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

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


          3、反射的本質(zhì)及應(yīng)用

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

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

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


             3.1“正射”

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

          正射的使用意義是,我事先定義了一個對象的某些東西,然后當(dāng)我需要的時候,我會通知內(nèi)存去創(chuàng)建這個對象,然后我事先知道這個對象有什么,所以我會精準(zhǔn)的調(diào)用它的某個方法,某個成員變量。

          用一個我們習(xí)以為常的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的實例對象,可以調(diào)用changeName方法,如果我手抖寫了調(diào)用changeNamee方法,我也會立即改回來,因為我知道Human里沒有這個方法。假如我不知道Human里有沒有一個改名字的方法,即Human類對我來說是不透明的第三方類,我嘗試性的在程序中調(diào)用了一個newName方法,保存、編譯。這時候編譯器會通知我,這樣寫程序是不對的,Human里沒有一個叫newName的方法,編譯失敗。


          3.2反射

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


          3.3反射可提供的功能

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

          2. 在運行時構(gòu)造任意一個類的對象。

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

          4. 在運行時調(diào)用任意一個對象的方法。

          5. 生成動態(tài)代理。

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


          3.4反射的使用

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

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

          定義注解@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);
              }





          粉絲福利:Java從入門到入土學(xué)習(xí)路線圖

          ??????

          ??長按上方微信二維碼 2 秒


          感謝點贊支持下哈 

          瀏覽 51
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色国产无码 | 国产成人免费做爰视频 | 中国免费黄色视频 | 国产精品久久久久久高潮 | 久久激情精品 |