欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

快速掌握Java中注解與反射

 更新時間:2024年10月11日 16:03:18   作者:楠尋尋  
本文詳細介紹了Java中注解和反射的概念及應用,注解是用于給代碼添加元數(shù)據(jù)的標記,如@Override、@Deprecated等,反射機制則是在運行時獲取和操作類的內(nèi)部信息,提高了代碼的靈活度,感興趣的朋友跟隨小編一起看看吧

注解和反射

一、注解

什么是注解?Annotation

 @Override :表示一個方法聲明打算重寫超類的另一個方法聲明
 @Deprecated:表示不鼓勵程序員使用這樣的元素,(此注釋可以用于修飾方法,屬性,類)
 @SupperssWarnings():用來抑制編譯時的警告信息
 "all", "unchecked", value={"unchecked","deprecation"})]

元注解

元注解的作用就是負責注解其他注解,Java定義了4個標準的meta-annotation類型,它們被用來對其他annotation類型作說明。

  • @Target:用于描述注解的使用范圍(即:被描述的注解可以用在什么地方)

表示我們的注解可以用在哪些地方(字段、方法等)

  • @Retention:表示需要什么級別保存該注釋信息,用于描述注解的生命周期(source源碼 < class < runtime運行)

表示我們的注解在什么地方還有效

  • @Document:說明該注解將被包含在javadoc中

表示是否將我們的注解生成在javadoc中

  • @Inherited:說明子類可以繼承父類中的該注解

子類可以繼承父類的注解

二、反射機制

動態(tài)語言:

  • 在運行時可以根據(jù)某些條件改變自身結(jié)構(gòu)。如:C、C#、JavaScript、PHP、Python

靜態(tài)語言:

  • 在運行時結(jié)構(gòu)不可改變的語言就是靜態(tài)語言,如Java、C、C++

Java不是動態(tài)語言,但是Java可以稱之為“準動態(tài)語言”。即Java有一定的動態(tài)性,我們可以利用反射機制獲得類似動態(tài)語言的特性。

Reflection(反射)是Java被視為動態(tài)語言的關鍵,反射機制允許程序在執(zhí)行期間于Reflection API取得任何類的內(nèi)部信息,并能直接操作任意對象的內(nèi)部屬性及方法。

Class c = Class.forName("java.lang.String")

加載完類之后,在堆內(nèi)存的方法區(qū)中就產(chǎn)生了一個Class類型的對象(一個類只有一個Class對象),這個對象就包含了完整的類的結(jié)構(gòu)信息(構(gòu)造器、方法、字段、包括私有字段等)。我們可以通過這個對象看到類的結(jié)構(gòu)。這個對象就像一面鏡子,透過這個鏡子看到類的結(jié)構(gòu),所以,我們形象的稱之為:反射

  • 正常方式:引入需要的“包類”名稱 ---> 通過new實例化--->取得實例化對象
  • 反射方式:實例化對象--->getClass()--->取得完整的“包類”名稱

Java反射機制提供的功能

  • 在運行時判斷任意一個對象所屬的類、判斷任意一個類所具有的成員變量和方法。
  • 在運行時構(gòu)造任意一個類的對象
  • 在運行時獲取泛型信息
  • 在運行時調(diào)用任意一個對象的成員變量和方法
  • 在運行時處理注解
  • 生成動態(tài)代理
  • .......

Java反射優(yōu)缺點

  • 優(yōu)點:可以實現(xiàn)動態(tài)創(chuàng)建對象和編譯,體現(xiàn)出很大的靈活性。
  • 缺點:對性能有影響。使用反射基本上是一種解釋操作,我們可以告訴JVM,我們希望做什么并且它滿足我們的要求。這類操作總是慢于直接執(zhí)行相同的操作。
 java.lang.Class; 代表一個類
 java.lang.reflect.Method; 代表類的方法
 java.lang.reflect.Field; 代表類的成員變量
 java.lang.reflect.Constructor; 代表類的構(gòu)造器  

Class類

在Object類中定義了以下的方法,此方法將被所有子類繼承

