首頁 > Java > java教程 > Java內省機制怎麼實現

Java內省機制怎麼實現

WBOY
發布: 2023-04-24 08:04:06
轉載
1640 人瀏覽過

    概念

    JavaBean

    在實際程式設計中,我們常常需要一些用來包裝值物件的類別,例如Student、 Employee 、Order,這些類別中往往沒有業務方法,只是為了把需要處理的實體物件進行封裝,有這樣的特徵:

    • ##屬性都是私有的;

    • 有無參的public建構方法;

    • 對私有屬性依需求提供公有的getXxx方法以及setXxx方法;

    例如:屬性名稱為name,則有getName方法傳回屬性name值,setName方法設定name值;注意方法的名稱通常是get或set加上屬性名稱,並把屬性名稱的首字母大寫;這些方法稱為getters/setters;getters必須有返回值沒有方法參數; setter值沒有回傳值,有方法參數;

    例如下面的例子:

    Java內省機制怎麼實現# #符合這些特徵的類,稱為JavaBean;

    內省

    內省(Inspector)機制就是基於反射的基礎, Java語言對Bean類別屬性、事件的一種缺失省處理方法。

    只要類別中有getXXX方法,或setXXX方法,或同時有getXXX及setXXX方法,其中getXXX方法沒有方法參數,有回傳值;setXXX方法沒有回傳值,有一個方法參數;那麼內省機制就認為XXX為一個屬性;

    例如下面程式碼

    Employee類別中根本沒有聲明age屬性,只是聲明了這樣的getter和setter.內省機制就認為age是屬性

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    package com.shixun.introspector;

     

    public class Employee {

        private String name;

        private Double score;

     

        // age将被内省认为是属性

        public int getAge(){

            return 30;

        }

     

        // name将被内省认为是属性

        public String getName() {

            return name;

        }

     

        public void setName(String name) {

            this.name = name;

        }

     

        // score将被内省认为是属性

        public Double getScore() {

            return score;

        }

     

        public void setScore(Double score) {

            this.score = score;

        }

     

        public static void main(String[] args) {

             

     

        }

    }

    登入後複製

    相關API

    與Java內省有關的主要類別及介面有:

    • java.beans.Introspector類別

      : 為取得JavaBean屬性、事件、方法提供了標準方法;通常使用其中的getBeanInfo方法傳回BeanInfo物件;

    • Java.beans.BeanInfo介面

      :不能直接實例化,通常透過Introspector類別傳回該類型對象,提供了傳回屬性描述子物件(PropertyDescriptor)、方法描述子物件(MethodDescriptor) 、 bean描述子(BeanDescriptor)物件的方法;

    • #Java.beans.PropertyDescriptor類別

      :用來描述一個屬性,該屬性有getter及setter方法;

      ##可以使用PropertyDescriptor類別的方法取得屬性相關的信息,例如getName方法傳回屬性的名字:
    PropertyDescriptor類別中定義了方法可以取得該屬性的getter和setter方法

    方法方法描述Method getReadMethod()回屬性對應的getter方法物件;Method getWriteMethod()回屬性對應的setter方法物件;下面我們來用程式碼深入探究:
    程式碼案例:取得屬性相關資訊

    Employee如上面程式碼所示,繼續寫主函數進行測試

    先用BeanInfo介面取得BeanInfo的對象,再透過BeanInfo物件取得PropertyDescriptor屬性描述

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    //获取BeanInfo的对象

     BeanInfo employeeBeanInfo = Introspector.getBeanInfo(Employee.class);

     //通过BeanInfo对象获取PropertyDescriptor属性描述

     PropertyDescriptor[] propertyDescriptors = employeeBeanInfo.getPropertyDescriptors();

     System.out.println("通过Inspector内省机制获取JavaBean属性======= 打印所有信息 ====================");

     Arrays.stream(propertyDescriptors).forEach(f->{

         System.out.println("====================================");

         System.out.println("属性名:"+f.getName());

         System.out.println("类型:"+f.getPropertyType());

         System.out.println("get方法:"+f.getReadMethod());

         System.out.println("set方法:"+f.getWriteMethod());

     });

     

    // 或者用增强for

    System.out.println("通过Inspector内省机制获取JavaBean属性======= 打印所有信息 ====================");

    for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {

        System.out.println("====================================");

        System.out.println("名字:" + propertyDescriptor.getName());

        System.out.println("类型:" + propertyDescriptor.getPropertyType());

        System.out.println("get方法:" + propertyDescriptor.getReadMethod());

        System.out.println("set方法:" + propertyDescriptor.getWriteMethod());

    }

    登入後複製

    運行結果如下:

    我們也可以透過反射來呼叫這裡取得的get或set方法Java內省機制怎麼實現

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    //创建Employee的对象

    Class<?> clazz = Class.forName("com.shixun.introspector.Employee");

    Object employee = clazz.newInstance();

     

    //遍历属性描述对象

    for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {

        //打印属性名称

        System.out.println(propertyDescriptor.getName());

        //判断属性名称是不是name

        if (propertyDescriptor.getName().equals("name")) {

            //setter方法

            Method writeMethod = propertyDescriptor.getWriteMethod();

            //调用setName方法

            writeMethod.invoke(employee, "jack");

            //getter方法

            Method readMethod = propertyDescriptor.getReadMethod();

            //调用getName方法

            Object nameValue = readMethod.invoke(employee);

            System.out.println("name属性的值为:" + nameValue);

        }

        //判断属性名称是否为score

        if (propertyDescriptor.getName().equals("score")) {

            //setter方法

            Method scoreWriteMethod = propertyDescriptor.getWriteMethod();

            //调用setScore方法

            scoreWriteMethod.invoke(employee, new Double(3000));

            //getter方法

            Method scoreReadMethod = propertyDescriptor.getReadMethod();

            Object scoreValue = scoreReadMethod.invoke(employee);

            System.out.println("score属性的值为:" + scoreValue);

        }

    }

    System.out.println("当前对象的信息:"+employee.toString());

    登入後複製

    運行結果如下所示:

    Java內省機制怎麼實現

    全部程式碼附在最下方! ! ! ! ! !

    內省屬性的注意事項

    很多框架都使用了內省機制來擷取物件的屬性,定義屬性名稱時,名字最好起碼以兩個小寫字母開頭,例如stuName,而不要使用sName,某些情況下,可能會導致檢索屬性失敗;
    • 內省機制檢索屬性時,是根據getter和setter方法確認屬性名字,而不是根據類別裡宣告的成員變數名稱決定;
    • 完整程式碼
    • 1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      85

      86

      87

      88

      89

      90

      91

      92

      93

      94

      95

      96

      97

      98

      99

      100

      101

      102

      103

      104

      105

      106

      107

      package com.shixun.introspector;

       

      import java.beans.BeanInfo;

      import java.beans.IntrospectionException;

      import java.beans.Introspector;

      import java.beans.PropertyDescriptor;

      import java.lang.reflect.InvocationTargetException;

      import java.lang.reflect.Method;

      import java.util.Arrays;

       

      public class Employee {

          private String name;

          private Double score;

       

          // age将被内省认为是属性

          public int getAge() {

              return 30;

          }

       

          // name将被内省认为是属性

          public String getName() {

              return name;

          }

       

          public void setName(String name) {

              this.name = name;

          }

       

          // score将被内省认为是属性

          public Double getScore() {

              return score;

          }

       

          public void setScore(Double score) {

              this.score = score;

          }

       

          @Override

          public String toString() {

              return "Employee{" +

                      "name=&#39;" + name + &#39;\&#39;&#39; +

                      ", score=" + score +

                      &#39;}&#39;;

          }

       

          public static void main(String[] args) throws ClassNotFoundException, IntrospectionException, IllegalAccessException, InstantiationException, InvocationTargetException {

              //获取BeanInfo的对象

              BeanInfo employeeBeanInfo = Introspector.getBeanInfo(Employee.class);

       

              //通过BeanInfo对象获取PropertyDescriptor属性描述

              PropertyDescriptor[] propertyDescriptors = employeeBeanInfo.getPropertyDescriptors();

      //        System.out.println("通过Inspector内省机制获取JavaBean属性======= 打印所有信息 ====================");

      //        Arrays.stream(propertyDescriptors).forEach(f->{

      //            System.out.println("====================================");

      //            System.out.println("属性名:"+f.getName());

      //            System.out.println("类型:"+f.getPropertyType());

      //            System.out.println("get方法:"+f.getReadMethod());

      //            System.out.println("set方法:"+f.getWriteMethod());

      //        });

      //

      //

      //

      //        System.out.println("通过Inspector内省机制获取JavaBean属性======= 打印所有信息 ====================");

      //

      //        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {

      //            System.out.println("名字:" + propertyDescriptor.getName());

      //            System.out.println("类型:" + propertyDescriptor.getPropertyType());

      //            System.out.println("get方法:" + propertyDescriptor.getReadMethod());

      //            System.out.println("set方法:" + propertyDescriptor.getWriteMethod());

      //        }

       

              //创建Employee的对象

              Class<?> clazz = Class.forName("com.shixun.introspector.Employee");

              Object employee = clazz.newInstance();

       

              //遍历属性描述对象

              for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {

                  //打印属性名称

                  System.out.println(propertyDescriptor.getName());

                  //判断属性名称是不是name

                  if (propertyDescriptor.getName().equals("name")) {

                      //setter方法

                      Method writeMethod = propertyDescriptor.getWriteMethod();

                      //调用setName方法

                      writeMethod.invoke(employee, "jack");

                      //getter方法

                      Method readMethod = propertyDescriptor.getReadMethod();

                      //调用getName方法

                      Object nameValue = readMethod.invoke(employee);

                      System.out.println("name属性的值为:" + nameValue);

                  }

                  //判断属性名称是否为score

                  if (propertyDescriptor.getName().equals("score")) {

                      //setter方法

                      Method scoreWriteMethod = propertyDescriptor.getWriteMethod();

                      //调用setScore方法

                      scoreWriteMethod.invoke(employee, new Double(3000));

                      //getter方法

                      Method scoreReadMethod = propertyDescriptor.getReadMethod();

                      Object scoreValue = scoreReadMethod.invoke(employee);

                      System.out.println("score属性的值为:" + scoreValue);

                  }

              }

       

              System.out.println("当前对象的信息:"+employee.toString());

          }

      }

      登入後複製

      以上是Java內省機制怎麼實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    相關標籤:
    來源:yisu.com
    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
    熱門教學
    更多>
    最新下載
    更多>
    網站特效
    網站源碼
    網站素材
    前端模板