日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

java 反射 Constructor、Method、Field 基本用法

發布時間:2025/1/21 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 反射 Constructor、Method、Field 基本用法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

java反射主要從以下幾個方面理解

  • 理解 Class 類
  • 理解 Java 的類加載機制
  • 學會使用 ClassLoader 進行類加載
  • 理解反射的機制
  • 掌握 Constructor、Method、Field 類的用法
  • 理解并掌握動態代理

1、理解Class類

Java程序在運行時,Java運行時系統一直對所有的對象進行所謂的運行時類型標識,即所謂的RTTI。這項信息紀錄了每個對象所屬的類。虛擬機通常使用運行時類型信息選準正確方法去執行,用來保存這些類型信息的類是Class類。Class類封裝一個對象和接口運行時的狀態,當裝載類時,Class類型的對象自動創建。
簡單解釋上面一段話
1、Class類也是類的一種,只是名字和class關鍵字高度相似。Java是大小寫敏感的語言。
2、Class類的對象內容是你創建的類的類型信息,比如你創建一個shapes類,那么,Java會生成一個內容是shapes的Class類的對象。
3、Class類的對象不能像普通類一樣,以 new shapes() 的方式創建,它的對象只能由JVM創建,因為這個類沒有public構造函數。
4、Class類的作用是運行時提供或獲得某個對象的類型信息。

Class原理

所有java類都是繼承了object這個類,在object這個類中有一個方法:getclass().這個方法是用來取得該類已經被實例化了的對象的該類的引用,這個引用指向的是Class類的對象。

怎么獲取Class對象

1、Class類的forName方法

Class<?> aClass = Class.forName("com.sl.reflect.Student");

2、對象的getClass()方法

Student student = new Student();Class<? extends Student> aClass1 = student.getClass();

3、使用類名加.class

Class classes = Student.class.getClass();

4、通過ClassLoader對象的loadClass()方法

Class<?> aClass2 = ClassLoader.getSystemClassLoader().loadClass("com.sl.reflect.Student");

Class類的常用方法

image.png

敲黑板調用newInstance()方法時,調用的是無參構造器,所以每個類中一定要聲明一個無參構造器

ClassLoader加載

類裝載器是用來把類(class)裝載進 JVM 的。JVM 規范定義了兩種類型的類裝載器:啟動類裝載器(bootstrap)和用戶自定義裝載器(user-defined class loader)。 JVM在運行時會產生3個類加載器組成的初始化加載器層次結構 ,如下圖所示:

?

image.png

//1、獲取系統類的加載器ClassLoader classLoader = ClassLoader.getSystemClassLoader();System.out.println(classLoader);//2. 獲取系統類加載器的父類加載器(擴展類加載器,可以獲取).classLoader = classLoader.getParent();System.out.println(classLoader);//3. 獲取擴展類加載器的父類加載器(引導類加載器,不可獲取).classLoader = classLoader.getParent();System.out.println(classLoader);

注意系統類加載器可以加載當前項目src目錄下面的所有類,如果文件也放在src下面,也可以用類加載器來加載調用 getResourceAsStream 獲取類路徑下的文件對應的輸入流。

//文件夾在src下InputStream resourceAsStream = ClassLoader.getSystemClassLoader().getResourceAsStream("text1.txt");//文件夾在包名下InputStream resourceAsStream1 = ClassLoader.getSystemClassLoader().getResourceAsStream("com/sl/reflect/text2.txt");

反射

Java反射機制主要提供了以下功能

  • 在運行時構造任意一個類的對象
  • 在運行時獲取任意一個類所具有的成員變量和方法
  • 在運行時調用任意一個對象的方法(屬性)
  • 生成動態代理

Student測試類

/*** @author shuliangzhao* @Title: Student* @ProjectName design-parent* @Description: TODO* @date 2019/6/15 23:08*/ public class Student {private String name;private Integer age;public Student() {}public Student(String name,Integer age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;} }

Method類