public final Class getClass()

此方法返回值的類型是一個Class類,此類是Java反射的源頭,實際上所謂從程序中的運行結(jié)果來看也是很好理解,即:可以通過對象反射類的名稱。

對象照鏡子后可以得到的信息:某個類的屬性、方法和構(gòu)造器、某個類到底實現(xiàn)了哪些接口。對于每個類而言,JRE都為其保留了Class類型的對象。一個Class對象包含了特定某個結(jié)構(gòu)(class/interface/enum/annotation/primitive type/void/[])的有關信息。

  • Class本身是一個類
  • Class對象只能由系統(tǒng)建立對象
  • 一個加載的類在JVM中只會有一個Class實例
  • 一個Class對象對應的是一個加載JVM中的一個class文件
  • 每個類的實例都會記得自己是由那個Class實例所生成
  • 通過Class可以完整地得到一個類中的所有被加載的結(jié)構(gòu)
  • Class類是Reflection的根源,針對任何你想動態(tài)加載、運行的類,唯有先獲得相應的Class對象

Class類的常用方法

Class類中部分源碼

 public class Class<T> {
      /**
      * 根據(jù)類的全限定名稱獲取 Class 對象
      *
      * @param className 類的全限定名稱
      * @return Class 對象
      * @throws ClassNotFoundException 如果找不到指定名稱的類
      */
     public static Class<?> forName(String className)
         throws ClassNotFoundException {
         return Class.forNameImpl(className, false);
     }
 ?
     // 實現(xiàn)細節(jié)
     private static Class<?> forNameImpl(String name, boolean initialize)
         throws ClassNotFoundException {
         ClassLoader cl = null;
         try {
             if (cl == null) {
                 cl = Thread.currentThread().getContextClassLoader();
             }
             return cl.loadClass(name);
         } catch (ClassNotFoundException e) {
             // 嘗試使用當前類加載器
             cl = ClassLoader.getSystemClassLoader();
             return cl.loadClass(name);
         }
     }
     // 構(gòu)造器是私有的,不允許外部直接創(chuàng)建 Class 對象
     private Class() {}
 ?
     // 返回類的全限定名稱
     public native String getName();
 ?
     // 返回類的規(guī)范名稱
     public String getCanonicalName() {
         return null; // 實際實現(xiàn)可能返回具體的規(guī)范名稱
     }
 ?
     // 返回類的簡單名稱
     public String getSimpleName() {
         int lastDot = name.lastIndexOf('.');
         return (lastDot < 0) ? name : name.substring(lastDot + 1);
     }
 ?
     // 創(chuàng)建并返回此 Class 對象所表示的類的一個新實例
     @Deprecated(since = "9")
     public T newInstance() throws InstantiationException, IllegalAccessException {
         return getDeclaredConstructor().newInstance();
     }
 ?
     // 獲取此 Class 對象所表示的類聲明的所有方法
     public Method[] getDeclaredMethods() {
         Method[] result = declaredMethods;
         if (result == null) {
             // 實際實現(xiàn)會從類信息中獲取方法
             // 這里簡化處理
             result = new Method[0];
         }
         return result;
     }
 ?
     // 獲取此 Class 對象所表示的類聲明的所有字段
     public Field[] getDeclaredFields() {
         Field[] result = declaredFields;
         if (result == null) {
             // 實際實現(xiàn)會從類信息中獲取字段
             // 這里簡化處理
             result = new Field[0];
         }
         return result;
     }
 ?
     // 測試指定對象是否分配了此 Class 對象所表示的類或接口
     public boolean isInstance(Object obj) {
         return this.equals(obj.getClass());
     }
 ?
     // 獲取此 Class 對象所表示的類的直接超類
     public native Class<?> getSuperclass();
 }
 ?
 ?

獲取Class類的實例

  • 若已知具體的,通過類的class屬性獲取,該方法最為安全可靠,程序性能最高。

Class c1 = Person.class;

  • 已知某個類的實例,調(diào)用該實例的getClass()方法獲取Class對象

