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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

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

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

  • 理解 Class 類
  • 理解 Java 的類加載機(jī)制
  • 學(xué)會使用 ClassLoader 進(jìn)行類加載
  • 理解反射的機(jī)制
  • 掌握 Constructor、Method、Field 類的用法
  • 理解并掌握動態(tài)代理

1、理解Class類

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

Class原理

所有java類都是繼承了object這個類,在object這個類中有一個方法:getclass().這個方法是用來取得該類已經(jīng)被實(shí)例化了的對象的該類的引用,這個引用指向的是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

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

ClassLoader加載

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

?

image.png

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

注意系統(tǒng)類加載器可以加載當(dāng)前項(xiàng)目src目錄下面的所有類,如果文件也放在src下面,也可以用類加載器來加載調(diào)用 getResourceAsStream 獲取類路徑下的文件對應(yīng)的輸入流。

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

反射

Java反射機(jī)制主要提供了以下功能

  • 在運(yùn)行時構(gòu)造任意一個類的對象
  • 在運(yùn)行時獲取任意一個類所具有的成員變量和方法
  • 在運(yùn)行時調(diào)用任意一個對象的方法(屬性)
  • 生成動態(tài)代理

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對應(yīng)類中的所有方法--方法數(shù)組(一)// 不能獲取private方法,并且獲取從父類繼承來的所有方法Method[] methods = aClass.getMethods();for (Method method:methods) {System.out.println(method);}System.out.println("================================");//2.獲取方法// 獲取取clazz對應(yīng)類中的所有方法--方法數(shù)組(一)// 不能獲取private方法,不獲取從父類繼承來的所有方法Method[] declaredMethods = aClass.getDeclaredMethods();for (Method method:declaredMethods) {System.out.println(method);}System.out.println("=================================");// 1.3.獲取指定的方法// 需要參數(shù)名稱和參數(shù)列表,無參則不需要寫// 對于方法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);// 這樣寫是獲取不到的,如果方法的參數(shù)類型是int型// 如果方法用于反射,那么要么int類型寫成Integer: public void setAge(Integer age) { }// 要么獲取方法的參數(shù)寫成int.class//2.執(zhí)行方法// invoke第一個參數(shù)表示執(zhí)行哪個對象的方法,剩下的參數(shù)是執(zhí)行方法時需要傳入的參數(shù)Object obje = aClass.newInstance();method.invoke(obje,2);//如果一個方法是私有方法,第三步是可以獲取到的,但是這一步卻不能執(zhí)行//私有方法的執(zhí)行,必須在調(diào)用invoke之前加上一句method.setAccessible(true);}/*** 把類對象和類方法名作為參數(shù),執(zhí)行方法** 把全類名和方法名作為參數(shù),執(zhí)行方法* 可變參數(shù)可以放數(shù)組* @param obj: 方法執(zhí)行的那個對象.* @param methodName: 類的一個方法的方法名. 該方法也可能是私有方法.* @param args: 調(diào)用該方法需要傳入的參數(shù)* @return: 調(diào)用方法后的返回值**/public Object invoke(Object obj, String methodName, Object ... args) throws Exception{//1. 獲取 Method 對象// 因?yàn)間etMethod的參數(shù)為Class列表類型,所以要把參數(shù)args轉(zhuǎn)化為對應(yīng)的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. 執(zhí)行 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 獲取所有字段 -- 字段數(shù)組// 可以獲取公用和私有的所有字段,但不能獲取父類字段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();//如果字段是私有的,不管是讀值還是寫值,都必須先調(diào)用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設(shè)置指定對象的指定對象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獲取某一個,需要參數(shù)列表Constructor<Student> constructor = aClass.getConstructor(String.class, Integer.class);System.out.println(constructor);System.out.println("============================");//2. 調(diào)用構(gòu)造器的 newInstance() 方法創(chuàng)建對象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);}

小結(jié)

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

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

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。