public static void testMethod() throws Exception {Class<Student> aClass = (Class<Student>) Class.forName("com.sl.reflect.Student");//1.獲取方法// 獲取取clazz對應類中的所有方法--方法數組(一)// 不能獲取private方法,并且獲取從父類繼承來的所有方法Method[] methods = aClass.getMethods();for (Method method:methods) {System.out.println(method);}System.out.println("================================");//2.獲取方法// 獲取取clazz對應類中的所有方法--方法數組(一)// 不能獲取private方法,不獲取從父類繼承來的所有方法Method[] declaredMethods = aClass.getDeclaredMethods();for (Method method:declaredMethods) {System.out.println(method);}System.out.println("=================================");// 1.3.獲取指定的方法// 需要參數名稱和參數列表,無參則不需要寫// 對于方法public void setName(String name) { }Method method = aClass.getDeclaredMethod("setName", String.class);System.out.println(method);// 而對于方法public void setAge(int age) { }method = aClass.getDeclaredMethod("setAge", Integer.class);System.out.println(method);// 這樣寫是獲取不到的,如果方法的參數類型是int型// 如果方法用于反射,那么要么int類型寫成Integer: public void setAge(Integer age) { }// 要么獲取方法的參數寫成int.class//2.執行方法// invoke第一個參數表示執行哪個對象的方法,剩下的參數是執行方法時需要傳入的參數Object obje = aClass.newInstance();method.invoke(obje,2);//如果一個方法是私有方法,第三步是可以獲取到的,但是這一步卻不能執行//私有方法的執行,必須在調用invoke之前加上一句method.setAccessible(true);}/*** 把類對象和類方法名作為參數,執行方法** 把全類名和方法名作為參數,執行方法* 可變參數可以放數組* @param obj: 方法執行的那個對象.* @param methodName: 類的一個方法的方法名. 該方法也可能是私有方法.* @param args: 調用該方法需要傳入的參數* @return: 調用方法后的返回值**/public Object invoke(Object obj, String methodName, Object ... args) throws Exception{//1. 獲取 Method 對象// 因為getMethod的參數為Class列表類型,所以要把參數args轉化為對應的Class類型。Class [] parameterTypes = new Class[args.length];for(int i = 0; i < args.length; i++){parameterTypes[i] = args[i].getClass();System.out.println(parameterTypes[i]);}Method method = obj.getClass().getDeclaredMethod(methodName, parameterTypes);//如果使用getDeclaredMethod,就不能獲取父類方法,如果使用getMethod,就不能獲取私有方法////2. 執行 Method 方法//3. 返回方法的返回值return method.invoke(obj, args);}

Field類

public static void testField() throws Exception {Class<Student> aClass = (Class<Student>) Class.forName("com.sl.reflect.Student");//1.獲取字段// 1.1 獲取所有字段 -- 字段數組// 可以獲取公用和私有的所有字段,但不能獲取父類字段Field[] declaredFields = aClass.getDeclaredFields();for (Field field:declaredFields) {System.out.println(field);}System.out.println("=============================");// 1.2獲取指定字段Field field = aClass.getDeclaredField("name");System.out.println(field.getName());System.out.println("==============================");Student student = new Student();//如果字段是私有的,不管是讀值還是寫值,都必須先調用setAccessible(true)方法field.setAccessible(true);student.setAge(1);student.setName("張三");//2.使用字段// 2.1獲取指定對象的指定字段的值Object o = field.get(student);System.out.println(o);System.out.println("==========================");// 2.2設置指定對象的指定對象Field值field.set(student, "DEF");System.out.println(student.getName());}

Constructor類

public static void testConstructor() throws Exception{Class<Student> aClass = (Class<Student>) Class.forName("com.sl.reflect.Student");//1. 獲取 Constructor 對象// 1.1 獲取全部Constructor<?>[] constructors = aClass.getConstructors();for (Constructor constructor:constructors) {System.out.println(constructor);}System.out.println("============================");// 1.2獲取某一個,需要參數列表Constructor<Student> constructor = aClass.getConstructor(String.class, Integer.class);System.out.println(constructor);System.out.println("============================");//2. 調用構造器的 newInstance() 方法創建對象Object obj = constructor.newInstance("zhagn", 1);}

Annotation

@Retention(RetentionPolicy.RUNTIME) @Target(value={ElementType.METHOD}) public @interface AgeValidator {public int min();public int max(); }public static void testAnnotation() throws Exception{Class<?> aClass = Class.forName("com.sl.reflect.Student");Object o = aClass.newInstance();Method method = aClass.getDeclaredMethod("setAge", Integer.class);int val = 6;AgeValidator annotation = method.getAnnotation(AgeValidator.class);if (annotation != null) {if (annotation instanceof AgeValidator) {AgeValidator ageValidator = annotation;if (val < ageValidator.min() || val > ageValidator.max()) {throw new RuntimeException("年齡非法");}}}method.invoke(o,20);System.out.println(o);}

小結

  • Class: 是一個類; 一個描述類的類.
      封裝了描述方法的 Method,
    描述字段的 Filed,
    描述構造器的 Constructor 等屬性.
  • 如何得到 Class 對象:
      2.1 Person.class
      2.2 person.getClass()
      2.3 Class.forName("com.atguigu.javase.Person")
  • 關于 Method:
      3.1 如何獲取 Method:
        1). getDeclaredMethods: 得到 Method 的數組.
        2). getDeclaredMethod(String methondName, Class ... parameterTypes)
      3.2 如何調用 Method
        1). 如果方法時 private 修飾的, 需要先調用 Method 的 setAccessible(true), 使其變為可訪問
        2). method.invoke(obj, Object ... args);
  • 關于 Field:
      4.1 如何獲取 Field: getField(String fieldName)
      4.2 如何獲取 Field 的值:
        1). setAccessible(true)
        2). field.get(Object obj)
      4.3 如何設置 Field 的值:
        field.set(Obejct obj, Object val)
  • 了解 Constructor 和 Annotation
  • 反射和泛型.
      6.1 getGenericSuperClass: 獲取帶泛型參數的父類
      6.2 Type 的子接口: ParameterizedType
      6.3 可以調用 ParameterizedType 的 Type[] getActualTypeArguments() 獲取泛型參數的數組.
  • 總結

    以上是生活随笔為你收集整理的java 反射 Constructor、Method、Field 基本用法的全部內容,希望文章能夠幫你解決所遇到的問題。

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