Class c2 = person.getClass();

  • 已知一個類的全類名,且該類在類路徑下,可以通過Class類的靜態(tài)方法forName()獲取,可能會拋出ClassNotFoundException

Class c3 = Class.forName("Deom1.Student");

  • 基本內(nèi)置數(shù)據(jù)類型的包裝類都有一個Type屬性

Class c4 = Integer.Type;

  • 還可以利用ClassLoader

哪些類型可以有Class對象

class:外部類,成員(成員內(nèi)部類,靜態(tài)內(nèi)部類),局部內(nèi)部類,匿名內(nèi)部類。

Interface:接口

[]:數(shù)組

enum:枚舉

annotation:注解@interface

primitive type:基本數(shù)據(jù)類型

void

package com.briup.chap13;
 ?
 import java.lang.annotation.ElementType;
 ?
 /**
  * @author 35329
  */
 public class Test04 {
     public static void main(String[] args) {
         Class c1 = Object.class;  // 類
         Class c2 = Comparable.class;// 接口
         Class c3 = String[].class;//一維數(shù)組
         Class c4 = int[][].class;//二維數(shù)組
         Class c5 = Override.class;// 注解
         Class c6 = ElementType.class;// 枚舉
         Class c7 = Integer.class; //基本數(shù)據(jù)類型
         Class c8 = void.class;// void
         Class c9 = Class.class;// Class
 ?
         System.out.println("c1 = " + c1);
         System.out.println("c2 = " + c2);
         System.out.println("c3 = " + c3);
         System.out.println("c4 = " + c4);
         System.out.println("c5 = " + c5);
         System.out.println("c6 = " + c6);
         System.out.println("c7 = " + c7);
         System.out.println("c8 = " + c8);
         System.out.println("c9 = " + c9);
 ?
         // 只要元素類型與維度一樣,就是同一個Class
         int[] a = new int[10];
         int[] b = new int[100];
         System.out.println("a.getClass().hashCode() = " + a.getClass().hashCode());
         System.out.println("b.getClass().hashCode() = " + b.getClass().hashCode());
 ?
         // 運行結(jié)果:
         //c1 = class java.lang.Object
         //c2 = interface java.lang.Comparable
         //c3 = class [Ljava.lang.String;
         //c4 = class [[I
         //c5 = interface java.lang.Override
         //c6 = class java.lang.annotation.ElementType
         //c7 = class java.lang.Integer
         //c8 = void
         //c9 = class java.lang.Class
 ?
         //a.getClass().hashCode() = 21685669
         //b.getClass().hashCode() = 21685669
     }
 }

類加載內(nèi)存分析:

類的加載過程:

  • 加載:將class文件字節(jié)碼內(nèi)容加載到內(nèi)存中,并將這些靜態(tài)數(shù)據(jù)轉(zhuǎn)化成方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu),然后生成一個代表這個類的java.lang.Class對象。
  • 鏈接:將Java類的二進制代碼合并到JVM的運行狀態(tài)之中的過程。
    • 驗證:確保加載的類信息符合JVM規(guī)范,沒有安全方面的問題。
    • 準備:正式為類變量(static)分配內(nèi)存并設置類變量默認初始值的階段,這些內(nèi)存都將在方法去中進行分配。
    • 解析:虛擬機常量池內(nèi)的符號引用(常量名)替換為直接引用(地址)的過程。
  • 初始化:
    • 執(zhí)行類構(gòu)造器<clinit>()方法的過程,類構(gòu)造器<clinit>()方法是由編譯期自動收集類中所有類變量的賦值動作和靜態(tài)代碼塊中的語句合并產(chǎn)生的。(類構(gòu)造器是構(gòu)造類信息的,不是構(gòu)造該類對象的構(gòu)造器)。
    • 當初始化一個類的時候,如果發(fā)現(xiàn)其父類還沒有進行初始化,則需要先觸發(fā)其父類的初始化。
    • 虛擬機會保證一個類的<clinit>()方法在多線程環(huán)境中被正確加鎖和同步。
