程序員內(nèi)功修煉大法【反射、內(nèi)省】(下)

      網(wǎng)友投稿 870 2022-05-30

      五、內(nèi)省

      5.1、JavaBean

      JavaBean 是 Java 中最重要的一個可重用的組件(減少代碼重復(fù),可重用,封裝業(yè)務(wù)邏輯,封裝數(shù)據(jù))。

      5.1.1、JavaBean 的規(guī)范要求

      使用 public 修飾。

      字段私有化。

      提供 get/set 方法。

      公共的無參數(shù)的構(gòu)造器(使用反射,使用字節(jié)碼對象.newInstance去創(chuàng)建對象)。

      5.1.2、三大成員

      事件

      方法

      屬性

      5.1.3、什么是屬性

      JavaBean 可以封裝數(shù)據(jù),就是將數(shù)據(jù)保存到一個 bean 對象的屬性中的。

      屬性不是字段,屬性是通過get/set方法推導(dǎo)出來的。

      **規(guī)范的get方法/獲取方法/讀方法:**public修飾、無參數(shù)、有返回、get開頭。

      **規(guī)范的set方法/設(shè)置方法/寫方法:**public修飾、有參數(shù)、無返回、set開頭。

      注意:

      只要是標準的get/set方法,就存在屬性,不一定非得是通過工具自動生成的規(guī)范的寫法。

      字段是 boolean 的,讀方法不是 get 開頭,而是 is 開頭。

      5.2、內(nèi)省的概述

      JavaBean是一個非常常用的組件,無外乎就是操作里面的屬性。而之前我們要獲取JavaBean中的方法,如果使用反射非常麻煩,于是SUN公司專門提供了一套操作 JavaBean 屬性的API: 內(nèi)省(Introspector)。

      5.3、內(nèi)省的作用

      獲取到屬性名和屬性類型等相關(guān)狀態(tài)信息。

      獲取屬性對應(yīng)的讀寫方法操作屬性的值等操作方式。

      5.4、內(nèi)省常用的API

      通過字節(jié)碼對象,獲取到JavaBean的描述對象,返回 JavaBean的描述對象

      public static BeanInfo getBeanInfo(Class beanClass, Class stopClass);

      通過 JavaBean 描述對象獲取屬性描述器

      PropertyDescriptor[] getPropertyDescriptors();

      通過屬性描述器,獲取到屬性名、屬性類型、讀寫(getter/setter)方法

      獲取屬性名:public String getName();

      獲取屬性類型:public Class getPropertyType();

      獲取讀方法(getter):public Method getReadMethod();

      獲取寫方法(setter):public Method getWriteMethod();

      通過字節(jié)碼對象來獲取BeanInfo對象的時候,默認會內(nèi)省當前字節(jié)碼對象以及其所有的父類的信息。比如:getBeanInfo(A.class),其實它也會內(nèi)省A的父類,如Object的信息。一般來說,我們不關(guān)心父類的屬性相關(guān)信息,此時可以調(diào)用getBeanInfo的重載方法:getBeanInfo(beanClass,stopClass)。

      示范:BeanInfo beanInfo = Introspector.getBeanInfo(Person.class,Object.class);

      package com.day03.IntrospectorDemo; import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; /** * @author Xiao_Lin * @date 2020/12/29 13:37 */ public class TestIntrospector { public static void main(String[] args) throws Exception { //創(chuàng)建對象 Student student = Student.class.newInstance(); //把 JavaBean 轉(zhuǎn)成 beanInfo BeanInfo beanInfo = Introspector.getBeanInfo(student.getClass(),Object.class); //通過通過beanInfo獲取所有屬性 PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); //遍歷屬性描述器數(shù)組,獲取到每個屬性描述器 for (PropertyDescriptor pd : propertyDescriptors) { //獲取屬性名 System.out.println("屬性名 = " + pd.getName()); //獲取屬性類型 System.out.println("屬性類型 = " + pd.getPropertyType()); //獲取屬性的getter/setter方法 Method getMethod = pd.getReadMethod(); System.out.println("get方法 = " +getMethod); Method setMethod = pd.getWriteMethod(); System.out.println("set方法 = " +setMethod); //調(diào)用age屬性的set方法 if ("age".equals(pd.getName())){ //執(zhí)行age的set方法,invoke參數(shù)含義是給哪個對象賦予哪個值 setMethod.invoke(student,22); } //再次執(zhí)行g(shù)et方法 System.out.println(student.getAge()); } } }

      5.5、JavaBean 和 Map 之間的轉(zhuǎn)化

      map和JavaBean的結(jié)構(gòu)很類似,我們可以將 map 和 JavaBean 相互轉(zhuǎn)換.將key和屬性名一 一對應(yīng)起來

      5.5.1、JavaBean轉(zhuǎn)map

      // Javabean 轉(zhuǎn) map public static Map BeanToMap(Object obj) throws Exception{ Map map = new HashMap<>(); //通過內(nèi)省獲得所有屬性 BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass(), Object.class); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor pd : pds) { //獲取屬性名作為key String key = pd.getName(); //獲取屬性的getter方法并且調(diào)用 Object value = pd.getReadMethod().invoke(obj); map.put(key, value); } return map; }

      public class BeanMap { public static void main(String[] args) throws Exception{ Map map = BeanToMap(new Student("張三", 20)); map.forEach((k,v)-> System.out.println(k+"->"+v)); } }

      5.5.2、map轉(zhuǎn)JavaBean

      //map轉(zhuǎn)JaveBean,這里使用泛型 public static T MapToBean(Map map ,Class clz) throws Exception{ //創(chuàng)建JavaBean對象 T t = clz.newInstance(); //遍歷屬性,獲取屬性名作為mao的key 去獲取value值,再設(shè)置給setter方法 //獲取所有屬性 BeanInfo beanInfo = Introspector.getBeanInfo(clz, Object.class); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor pd : pds) { String key = pd.getName(); Object value = map.get(key); pd.getWriteMethod().invoke(t,value); } return t; }

      六、注解

      6.1、注解介紹

      我們可以使用注解來修飾類中的成員信息,注解其實就是Annotation。

      6.2、定義格式

      @Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface 注解名 { }

      定義格式:@interface 注解名

      使用格式:@注解名(屬性名=屬性值, 屬性名=屬性值)

      注解貼在程序元素上,想要擁有某一些功能,必須有三個角色去參與:

      程序員內(nèi)功修-【反射、內(nèi)省】(下)

      注解本身

      被貼的程序元素

      第三方程序,使用反射給注解賦予功能(在注解的背后,一定有一段代碼給注解賦予功能)。

      6.3、內(nèi)置注解

      @Override 限定覆寫父類方法

      @Deprecated 標記已過時,不推薦使用.在JDK5之前,使用文檔注釋來標記過時

      @SuppressWarings 抑制編譯器發(fā)出的警告

      @Functionallnterface 標記該接口是一個函數(shù)接口(JDK1.8開始出現(xiàn)的)

      6.4、元注解

      注解:用來貼在類/方法/變量等之上的一個標記,第三方程序可以通過這個標記賦予一定功能。

      元注解:在定義注解的時候用來貼在注解上的注解,用來限定注解的用法。他囊括了三個注解

      6.4.1、@Target

      表示注解可以貼在哪些位置(類,方法上,構(gòu)造器上等等).位置的常量封裝在ElementType枚舉類

      中。

      ElementType.ANNOTATION_TYPE只能修飾類。

      ElementType.CONSTRUCTOR只能修飾構(gòu)造方法。

      ElementType.FIELD只能修飾字段(屬性),包括枚舉常量。

      ElementType.LOCAL_VARIABLE只能修飾局部變量。

      ElementType.METHOD只能修飾方法。

      ElementType.PACKAGE只能修飾包。

      ElementType.PARAMETER只能修飾參數(shù)。

      ElementType.TYPE只能修飾類,接口,枚舉。

      6.4.2、@Retention

      表示注解可以保存在哪一個時期,表示時期的值,封裝在RetentionPolicy枚舉類中。

      6.4.3、@Documented

      使用@Documented標注的標簽會保存到API文檔中。

      6.4.4、@Inherited

      @Inherited標注的標簽可以被子類所繼承。

      標記已過時,不推薦使用.在JDK5之前,使用文檔注釋來標記過時

      @SuppressWarings 抑制編譯器發(fā)出的警告

      @Functionallnterface 標記該接口是一個函數(shù)接口(JDK1.8開始出現(xiàn)的)

      6.4、元注解

      注解:用來貼在類/方法/變量等之上的一個標記,第三方程序可以通過這個標記賦予一定功能。

      元注解:在定義注解的時候用來貼在注解上的注解,用來限定注解的用法。他囊括了三個注解

      6.4.1、@Target

      表示注解可以貼在哪些位置(類,方法上,構(gòu)造器上等等).位置的常量封裝在ElementType枚舉類

      中。

      ElementType.ANNOTATION_TYPE只能修飾類。

      ElementType.CONSTRUCTOR只能修飾構(gòu)造方法。

      ElementType.FIELD只能修飾字段(屬性),包括枚舉常量。

      ElementType.LOCAL_VARIABLE只能修飾局部變量。

      ElementType.METHOD只能修飾方法。

      ElementType.PACKAGE只能修飾包。

      ElementType.PARAMETER只能修飾參數(shù)。

      ElementType.TYPE只能修飾類,接口,枚舉。

      6.4.2、@Retention

      表示注解可以保存在哪一個時期,表示時期的值,封裝在RetentionPolicy枚舉類中。

      6.4.3、@Documented

      使用@Documented標注的標簽會保存到API文檔中。

      6.4.4、@Inherited

      @Inherited標注的標簽可以被子類所繼承。

      API 開發(fā)者

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:Java代碼覆蓋率利器JaCoCo基本概念詳解
      下一篇:clipboardjs實現(xiàn)點擊拷貝復(fù)制
      相關(guān)文章
      亚洲男人天堂影院| 亚洲成人国产精品| 激情小说亚洲图片| 亚洲偷自精品三十六区| 亚洲国产成人久久精品app| 亚洲精品国产成人专区| 亚洲AV成人无码久久精品老人| 国产亚洲精品资源在线26u| 在线播放亚洲第一字幕| 亚洲综合伊人久久大杳蕉| 日韩精品亚洲aⅴ在线影院| 国产成人毛片亚洲精品| 综合亚洲伊人午夜网 | 456亚洲人成在线播放网站| 亚洲欧洲日产国产最新| 亚洲日本香蕉视频观看视频| 亚洲福利电影在线观看| 亚洲精品视频在线免费| 亚洲黄色网址大全| 亚洲成人一级电影| 国产精品亚洲精品观看不卡| youjizz亚洲| 久久久久亚洲精品无码网址色欲| 亚洲大尺度无码无码专线一区| 亚洲精品午夜国产va久久| 日韩亚洲产在线观看| 在线a亚洲老鸭窝天堂av高清| 亚洲人片在线观看天堂无码| 国产精品亚洲精品久久精品| 亚洲成a人在线看天堂无码| 亚洲一区精品伊人久久伊人| 亚洲人成77777在线播放网站| 久久精品国产精品亚洲精品| 亚洲av福利无码无一区二区| 亚洲精品中文字幕无乱码| 亚洲综合精品伊人久久| 亚洲国产高清精品线久久| 亚洲人成网77777色在线播放| 亚洲天堂在线播放| 久久精品国产亚洲AV忘忧草18| 亚洲人成人伊人成综合网无码 |