<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系列之反射

          共 11409字,需瀏覽 23分鐘

           ·

          2020-10-19 09:15

          1fa84183c75d2269318ee815835ddabe.webp最近知識(shí)比較零碎,不適合整理成文,來(lái)一篇以前的關(guān)于反射的學(xué)習(xí)筆記,主要內(nèi)容如下:

          1. 反射機(jī)制

          2. 反射獲取類(lèi)的信息

          3. 反射操作類(lèi)的信息

          4. 反射獲取泛型

          5. 反射獲取注解信息

          反射機(jī)制

          Java 的反射機(jī)制是指在運(yùn)行狀態(tài)下,對(duì)于任意一個(gè)類(lèi),都能夠知道這個(gè)類(lèi)的所有屬性和方法,反射是一種可在代碼運(yùn)行時(shí)動(dòng)態(tài)獲取類(lèi)的信息的一種機(jī)制,可通過(guò)反射獲取在編譯期不可能獲取到的類(lèi)的信息,當(dāng)一個(gè)任意類(lèi)被類(lèi)加載器(ClassLoader)首次加載之后會(huì)自動(dòng)生成一個(gè)該類(lèi)對(duì)應(yīng)的 Class 對(duì)象,這個(gè) Class 對(duì)象保存了對(duì)應(yīng)類(lèi)的所有信息。這種當(dāng)一個(gè)任意類(lèi)被類(lèi)加載器加載之后,動(dòng)態(tài)獲取 Class 對(duì)象的信息以及動(dòng)態(tài)操作 Class 對(duì)象的屬性和方法的功能稱(chēng)之為 Java 的反射機(jī)制。Java 反射機(jī)制的關(guān)鍵是獲取某個(gè)任意類(lèi)的 Class 對(duì)象,下面的內(nèi)容就是如何通過(guò)這個(gè) Class 對(duì)象獲取和動(dòng)態(tài)操作類(lèi)的相關(guān)信息,為了便于后文中對(duì)反射的使用,這里先創(chuàng)建一個(gè) User 類(lèi)供下文中使用,具體如下:
           1package?com.manu.reflection.bean;
          2
          3/**
          4?*?反射測(cè)試類(lèi)
          5?*/

          6public?class?User?{
          7
          8????private?int?id;
          9????private?String?name;
          10????private?String?password;
          11
          12????public?User()?{
          13????????super();
          14????}
          15????public?User(int?id,?String?name,?String?password)?{
          16????????super();
          17????????this.id?=?id;
          18????????this.name?=?name;
          19????????this.password?=?password;
          20????}
          21????public?int?getId()?{
          22????????return?id;
          23????}
          24????public?void?setId(int?id)?{
          25????????this.id?=?id;
          26????}
          27????public?String?getName()?{
          28????????return?name;
          29????}
          30????public?void?setName(String?name)?{
          31????????this.name?=?name;
          32????}
          33????public?String?getPassword()?{
          34????????return?password;
          35????}
          36????public?void?setPassword(String?password)?{
          37????????this.password?=?password;
          38????}
          39????@Override
          40????public?String?toString()?{
          41????????return?"User?[id="?+?id?+?",?name="?+?name?+?",?password="?+?password?+?"]";
          42????}
          43
          44}

          反射獲取類(lèi)的信息

          這里總結(jié)一下如何獲取類(lèi)的基本信息,如類(lèi)的構(gòu)造方法、屬性、方法等,可通過(guò)某個(gè)類(lèi)對(duì)應(yīng)的 Class 對(duì)象對(duì)應(yīng)的 getter 方法獲取某個(gè)類(lèi)的名稱(chēng)、構(gòu)造方法、屬性、方法等,下面以獲取某個(gè)類(lèi)的構(gòu)造方法為例說(shuō)明獲取方式不同:
          • getConstructors:表示獲取某個(gè)類(lèi)中修飾符為 public 的所有構(gòu)造方法,如 getFields()、getMethods() 還包括從父類(lèi)繼承來(lái)的 public 修飾的屬性和方法。

          • getDeclaredConstructors:表示獲取某個(gè)類(lèi)中所有聲明的構(gòu)造方法,只限定于本類(lèi)中。

          此外,還可獲取指定的構(gòu)造方法、屬性、方法等,下面的代碼主要以獲取已定義(Declared)的構(gòu)造方法、屬性、方法為例,參考如下:
           1/**
          2?*?反射獲取類(lèi)的信息
          3?*/

          4private?static?void?getReflectClassInfo()?{
          5????try?{
          6????????//獲取某個(gè)類(lèi)的Class對(duì)象
          7????????String?name?=?"com.manu.reflection.bean.User";
          8????????Class?clazz?=?Class.forName(name);
          9
          10????????//反射獲取類(lèi)的名稱(chēng)
          11????????System.out.println("----------反射獲取類(lèi)的名稱(chēng)----------");
          12????????String?n1?=?clazz.getName();//完整路徑:包名+類(lèi)名?(com.manu.reflection.bean.User)
          13????????String?n2?=?clazz.getSimpleName();//類(lèi)名(User)
          14????????System.out.println("獲取類(lèi)的名稱(chēng)n1:"+n1);
          15????????System.out.println("獲取類(lèi)的名稱(chēng)n2:"+n2);
          16
          17????????//反射獲取類(lèi)的構(gòu)造方法
          18????????System.out.println("----------反射獲取類(lèi)的構(gòu)造方法----------");
          19????????Constructor?c1?=?clazz.getDeclaredConstructor(null);
          20????????System.out.println("獲取無(wú)參構(gòu)造方法:"+c1);
          21????????Constructor?c2?=?clazz.getDeclaredConstructor(int.class,String.class,String.class);
          22????????System.out.println("獲取有參構(gòu)造方法:"+c2);
          23????????Constructor[]?constructors?=?clazz.getDeclaredConstructors();
          24????????for(Constructor?c:?constructors)?{
          25????????????System.out.println("獲取所有的構(gòu)造方法:"+c);
          26????????}
          27
          28????????//反射獲取類(lèi)的屬性
          29????????System.out.println("----------反射獲取類(lèi)的屬性----------");
          30????????Field?f1?=?clazz.getDeclaredField("name");
          31????????System.out.println("獲取名稱(chēng)為name的屬性:"+f1);
          32????????Field[]?fields?=?clazz.getDeclaredFields();
          33????????for(Field?f?:?fields)?{
          34????????????System.out.println("獲取所有的屬性:"+f);
          35????????}
          36
          37????????//反射獲取類(lèi)的方法
          38????????System.out.println("----------反射獲取類(lèi)的方法----------");
          39????????Method?m1?=?clazz.getDeclaredMethod("getName",?null);//獲取無(wú)參方法
          40????????Method?m2?=?clazz.getDeclaredMethod("setName",?String.class);//獲取有參方法
          41????????System.out.println("獲取方法名為getName的方法m1:"+m1);
          42????????System.out.println("獲取方法名為setName的方法m2:"+m2);
          43????????Method[]?mathods?=?clazz.getDeclaredMethods();
          44????????for(Method?m:?mathods)?{
          45????????????System.out.println("獲取所有方法:"+m);
          46????????}
          47
          48????}?catch?(Exception?e)?{
          49????????e.printStackTrace();
          50????}
          51}
          通過(guò)反射獲取某個(gè)類(lèi)的相關(guān)信息主要如上,來(lái)上述代碼的執(zhí)行結(jié)果如下:
           1----------反射獲取類(lèi)的名稱(chēng)----------
          2獲取類(lèi)的名稱(chēng)n1:com.manu.reflection.bean.User
          3獲取類(lèi)的名稱(chēng)n2:User
          4----------反射獲取類(lèi)的構(gòu)造方法----------
          5獲取無(wú)參構(gòu)造方法:public?com.manu.reflection.bean.User()
          6獲取有參構(gòu)造方法:public?com.manu.reflection.bean.User(int,java.lang.String,java.lang.String)
          7獲取所有的構(gòu)造方法:public?com.manu.reflection.bean.User()
          8獲取所有的構(gòu)造方法:public?com.manu.reflection.bean.User(int,java.lang.String,java.lang.String)
          9----------反射獲取類(lèi)的屬性----------
          10獲取名稱(chēng)為name的屬性:private?java.lang.String?com.manu.reflection.bean.User.name
          11獲取所有的屬性:private?int?com.manu.reflection.bean.User.id
          12獲取所有的屬性:private?java.lang.String?com.manu.reflection.bean.User.name
          13獲取所有的屬性:private?java.lang.String?com.manu.reflection.bean.User.password
          14----------反射獲取類(lèi)的方法----------
          15獲取方法名為getName的方法m1:public?java.lang.String?com.manu.reflection.bean.User.getName()
          16獲取方法名為setName的方法m2:public?void?com.manu.reflection.bean.User.setName(java.lang.String)
          17獲取所有方法:public?java.lang.String?com.manu.reflection.bean.User.toString()
          18獲取所有方法:public?java.lang.String?com.manu.reflection.bean.User.getName()
          19獲取所有方法:public?int?com.manu.reflection.bean.User.getId()
          20獲取所有方法:public?void?com.manu.reflection.bean.User.setName(java.lang.String)
          21獲取所有方法:public?java.lang.String?com.manu.reflection.bean.User.getPassword()
          22獲取所有方法:public?void?com.manu.reflection.bean.User.setId(int)
          23獲取所有方法:public?void?com.manu.reflection.bean.User.setPassword(java.lang.String)

          反射操作類(lèi)的信息

          通過(guò) Java 的反射機(jī)制可以獲取的某個(gè)類(lèi)的構(gòu)造方法、屬性以及方法,然后就可以對(duì)該類(lèi)進(jìn)行相關(guān)操作了,下面是將通過(guò) Java 的反射機(jī)制構(gòu)建該類(lèi)的對(duì)象、操作該類(lèi)對(duì)象的屬性以及調(diào)用該類(lèi)對(duì)象的方法,具體參考如下:
           1/**
          2?*?反射操作類(lèi)的信息
          3?*/

          4private?static?void?setReflectClassInfo()?{
          5????try?{
          6????????//獲取某個(gè)類(lèi)的Class對(duì)象
          7????????String?name?=?"com.manu.reflection.bean.User";
          8????????Class?clazz?=?Class.forName(name);
          9
          10????????//反射操作類(lèi)的構(gòu)造方法
          11????????System.out.println("----------反射操作類(lèi)的構(gòu)造方法----------");
          12????????Constructor?c1?=?clazz.getDeclaredConstructor(null);//獲取無(wú)參構(gòu)造方法
          13????????Constructor?c2?=?clazz.getDeclaredConstructor(int.class,String.class,String.class);//獲取帶參構(gòu)造方法
          14????????User?u1?=?c1.newInstance();
          15????????User?u2?=?c2.newInstance(1000,"jzman-blog","111111");
          16????????System.out.println("u1:"+u1);
          17????????System.out.println("u2:"+u2);
          18
          19????????//反射操作類(lèi)的屬性
          20????????System.out.println("----------反射操作類(lèi)的屬性----------");
          21????????User?u3?=?c1.newInstance();
          22????????Field?field?=?clazz.getDeclaredField("name");
          23????????field.setAccessible(true);//設(shè)置該屬性不需要安全檢查,可直接放訪問(wèn)
          24????????field.set(u3,?"jzman");//反射設(shè)置User對(duì)象的name屬性值
          25????????System.out.println("u3:"+u3);
          26????????System.out.println("獲取User對(duì)象u3的name屬性值:"+field.get(u3));
          27
          28????????//反射操作類(lèi)的方法
          29????????System.out.println("----------反射操作類(lèi)的方法----------");
          30????????User?u4?=?c1.newInstance();
          31????????Method?method?=?clazz.getDeclaredMethod("setPassword",?String.class);
          32????????method.invoke(u4,?"222222");//設(shè)置User對(duì)象u4的password屬性,等同于u4.setPassword("222222);
          33????????System.out.println("u4:"+u4);
          34
          35????}?catch?(Exception?e)?{
          36????????e.printStackTrace();
          37????}
          38}
          上述代碼的執(zhí)行結(jié)果如下:
          1----------反射操作類(lèi)的構(gòu)造方法----------
          2u1:User?[id=0,?name=null,?password=null]
          3u2:User?[id=1000,?name=jzman-blog,?password=111111]
          4----------反射操作類(lèi)的屬性----------
          5u3:User?[id=0,?name=jzman,?password=null]
          6獲取User對(duì)象u3的name屬性值:jzman
          7----------反射操作類(lèi)的方法----------
          8u4:User?[id=0,?name=null,?password=222222]
          實(shí)際開(kāi)發(fā)中肯定會(huì)遇到某個(gè)組件中需要某個(gè)屬性,但是該屬性又是私有的,這時(shí)候就可以使用 Java 的反射機(jī)制了。

          反射操作泛型

          Java 采用泛型擦除的機(jī)制,Java 中的泛型僅僅是給編譯器 javac 使用的,這樣可確保數(shù)據(jù)的安全性的免去強(qiáng)制類(lèi)型轉(zhuǎn)換的麻煩,當(dāng)編譯完成之后,所有和泛型相關(guān)的類(lèi)型將會(huì)被全部擦除,為了能夠使用反射操作這些類(lèi)型,新增了四種類(lèi)型 GenericArrayType、ParameterizedType、TypeVariable?和 WildcardType 來(lái)表示不能被歸一到 Class 類(lèi)中的類(lèi)型但又是和原始類(lèi)型齊名的類(lèi)型,也就是說(shuō)正常的能夠獲取對(duì)應(yīng)的 Class 對(duì)象的 Type 還是 Class 對(duì)象,如基本數(shù)據(jù)類(lèi)型。反射操作泛型就要涉及到 Java 中的 Type, 在 Java 中 Type 表示所有類(lèi)型的公共接口,這些類(lèi)型包括原始類(lèi)型、參數(shù)化類(lèi)型、數(shù)組類(lèi)型、類(lèi)型變量和基本類(lèi)型,其聲明如下:
          1/**
          2?*?Type?是?Java?語(yǔ)言中所有類(lèi)型的公共接口
          3?*?這些類(lèi)型包括原始類(lèi)型、參數(shù)化類(lèi)型、數(shù)組類(lèi)型、類(lèi)型變量和基本類(lèi)型
          4?*/

          5public?interface?Type?{
          6????default?String?getTypeName()?{
          7????????return?toString();
          8????}
          9}
          Type 有四個(gè)直接子接口,具體含義如下:
          1GenericArrayType:表示泛型數(shù)組類(lèi)型,如 ArraryList[] listArrary
          2ParameterizedType:表示參數(shù)化類(lèi)型(泛型),如 ArrayList list
          3TypeVariable:表示類(lèi)型變量,如T
          4WildcardType:表示一個(gè)通配符類(lèi)型,如 ?、? extends Number 或 ? super?Integer
          下面以 GenericArrayType 和 ParameterizedType ?為例來(lái)說(shuō)明如何使用反射來(lái)操作泛型類(lèi)型,具體如下:
           1//用來(lái)測(cè)試獲取泛型的屬性
          2private?String[]?array;
          3private?List[]?listArray;
          4//用來(lái)測(cè)試獲取泛型的方法
          5private?String?testGenericType(Map?map,?String[]?array,?int?name,User?user)?{
          6????System.out.println("testGenericType");
          7????return?null;
          8}
          9
          10//通過(guò)反射獲取泛型
          11private?static?void?refectGenericType()?{
          12????try?{???????
          13????????System.out.println("---------GenericArrayType---------");
          14
          15????????//獲取泛型數(shù)組(GenericArrayType)
          16????????Field?field?=?ReflectTest02.class.getDeclaredField("listArray");//獲取屬性listArray
          17????????GenericArrayType?type?=?(GenericArrayType)?field.getGenericType();
          18????????System.out.println("獲取泛型數(shù)組:"+type);
          19
          20????????System.out.println("---------ParameterizedType---------");
          21
          22????????//獲取參數(shù)化類(lèi)型(泛型)(ParameterizedType)
          23????????Method?method?=?ReflectTest02.class.getDeclaredMethod("testGenericType",?Map.class,String[].class,int.class,User.class);
          24????????Type[]?types?=?method.getGenericParameterTypes();//獲得方法參數(shù)類(lèi)型
          25????????for(Type?type1:?types)?{
          26????????????System.out.println("方法參數(shù)類(lèi)型:"+type1);
          27????????????if(type1?instanceof?ParameterizedType)?{
          28????????????????System.out.println("ParameterizedType:"+type1);
          29????????????}
          30????????}
          31
          32????}?catch?(Exception?e)?{
          33????????e.printStackTrace();
          34????}
          35}
          上述代碼中方法 refectGenericType 的執(zhí)行結(jié)果如下:
          1---------GenericArrayType---------
          2獲取泛型數(shù)組:java.util.List[]
          3---------ParameterizedType---------
          4方法參數(shù)類(lèi)型:java.util.Map
          5ParameterizedType:java.util.Map
          6方法參數(shù)類(lèi)型:class?[Ljava.lang.String;
          7方法參數(shù)類(lèi)型:int
          8方法參數(shù)類(lèi)型:class?com.manu.reflection.bean.User
          9

          可參照代碼查看對(duì)應(yīng)的輸出結(jié)果。

          反射獲取注解信息

          通過(guò)反射還可以獲取注解信息,記如果對(duì)注解比較陌生可以參考之前分享的一篇文章 Java 系列之注解,這里簡(jiǎn)單模仿數(shù)據(jù)庫(kù)表字段與 Java 對(duì)象的屬性是如何通過(guò)注解信息一一對(duì)應(yīng)的,為什么我們使用一些數(shù)據(jù)庫(kù)框架的時(shí)候,通過(guò)一些表注解、字段注解就能夠創(chuàng)建表,這里就涉及到使用反射來(lái)獲取注解信息來(lái)生成 SQL,進(jìn)而生成對(duì)應(yīng)的表。創(chuàng)建兩個(gè)注解分別作為表注解和字段注解,參考如下:
           1//表注解
          2@Target(ElementType.TYPE)
          3@Retention(RetentionPolicy.RUNTIME)
          4public?@interface?TableAnnotation?{
          5????String?value();
          6}
          7
          8//字段注解
          9@Target(ElementType.FIELD)
          10@Retention(RetentionPolicy.RUNTIME)
          11public?@interface?FieldAnnotation?{
          12????String?column();
          13????int?length();
          14????String?type();
          15}
          然后,創(chuàng)建一個(gè)類(lèi)并使用該注解,參考如下:
           1/**
          2?*?反射讀取注解信息測(cè)試Bean
          3?*?@author?jzman
          4?*/

          5
          6@TableAnnotation(value?=?"student_table")
          7public?class?Student?{
          8????@FieldAnnotation(column?=?"uid",?length?=?20,?type?=?"int")
          9????private?int?sId;
          10????@FieldAnnotation(column?=?"name",?length?=?10,?type?=?"varchar")
          11????private?String?sName;
          12????@FieldAnnotation(column?=?"uiaged",?length?=?3,?type?=?"varchar")
          13????private?int?sAge;
          14
          15????//setter、getter方法
          16????//...
          17}
          最后,獲取注解信息,參考如下:
           1/**
          2?*?反射獲取注解信息
          3?*?@author?jzman
          4?*/

          5public?class?ReflectTest03?{
          6????public?static?void?main(String[]?args)?{
          7????????try?{
          8????????????Class?clazz?=?Class.forName("com.manu.reflection.bean.Student");
          9
          10????????????//反射獲取類(lèi)的注解信息
          11????????????TableAnnotation?tableAnnotation?=?(TableAnnotation)?clazz.getAnnotation(TableAnnotation.class);
          12????????????System.out.println("反射獲取類(lèi)的注解信息:"+tableAnnotation);
          13
          14????????????//反射獲取屬性的注解信息
          15????????????Field?field?=?clazz.getDeclaredField("sName");
          16????????????FieldAnnotation?fieldAnnotation?=?field.getAnnotation(FieldAnnotation.class);
          17????????????System.out.println("反射獲取屬性的注解信息:"+fieldAnnotation);
          18
          19????????????//獲取其他注解信息使用方式類(lèi)似
          20????????????//...
          21????????}?catch?(Exception?e)?{
          22????????????e.printStackTrace();
          23????????}
          24????}
          25}
          上述代碼的執(zhí)行結(jié)果如下:
          1反射獲取類(lèi)的注解信息:@com.manu.reflection.TableAnnotation(value=student_table)
          2反射獲取屬性的注解信息:@com.manu.reflection.FieldAnnotation(column=name,?length=10,?type=varchar)
          顯然,通過(guò)反射獲取到了相應(yīng)的注解信息,這些注解信息標(biāo)注了該類(lèi)對(duì)應(yīng)數(shù)據(jù)庫(kù)表的一些關(guān)鍵信息,然后就可以生成對(duì)應(yīng)的 SQL 語(yǔ)句,這樣就不難理解數(shù)據(jù)庫(kù)表字段與Java對(duì)象屬性的映射關(guān)系了。使用反射獲取私有屬性或私有方法是必須設(shè)置 setAccessible 為 true 才能跳過(guò) Java 安全檢查,從而獲取私有的屬性、方法等,同時(shí)設(shè)置 setAccessible 為 true 在一定程度上可以提高反射的運(yùn)行速度。推薦閱讀:
          瀏覽 60
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  青娱乐无码在线视频 | av黄色电影一区天堂一区二区三区 | 超碰自拍中文字幕 | 狠狠干狠狠插 | 日一本一乱一纶一视一频一一区一二区 |