package com.briup.chap13;
 ?
 /**
  * @author 35329
  */
 public class Test05 {
     public static void main(String[] args) {
         A a = new A();
         System.out.println(A.m);
         /**
          * 1、加載到內(nèi)存,會產(chǎn)生一個類對應Class對象
          * 2、鏈接,鏈接結(jié)束后 m = 0;
          * 3、初始化
          *   <clinit>(){
          *         System.out.println("A類靜態(tài)代碼塊初始化");
          *         m = 300;
          *         m = 100;
          *   }
          *   m = 100;
          */
     }
 }
 ?
 class A{
     static {
         System.out.println("A類靜態(tài)代碼塊初始化");
         m = 300;
     }
     static int m = 100;
     /*
     * m = 300
     * m = 100
     * 后面的會覆蓋前面的
     * */
     public A(){
         System.out.println("A類的無參構(gòu)造初始化");
     }
 }
 ?
 // 運行結(jié)果:
 //A類靜態(tài)代碼塊初始化
 //A類的無參構(gòu)造初始化
 //100

什么時候會發(fā)生類初始化

  • 類的主動引用(一定會發(fā)生類的初始化)重點
    • 當虛擬機啟動,先初始化main方法所在的類
    • new一個類的對象
    • 調(diào)用類的靜態(tài)成員(除了final常量)和靜態(tài)方法
    • 使用java.lang.reflect包的方法對類進行反射調(diào)用
    • 當初始化一個類,如果其父類沒有被初始化,則先會初始化它的父類
  • 類的被動引用(不會發(fā)生類的初始化)
    • 當訪問一個靜態(tài)域時,只有真正聲明這個域的類才會被初始化。如:當通過子類引用父類的靜態(tài)變量,不會導致子類初始化。
    • 通過數(shù)組定義類引用,不會觸發(fā)此類的初始化
    • 引用常量不會觸發(fā)此類的初始化(常量在鏈接階段就存入調(diào)用類的常量池中了
package com.briup.chap13;
 ?
 /**
  * @author 35329
  */
 // 測試類什么時候會初始化
 public class Test06 {
     static {
         System.out.println("mian類被加載");
     }
 ?
     public static void main(String[] args) throws ClassNotFoundException {
         // 1、主動被加載
         // Son son = new Son();
 ?
         // 反射也會產(chǎn)生主動引用
         // Class.forName("com.briup.chap13.Son");
 ?
         // 不會產(chǎn)生類的引用的方法
         // System.out.println("Son.b = " + Son.b);
 ?
         // Son[] arr = new Son[5];
 ?
         System.out.println("Son.M = " + Son.M);
     }
 }
 ?
 class Father{
     static int b = 2;
     static {
         System.out.println("父類被加載");
     }
 }
 class Son extends Father{
     static {
         System.out.println("子類被加載");
         m = 300;
     }
 ?
     static int m = 100;
     static final int M = 1;
 }
 ?

類加載器的作用:

類加載器的作用:將class文件字節(jié)碼內(nèi)容加載到內(nèi)存中,并將這些靜態(tài)數(shù)據(jù)轉(zhuǎn)換成方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu),然后在堆中生成一個代表這個類的java.lang.Class對象,作為方法區(qū)中類數(shù)據(jù)的訪問入口。

類緩存:標準的JavaSE類加載器可以按要求查找類,但一旦某個類被加載到類加載器中,它將維持加載(緩存)一段時間。不過JVM垃圾回收機制可以回收這些Class對象。

1c3526c321964cd2827f703e5d296b30.png

類加載器作用是用來把類(class)裝載進內(nèi)存的。JVM規(guī)范定義了如下類型的類的加載器。

  • 引導類加載器:用C++編寫,是JVM自帶的類加載器,負責Java平臺核心庫,用來裝載核心類庫。該加載器無法直接獲取。
  • 擴展類加載器:負責jre/lib/ext目錄下的jar包或 -D java.ext.dirs指定目錄下的jar包裝入工作庫
  • 系統(tǒng)類加載器:負責java -classpath 或 -D java.class.path所指的目錄下的類與jar包裝入工作,是最常用的加載器。
