日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

反射与注解

發布時間:2023/12/14 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 反射与注解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

反射

通過某種機制,動態得到這個類的所有信息(屬性,方法,構造方法),也可以動態的調用這個類所有的屬性,方法,構造方法... 這種機制就是所謂的反射

反射的核心:類的鏡子,類的字節碼文件 對應的類:Class類

每一個類,它的Class類的對象,唯一一個,類的Class對象, 在這個類的字節碼文件加載到內存時候,JVM就會為該類的字節碼文件創建一個Class對象

與new對象不同

不確定的類、不確定的對象創建 在框架底層 使用反射

反射的使用

創建對象

  • 得到某個類的Class對象

    1) 類名.class()

    Class<Student> clazz = Student.class;

    2) 類的對象.getClass()

    Student stu = new Student(); Class<? extends Student> clazz2 = stu.getClass();//Student本類 子類 上界 ?泛型通配符

    3)通過Class類的static方法:forName(類的全限定名:包名.類名)

    Class<?> clazz3 = Class.forName("com.fs.Student");

  • 從這個Class對象獲取某個類所有的屬性,方法,構造方法

  • 通過Class對象,調用屬性,方法

    創建這個對象,類名是可變的String 如"Student","Dog"

    new Student() 不可變 固定

  • 獲取構造方法

    方法,構造方法,屬性,參數都可以看作是一個個對象

    getConstructor() getConstructors()

    <init>(int) 表示的構造方法

    // NoSuchMethodException異常: 沒有匹配的方法的異常

    Constructor[] constructors = clazz.getConstructors(); //只能得到公開的構造方法 ? Constructor c1 = clazz.getDeclaredConstructor(int.class,String.class);//得到所有的 不管是公開還是私有

    指定參數類型的構造方法

    .getModifiers() 得到訪問修飾符 返回值int 0. 缺省的 1. public 2. private 4. protected

    用構造方法創建對象 new 構造方法() 創建對象

    反射方式創建對象:

    1)通過Class類的newInstance(),底層調用本類的無參構造方法

    ?Student stu = ?clazz.newInstance(); ? // new Student()

    2)通過構造方法對象的Constructor類newInstance(Object obj)

    Constructor<Student> c = clazz.getDeclaredConstructor(int.class); c.Accessble(true);//如果調用的類的private修飾的屬性無法訪問,設置允許訪問 Student stu = c.newInstance();

    獲取屬性

    Field

    //獲得所有的public修飾的屬性(繼承自父類的屬性也能獲得),private修飾的屬性不能獲得 Field [] fs = cls.getFields(); ? Field [] fs = cls.getDeclaredFields(); // 獲得本類所有的屬性 for(int i=0;i<fs.length;i++){System.out.println(fs[i]); } ? //獲得指定的屬性 Field f = cls.getDeclaredField("mastername"); //mastername屬性為私有的,所以要先解除封裝 f.setAccessible(true); ? ? //修改指定的屬性 Field f = cls.getDeclaredField("mastername"); f.setAccessible(true); f.set(obj, "lisi"); System.out.println(f.get(obj));

    獲取方法

    //獲得所有的方法,包括繼承自父類的方法,但只能是public 修飾的方法 Method[] ms = ?cls.getMethods(); ? //獲得本類所有的方法,不包括繼承自父類的方法,但private 修飾的方法也能獲得 Method[] ms = ?cls.getDeclaredMethods(); ? noSuchMethodException 找不到方法異常 ? //方法的執行 //通過invoke調用方法,obj表示在哪個對象里調用方法,后續的參數都是方法的傳入的參數 //invoke返回值:如果方法為void 返回值為null String str = (String) ms.invoke(obj, "測試有參方法"); System.out.println("方法執行的結果:"+str); ? I

    getName() //獲取全限定名 包名 +類名 getSimpleName() // 只得到類名

    注解

    // /** */ /**/ 注釋:便于閱讀代碼,對代碼的描述

    注解(Annotation):對代碼的描述,作為代碼的形式保留

    Annontation像一種修飾符一樣,應用于包、類型、構造方法、方法、成員變量、參數及本地變量的聲明語句中。

    注釋類似于商品的標簽,描述商品;注解類似于商品的條形碼,方便后期結算。

    注解的作用

  • 生成文檔

  • 實現代替配置文件功能

  • 在編譯時進行格式檢查 如 @Override 重寫 方法名和參數必須相同

  • 注解的本質:特殊的接口

    聲明注解:創建了一個特殊接口

    使用注解: @注解名 (創建注解的一個對象)

    注解的分類

    內置注解

    jdk提供的這個注解的聲明,開發者直接使用

    @Override檢查重寫

    @Deprecated 標記這個方法已過時

    @SupperssWarnings抑制生成警告信息

    1900~1999 計算機元年 1970年

    元注解

    使用元注解,對自定義的注解進行聲明,限制使用區域

    1.@Documented-注解是否將包含在JavaDoc中

    2.@Retention–什么時候使用該注解 Retention 保留期 存活時間

    ????????自定義注解一定設置為runtime

    RetentionPolicy.RUNTIME 注解可以保留到程序運行的時候,它會被加載進入到 JVM 中,所以在程序運行時可以獲取到它們。

    RetentionPolicy.SOURCE注解只在源碼階段保留,在編譯器進行編譯時它將被丟棄忽視。

    RetentionPolicy.CLASS注解只被保留到編譯進行的時候,它并不會被加載到 JVM 中。

    3.?@Target–注解用于什么地方 如果沒有寫,表示這個注解可以在任意地方使用

    注解可以使用在 類、方法、屬性 上

    給注解的參數賦值

    如果給注解定義的參數是數組類型,給數組類型賦值

    賦一個值@Target(value = {ElementType.TYPE})描述類、接口或enum聲明

    賦多個值 @Target(value = {ElementType.TYPE,ElementType.METHOD})描述類、接口或enum聲明和方法

    4.@Inherited– 定義該注釋和子類的關系 Inherited 繼承 子類可以繼承父類的注解

    自定義注解

    聲明注解的語法:@interface 默認繼承Annotation

    參數成員訪問修飾符只能為默認default或public 方法返回值

    ? @Target(ElementType.FIELD)//可以用來修飾對象,屬性 @Retention(RetentionPolicy.RUNTIME)//什么時候都不丟棄 @Documented//用于生成javadoc文檔 public @interface 注解名{//成員:常量 //String value() defualt ="zhangsan"; 給參數賦值就是給方法的返回值String value();//如果沒有設置default默認值,使用這個注解時一定要給參數賦值//如果設置了default,可以在使用時改變默認值//參數數據類型:八大數據類型,String,枚舉,Class,注解類型,數組類型(12種)}

    通過接口自動生成Annotation的實現類

    自定義注解,可以有參數,也可以沒有。沒有參數這個注解沒有意義

    必須代碼解析注解它的功能,獲取該注解的對象,只能使用反射來獲取

    創建一個類,在類中應用自定義的注解:

    package AnnotationExample; //商品類 public class Good {@Role("管理員")public void shangjia(){System.out.println("商品正在上架");}@Role("管理員")public void xiajia(){System.out.println("商品正在下架");}public void show(){System.out.println("商品正在展示");}@Role("顧客")public void buy(){System.out.println("商品正在購買");} }

    創建一個注解:

    package AnnotationExample; ? import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; ? //角色的注解 //如果參數名為value 在注解上 單獨給這個value參數賦值 省略 value= //如果給多個參數賦值,不能省略 @Target(ElementType.METHOD) //只能在方法上面使用 @Retention(RetentionPolicy.RUNTIME)//運行時 public @interface Role {// String role();//權限 管理員 顧客String value(); //String value() default ""; }

    創建一個工具類用來處理注解:

    ? package AnnotationExample; ? import java.lang.reflect.Method; import java.util.Scanner; ? public class TestGood {public static void main(String[] args) throws Exception {Scanner input = new Scanner(System.in);System.out.println("請輸入您的角色");String role = input.next();System.out.println("請輸入您要調用的方法");String methodName = input.next();Good good = new Good();//調用方法前 判斷角色與方法上定義的角色是否匹配//如果不匹配,禁止訪問//通過反射// 1、獲取Good的ClassClass<Good> clazz = Good.class;//2.獲取指定方法名的對象Method method = clazz.getDeclaredMethod(methodName);//獲取這個方法上需要的角色 ?if (method.isAnnotationPresent(Role.class)){ ?//判斷是否有@Role這個注解//獲取方法上的注解對象Role annotation = method.getAnnotation(Role.class);//獲取方法上的value參數String value = annotation.value();if (role.equals(value)){//判斷是否匹配System.out.println("您有權限");method.invoke(good); //調用方法}else{System.out.println("您沒有權限");}}else {//沒有 直接執行System.out.println("沒有這個注解");} ? ? ? ?} }

    補 記憶版

    內置注解:Java已經提供的注解,叫做內置注解。

    注解名稱?? ?注解作用
    @Override?用于重寫方法上面,可以避免子類重寫方法時出錯。
    @Deprecated?? ?標識某個方法已經過時了,后續不推薦使用該方法(但是可以使用,只是不建議)。
    @SuppressWarnings???告訴編譯器忽略指定的警告信息(這樣代碼里面就看不見那些黃色波浪線了)。
    @FunctionalInterface??標記某個接口是函數式接口(Jdk1.8新增)。

    元注解:用于對其他注解進行解釋說明的,一般用于創建自定義注解時候,聲明自定義注解的一些信息,例如:注解作用范圍、注解能夠保存到哪個階段,注解是否需要包含到用戶文檔里面等等。

    注解名稱注解作用
    @Documented標著這個注解是否包含在用戶文檔中(即:javadoc文檔里面)。
    @Target??標記這個注解能夠作用在哪些成員上面,例如:類上面、屬性上面、方法上面等等。
    @Retention?標記這個注解能夠保存到哪個階段,有三個可選值:源碼階段、字節碼階段、運行階段。
    @Inherited??標記某個注解是繼承自哪個注解類(注解默認是不繼承任何類的)。

    ?? ?
    ?? ?
    ?
    ??
    ?
    ?

    總結

    以上是生活随笔為你收集整理的反射与注解的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。