package com.briup.chap13;
 ?
 import com.briup.chap07.test.bean.Cat;
 ?
 /**
  * @author 35329
  */
 public class Test07 {
     public static void main(String[] args) throws ClassNotFoundException {
         // 獲取系統(tǒng)類的加載器
         ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
         System.out.println("systemClassLoader = " + systemClassLoader);
 ?
         // 獲取系統(tǒng)類加載器的父類加載器 --> 擴展類加載器
         ClassLoader parent = systemClassLoader.getParent();
         System.out.println("parent = " + parent);
 ?
         // 獲取擴展類加載器 --> 根加載器(C/c++)
         ClassLoader parent1 = parent.getParent();
         System.out.println("parent1 = " + parent1);
 ?
         // 運行結(jié)果:
         //systemClassLoader = sun.misc.Launcher$AppClassLoader@18b4aac2
         //parent = sun.misc.Launcher$ExtClassLoader@14ae5a5
         //parent1 = null
 ?
         // 測試當前類是那個加載器加載的
         ClassLoader classLoader = Class.forName("com.briup.chap13.Test07").getClassLoader();
         System.out.println("classLoader = " + classLoader);
 ?
         // 測試JDK內(nèi)置的類是誰加載的
         System.out.println("Class.forName(\"java.lang.Object\").getClassLoader() = " + Class.forName("java.lang.Object").getClassLoader());
 ?
         // 運行結(jié)果:
         //classLoader = sun.misc.Launcher$AppClassLoader@18b4aac2
         //Class.forName("java.lang.Object").getClassLoader() = null
 ?
         // 如何獲得系統(tǒng)類加載器可以加載的路徑
         System.out.println(System.getProperty("java.class.path"));
 ?
         // 運行結(jié)果:
         /*
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\deploy.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\access-bridge-64.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\cldrdata.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\dnsns.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jaccess.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jfxrt.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\localedata.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\nashorn.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunec.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunjce_provider.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunmscapi.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunpkcs11.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\zipfs.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\javaws.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\jce.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfr.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfxswt.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\jsse.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\management-agent.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\plugin.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\resources.jar;
         * C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar;
         * D:\JDProject\corejava\out\production\corejava;
         * C:\Users\35329\.m2\repository\junit\junit\4.12\junit-4.12.jar;
         * C:\Users\35329\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;
         * D:\idea\ideaIU-2020\lib\idea_rt.jar
         * */
     }
 }
 ?

獲取運行時類的完整結(jié)構(gòu)

通過反射獲取運行時類的完整結(jié)構(gòu)

Field、Method、Constructor、Superclass、Interface、Annotation

package com.briup.chap13;
 ?
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 ?
 /**
  * 通過反射獲得類的信息
  * @author 35329
  */
 public class Test08 {
     public static void main(String[] args) throws Exception {
         Class c1 = Class.forName("com.briup.chap13.user");
 ?
         // 獲得類的名字
         System.out.println("c1.getName() = " + c1.getName()); // 獲得包名 + 類名
         System.out.println("c1.getSimpleName() = " + c1.getSimpleName()); // 獲得類名
 ?
         System.out.println("-----------------------------------");
         // 獲得類的屬性
         Field[] fields = c1.getFields(); // 只能找到public屬性
 ?
         fields = c1.getDeclaredFields(); // 可以找到全部屬性
         for (Field field : fields) {
             System.out.println(field);
         }
 ?
         // 獲得指定屬性的值
         Field name = c1.getDeclaredField("name");
         System.out.println("name = " + name);
 ?
         System.out.println("-----------------------------------------");
         // 獲得類的方法
         Method[] methods = c1.getMethods(); // 獲得本類及其父類的全部public方法
         for (Method method : methods) {
             System.out.println("正常的:" + method);
         }
 ?
         Method[] declaredMethods = c1.getDeclaredMethods(); // 獲得本類的所有方法(包括私有的)
         for (Method declaredMethod : declaredMethods) {
             System.out.println(declaredMethod);
         }
 ?
         // 獲得指定方法
         // 重載
         Method getName = c1.getMethod("getName", null);
         Method setName = c1.getMethod("setName", String.class);
         System.out.println("getName = " + getName);
         System.out.println("setName = " + setName);
 ?
         System.out.println("--------------------------------");
         // 獲得類的構(gòu)造器
         Constructor[] constructors = c1.getConstructors(); // 獲得public修飾的構(gòu)造方法
         for (Constructor constructor : constructors) {
             System.out.println(constructor);
         }
         constructors = c1.getDeclaredConstructors();// 獲得全部構(gòu)造方法
         for (Constructor constructor : constructors) {
             System.out.println("#" + constructor);
         }
 ?
         //獲得指定的構(gòu)造器
         Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
         System.out.println("指定構(gòu)造器:" + declaredConstructor);
     }
 }
 ?

小結(jié):

  • 在實際操作中,取得類的信息的操作代碼,不會經(jīng)常開發(fā)。
  • 一定要熟悉java.lang.reflect包的作用,反射機制。
  • 如何取得屬性、方法、構(gòu)造器的名稱,修飾符等。

有了Class對象,能做什么?

創(chuàng)建一個類的對象:調(diào)用Class對象的newInstance()方法

  • 類必須有一個無參數(shù)的構(gòu)造器
  • 類的構(gòu)造器的訪問權(quán)限需要足夠

思考?難道沒有無參的構(gòu)造器就不能創(chuàng)建對象了嗎?只要在操作的時候明確的調(diào)用類中的構(gòu)造器,并將參數(shù)傳遞進去之后,才可以實例化操作。

步驟如下:

  • 通過Class類的getDeclaredConstructor(Class ... parameterTypes)取得本類的指定形參類型的構(gòu)造器。
  • 向構(gòu)造器的形參中傳遞一個對象數(shù)組進去,里面包含了構(gòu)造器中所需的各個參數(shù)。
  • 通過Constructor實例化對象。

通過指定的方法

通過反射,調(diào)用類中的方法,通過Method類完成

  • 通過Class類的getMethod(String name, Class ... parameter Types)方法取得一個Method對象,并設置此方法操作時所需要的參數(shù)類型。
  • 之后使用Object invoke(Object obj, Object[] args)進行調(diào)用,并向方法中傳遞要設置的obj對象的參數(shù)信息。

Object invoke(Object obj, Object ...args)

  • Object對應原方法的返回值,若原方法無返回值,此時返回null
  • 若原方法為靜態(tài)方法,此時形參Object obj可為null
  • 若原方法形參列表為空,則Object[] args為null
  • 若原方法聲明為private,則需要在調(diào)用此invoke()方法前,顯示調(diào)用方法對象的setAccessible(true)方法,將可訪問private修飾的方法。

setAccessible

  • Method和Field、Constructor對象都有setAccessible()方法
  • setAccessible()作用是啟示和禁用訪問安全檢查的開關
  • 參數(shù)值為true則指示反射的對象在使用時應該取消Java語言訪問檢查。
    • 提高反射的效率,如果代碼中必須用反射,而該句代碼需要頻繁的被調(diào)用,那么請設置為true
    • 使得原本無法訪問的私有成員也可以訪問
  • 參數(shù)值為false則指示反射的對象應該實施Java語言訪問檢查。
package com.briup.chap13;
 ?
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Map;
 ?
 /**
  * 分析性能問題
  * @author 35329
  */
 public class Test10 {
     // 通過普通方法調(diào)用
     public static void test01(){
         user user = new user();
         long startTime = System.currentTimeMillis();
         for (int i = 0; i < 1000000000; i++) {
             user.getName();
         }
 ?
         long endTime = System.currentTimeMillis();
         System.out.println("普通方法執(zhí)行10億次:" + (endTime - startTime) + "ms");
     }
     // 反射方法調(diào)用
     public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
         user user = new user();
         Class c1 = user.getClass();
         Method getName = c1.getDeclaredMethod("getName", null);
 ?
         long startTime = System.currentTimeMillis();
         for (int i = 0; i < 1000000000; i++) {
             getName.invoke(user,null);
         }
         long endTime = System.currentTimeMillis();
 ?
         System.out.println("反射方法執(zhí)行10億次:" + (endTime - startTime) + "ms");
     }
     // 反射方法調(diào)用 關閉檢測
     public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
         user user = new user();
         Class c1 = user.getClass();
         Method getName = c1.getDeclaredMethod("getName", null);
         getName.setAccessible(true);
 ?
         long startTime = System.currentTimeMillis();
         for (int i = 0; i < 1000000000; i++) {
             getName.invoke(user,null);
         }
         long endTime = System.currentTimeMillis();
 ?
         System.out.println("關閉檢測執(zhí)行10億次:" + (endTime - startTime) + "ms");
     }
 ?
     public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         test01();
         test02();
         test03();
     }
 }
 ?

反射操作泛型(了解即可)

  • Java采用泛型擦除的機制來引入泛型,Java中的泛型僅僅是給編譯器javac使用的確保數(shù)據(jù)的安全性和免去強制類型轉(zhuǎn)換問題,但是,一旦編譯完成,所有和泛型有關的類型全部擦除。
  • 為了通過反射操作這些類型,Java新增了ParameterizedType、GenericArrayType、TypeVariable和WildcardType幾種類型來代表不能被歸一到Class類中的類型但是又和原始類型齊名的類型。
  • ParameterizedType:表示一種參數(shù)化類型,比如Collection<String>
  • GenericArrayType:表示一種元素類型的參數(shù)化類型或者類型變量的數(shù)組類型
  • TypeVariable:是各種類型變量的公共接口
  • WildcardType:代表一種通配符類型表達式

反射操作注解

練習:什么是ORM?

  • Object relationship Mapping -->對象關系映射
  • 類和表結(jié)構(gòu)的映射關系
  • 類和表結(jié)構(gòu)對應
  • 屬性和字段對應
  • 對象和記錄對應
package com.briup.chap13;
 ?
 import java.lang.annotation.*;
 import java.lang.reflect.Field;
 ?
 /**
  * 練習反射操作注解
  * @author 35329
  */
 public class Test12 {
     public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
         Class<?> c1 = Class.forName("com.briup.chap13.Student2");
 ?
         // 通過反射獲取注解
         Annotation[] annotations = c1.getAnnotations();
         for (Annotation annotation : annotations) {
             System.out.println(annotation);
         }
 ?
         // 獲得注解的Value值
         TableBriup tableBriup = c1.getAnnotation(TableBriup.class);
         String value = tableBriup.value();
         System.out.println(value);
 ?
         // 獲得類指定的注解
         Field f = c1.getDeclaredField("name");
         FieldBriup annotation = f.getAnnotation(FieldBriup.class);
         System.out.println(annotation.columnName());
         System.out.println(annotation.type());
         System.out.println(annotation.length());
 ?
     }
 }
 ?
 @TableBriup("db_student")
 class Student2{
 ?
     @FieldBriup(columnName = "db_id", type = "int", length = 10)
     private int id;
     @FieldBriup(columnName = "db_age", type = "int", length = 10)
     private int age;
     @FieldBriup(columnName = "db_name", type = "varchar", length = 3)
     private String name;
 ?
     public Student2() {
     }
 ?
     public Student2(int id, int age, String name) {
         this.id = id;
         this.age = age;
         this.name = name;
     }
 ?
     @Override
     public String toString() {
         return "Test12{" +
                 "id=" + id +
                 ", age=" + age +
                 ", name='" + name + '\'' +
                 '}';
     }
 ?
     public int getId() {
         return id;
     }
 ?
     public void setId(int id) {
         this.id = id;
     }
 ?
     public int getAge() {
         return age;
     }
 ?
     public void setAge(int age) {
         this.age = age;
     }
 ?
     public String getName() {
         return name;
     }
 ?
     public void setName(String name) {
         this.name = name;
     }
 }
 ?
 // 類名注解
 @Target(ElementType.TYPE)
 @Retention(RetentionPolicy.RUNTIME)
 @interface TableBriup{
     String value();
 }
 ?
 // 屬性的注解
 @Target(ElementType.FIELD)
 @Retention(RetentionPolicy.RUNTIME)
 @interface FieldBriup{
     String columnName();
     String type();
     int length();
 }

到此這篇關于Java中注解與反射的詳細介紹的文章就介紹到這了,更多相關Java注解與反射內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • springMVC中的view視圖詳細解析

    springMVC中的view視圖詳細解析

    這篇文章主要介紹了springMVC中的view視圖,springMVC視圖的種類很多,默認有轉(zhuǎn)發(fā)視圖和重定向視圖,本文就每一種視圖給大家詳細介紹,需要的朋友可以參考下
    2022-03-03
  • SpringBoot日志配置SLF4J和Logback的方法實現(xiàn)

    SpringBoot日志配置SLF4J和Logback的方法實現(xiàn)

    日志記錄是不可或缺的一部分,本文主要介紹了SpringBoot日志配置SLF4J和Logback的方法實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-04-04
  • Postman form-data、x-www-form-urlencoded的區(qū)別及說明

    Postman form-data、x-www-form-urlencoded的區(qū)別及說明

    這篇文章主要介紹了Postman form-data、x-www-form-urlencoded的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Java8實現(xiàn)Stream流的合并的方法展示

    Java8實現(xiàn)Stream流的合并的方法展示

    本文介紹了Java8中Stream流的合并方法,包括concat()、flatMap()和reduce()三種方法。其中,concat()方法可以將兩個Stream流合并成一個,flatMap()方法可以將一個Stream流中的元素映射成多個Stream流并合并成一個,reduce()方法可以將Stream流中的元素逐個合并成一個結(jié)果
    2023-05-05
  • Java?超詳細講解字符流

    Java?超詳細講解字符流

    字符流就是在字節(jié)流的基礎上,加上編碼,形成的數(shù)據(jù)流,字符流出現(xiàn)的意義是因為字節(jié)流在操作字符時,可能會有中文導致的亂碼,所以由字節(jié)流引申出了字符流
    2022-04-04
  • Java Servlet線程中AsyncContext異步處理Http請求

    Java Servlet線程中AsyncContext異步處理Http請求

    這篇文章主要介紹了Java Servlet線程中AsyncContext異步處理Http請求及在業(yè)務中應用,AsyncContext是Servlet 3.0使Servlet 線程不再需要一直阻塞,直到業(yè)務處理完畢才能再輸出響應,最后才結(jié)束該Servlet線程
    2023-03-03
  • Java實現(xiàn)后端跨域的常見解決方案

    Java實現(xiàn)后端跨域的常見解決方案

    跨源資源共享(CORS——Cross-Origin Resource Sharing,跨源資源共享,或通俗地譯為跨域資源共享)是一種基于 HTTP 頭的機制,跨域的解決方案有很多種,前后端都有,本文給大家主要介紹Java實現(xiàn)后端跨域的常見解決方案,需要的朋友可以參考下
    2024-04-04
  • spring 整合JDBC和AOP事務的方法

    spring 整合JDBC和AOP事務的方法

    這篇文章主要介紹了spring 整合JDBC和AOP事務的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • 詳細解讀Java的Lambda表達式

    詳細解讀Java的Lambda表達式

    這篇文章主要介紹了詳細解讀Java的Lambda表達式,lambda?表達式?是Java?8新加入的新特性,它在Java中是引入了函數(shù)式編程這一概念,需要的朋友可以參考下
    2023-04-04
  • Java實現(xiàn)Html轉(zhuǎn)Pdf的方法

    Java實現(xiàn)Html轉(zhuǎn)Pdf的方法

    這篇文章主要介紹了Java實現(xiàn)Html轉(zhuǎn)Pdf的方法,實例分析了java基于ITextRenderer類操作頁面及系統(tǒng)自帶字體生成pdf文件的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07

最新評論