一、前置知識(shí)點(diǎn)
1、運(yùn)行java程序需要java虛擬機(jī)(JVM)
2淀歇、我們編寫(xiě)的java代碼需要被編譯成.class文件
3、.class文件會(huì)被類(lèi)加載器加載到j(luò)ava虛擬機(jī)當(dāng)中
4匈织、.class文件記錄著類(lèi)的所有的信息
個(gè)人理解:
計(jì)算機(jī)通過(guò)加載到的.class文件已經(jīng)知道類(lèi)的所有信息了浪默,但是為了讓人也能知道這個(gè)類(lèi)中描述的所有信息牡直,所以才有了反射,就是將類(lèi)的詳細(xì)信息以對(duì)象的形式表達(dá)出來(lái)纳决,方便人去進(jìn)行手動(dòng)管理碰逸。
就像汽車(chē)一樣,原本我們使用汽車(chē)能開(kāi)就可以了阔加,但是難免有人想改裝它饵史,這時(shí)候就需要提供這個(gè)車(chē)子的架構(gòu)圖了。個(gè)人覺(jué)得之所以有反射胜榔,就是這個(gè)道理胳喷。
二、測(cè)試實(shí)例
(1)基礎(chǔ)類(lèi)
測(cè)試注解
package com.suncy.article.article10;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyRefAnnotation {
}
測(cè)試基礎(chǔ)類(lèi)
兩個(gè)構(gòu)造方法夭织,兩個(gè)成員變量吭露,兩個(gè)成員方法
package com.suncy.article.article10;
import org.springframework.beans.factory.annotation.Value;
//添加測(cè)試注解
@MyRefAnnotation
public class MyRefTest {
public int a;
private String b;
public MyRefTest() {
}
private MyRefTest(String b) {
this.b = b;
}
public MyRefTest(int a) {
this.a = a;
}
@Value("444")
public void testA(String a) throws Exception{
System.out.println("ttttt" + a);
}
private void testB() {
}
}
(2) Class<?> 對(duì)象提供的一些方法
package com.suncy.article.article10;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
public class ReflexTestMain {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException,
IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
//基本獲取方法
System.out.println("=====================獲取Class<?>的三種方式=====================");
MyRefTest myRefTest = new MyRefTest();
Class<?> cls = myRefTest.getClass();
System.out.println("myRefTest.getClass() : " + cls);
Class<?> cls1 = MyRefTest.class;
System.out.println("MyRefTest.class : " + cls1);
Class<?> cls2 = Class.forName("com.suncy.article.article10.MyRefTest");
System.out.println("Class.forName(xxx) : " + cls2);
System.out.println();
//基本使用方法
//一、獲取構(gòu)造方法
//1尊惰、獲取所有的公有構(gòu)造方法
System.out.println("=======================獲取Constructor<?>=========================");
Constructor<?>[] constructors = cls.getConstructors();
System.out.println("cls.getConstructors() : " + Arrays.toString(constructors));
//2讲竿、獲取所有構(gòu)造方法 包括私有的 受保護(hù)的
Constructor<?>[] constructors1 = cls.getDeclaredConstructors();
System.out.println("cls.getDeclaredConstructors() : " + Arrays.toString(constructors1));
//3、獲取公有的無(wú)參構(gòu)造方法
Constructor<?> constructor = cls.getConstructor();
System.out.println("cls.getConstructor() : " + constructor);
//4弄屡、調(diào)用構(gòu)造方法 生成對(duì)象
System.out.println("通過(guò)constructor實(shí)例化對(duì)象");
MyRefTest myRefTest1 = (MyRefTest) constructor.newInstance();
System.out.println("myRefTest : " + myRefTest);
System.out.println("myRefTest1 : " + myRefTest1);
System.out.println();
System.out.println("=======================獲取Field=========================");
//二题禀、獲取成員變量
//1、獲取所有的公有字段
Field[] fields = cls.getFields();
System.out.println("cls.getFields() : " + Arrays.toString(fields));
//2膀捷、獲取所有的字段
Field[] fields1 = cls.getDeclaredFields();
System.out.println("cls.getDeclaredFields() : " + Arrays.toString(fields1));
//3投剥、獲取某個(gè)公有字段
Field fieldA = cls.getField("a");
System.out.println("cls.getField(xx) : " + fieldA);
//4、獲取某個(gè)字段担孔,包含私有的
Field fieldB = cls.getDeclaredField("b");
System.out.println("cls.getDeclaredField(xx) : " + fieldB);
System.out.println();
System.out.println("======================獲取Method=========================");
//三、獲取成員方法
//1吃警、獲取所有公有的成員方法
Method[] methods = cls.getMethods();
System.out.println("cls.getMethods() : " + Arrays.toString(methods));
//2糕篇、獲取所有的成員方法 包含私有
Method[] methods1 = cls.getDeclaredMethods();
System.out.println("cls.getDeclaredMethods() : " + Arrays.toString(methods1));
//3、獲取某個(gè)公有字段
Method methodA = cls.getMethod("testA", String.class);
System.out.println("cls.getMethod(xx, String.class) : " + methodA);
//4酌心、獲取某個(gè)字段拌消,包含私有的
Method methodB = cls.getDeclaredMethod("testB");
System.out.println("cls.getDeclaredMethod(xx) : " + methodB);
System.out.println();
System.out.println("======================獲取類(lèi)上的Annotation==========================");
//四、獲取類(lèi)注解
//1安券、獲取類(lèi)上所有的注解
Annotation[] annotations = cls.getAnnotations();
System.out.println("cls.getAnnotations() : " + Arrays.toString(annotations));
//2墩崩、獲取類(lèi)上特定的注解
MyRefAnnotation annotation = cls.getAnnotation(MyRefAnnotation.class);
System.out.println("cls.getAnnotation(xx) : " + annotation);
//3、獲取不存在的注解 會(huì)返回null
Override annotation1 = cls.getAnnotation(Override.class);
System.out.println("cls.getAnnotation(xx) : " + annotation1);
System.out.println();
//五侯勉、判斷類(lèi)的類(lèi)型
System.out.println("======================判斷類(lèi)的類(lèi)型==========================");
System.out.println("cls.isArray() : " + cls.isArray()); //數(shù)組類(lèi)
System.out.println("cls.isAnnotation() : " + cls.isAnnotation()); //注解類(lèi)
System.out.println("cls.isAnnotationPresent(xx) : " + cls.isAnnotationPresent(MyRefAnnotation.class)); //特定注解類(lèi)
System.out.println("cls.isInterface() : " + cls.isInterface()); //接口類(lèi)
System.out.println("cls.isLocalClass() : " + cls.isLocalClass()); //局部類(lèi)
System.out.println("cls.isEnum() : " + cls.isEnum()); //枚舉類(lèi)
System.out.println("cls.isAnonymousClass() : " + cls.isAnonymousClass()); //匿名類(lèi)
System.out.println("cls.isMemberClass() : " + cls.isMemberClass()); //內(nèi)部類(lèi)
System.out.println("cls.isInstance(xx) : " + cls.isInstance(myRefTest)); //判斷對(duì)象是否是該類(lèi)實(shí)例
System.out.println();
System.out.println("=======================Class<?>中的其他方法=========================");
//六鹦筹、其他方法
//獲取類(lèi)加載器
ClassLoader classLoader = cls.getClassLoader();
System.out.println("cls.getClassLoader() : " + classLoader);
Class<?>[] classes = cls.getClasses();
System.out.println("cls.getClasses() : " + Arrays.toString(classes));
Class<?>[] classes1 = cls.getDeclaredClasses();
System.out.println("cls.getDeclaredClasses() : " + Arrays.toString(classes1));
//獲取類(lèi)的名稱(chēng)(完整路徑)
String name = cls.getName();
System.out.println("cls.getName() : " + name);
//獲取類(lèi)的名稱(chēng)(類(lèi)名稱(chēng))
String name1 = cls.getSimpleName();
System.out.println("cls.getSimpleName() : " + name1);
//獲取類(lèi)的名稱(chēng)(獲取所傳類(lèi)從java語(yǔ)言規(guī)范定義的格式輸出)
String name2 = cls.getCanonicalName();
System.out.println("cls.getCanonicalName() : " + name2);
//獲取父類(lèi)類(lèi)型
Class<?> clsSuperclass = cls.getSuperclass();
System.out.println("cls.getSuperclass() : " + clsSuperclass);
//獲取接口類(lèi)型
Class<?>[] clsSuperclass1 = cls.getInterfaces();
System.out.println("cls.getInterfaces() : " + Arrays.toString(clsSuperclass1));
//獲取包名
Package clsPackage = cls.getPackage();
System.out.println("cls.getPackage() : " + clsPackage);
}
}
響應(yīng)結(jié)果
(3) Method、Field址貌、Annotation提供的一些方法
package com.suncy.article.article10;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
public class ReflexTestMain1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException,
IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
Class<?> cls = Class.forName("com.suncy.article.article10.MyRefTest");
//拿到Constructor對(duì)象
Constructor<MyRefTest> constructor = (Constructor<MyRefTest>) cls.getConstructor();
System.out.println("拿到MyRefTest類(lèi)的Constructor對(duì)象 : " + constructor);
//根據(jù)constructor實(shí)例化對(duì)象
MyRefTest myRefTest = constructor.newInstance();
System.out.println("根據(jù)這個(gè)myRefTest的constructor構(gòu)造對(duì)象(constructor.newInstance()) : " + myRefTest);
//拿到cls所有方法
Method[] methods = cls.getMethods();
System.out.println("拿到這個(gè)類(lèi)所有公有成員方法(cls.getMethods()) : " + Arrays.toString(methods));
System.out.println();
//拿到cls特定的某個(gè)方法 執(zhí)行myRefTest對(duì)象的這個(gè)特定的方法
System.out.println("=============testA方法對(duì)應(yīng)的Method對(duì)象================");
Method methodTestA = cls.getMethod("testA", String.class);
System.out.println("拿到testA方法的Method : " + methodTestA);
// 調(diào)用對(duì)象方法
System.out.println("調(diào)用testA方法 : ");
methodTestA.invoke(myRefTest, "22312312");
//拿到這個(gè)特定Method方法上的注解
System.out.println("拿到methodA方法上的注解 : " + Arrays.toString(methodTestA.getDeclaredAnnotations()));
//拿到這個(gè)特定Method方法上的異常
System.out.println("拿到methodA方法上的異常 : " + Arrays.toString(methodTestA.getExceptionTypes()));
System.out.println();
//給myRefTest對(duì)象的a字段設(shè)置值 通過(guò)Field對(duì)象拿到這個(gè)a字段的值
System.out.println("=============a字段對(duì)應(yīng)的Field對(duì)象================");
myRefTest.a = 34;
Field fieldA = cls.getField("a");
System.out.println("拿到a字段Field : " + fieldA);
System.out.println("拿到字段a的值 : " + fieldA.getInt(myRefTest));
System.out.println("是否能反射出a字段屬性值 : " + fieldA.isAccessible());
//設(shè)置是否能反射該屬性數(shù)
System.out.println("修改是否能反射a字段屬性值 : fieldA.setAccessible(true)");
fieldA.setAccessible(true);
System.out.println("是否能反射出a字段屬性值 : " + fieldA.isAccessible());
System.out.println("是否是枚舉類(lèi)型的元素 : " + fieldA.isEnumConstant());
System.out.println();
//拿到cls類(lèi)上持有的注解
System.out.println("==========MyRefAnnotation注解對(duì)應(yīng)的Annotation對(duì)象================");
Annotation annotation = cls.getAnnotation(MyRefAnnotation.class);
System.out.println("獲取MyRefAnnotation注解的Annotation : " + annotation);
//返回cls類(lèi)的規(guī)范名稱(chēng)(獲取所傳類(lèi)從java語(yǔ)言規(guī)范定義的格式輸出)
System.out.println("拿到類(lèi)的規(guī)范名稱(chēng) : " + cls.getCanonicalName());
//返回注解的注解類(lèi)型
System.out.println("拿到注解的annotationType : " + annotation.annotationType());
//返回注解的規(guī)范名稱(chēng)(獲取所傳類(lèi)從java語(yǔ)言規(guī)范定義的格式輸出)
System.out.println("拿到注解的規(guī)范名稱(chēng) : " + annotation.annotationType().getCanonicalName());
}
}
響應(yīng)結(jié)果
三铐拐、總結(jié)
1徘键、反射相關(guān)類(lèi):Class、Constructor遍蟋、Method吹害、Field、Annotation虚青。
2它呀、代理常用的一種方式是: methodTestA.invoke(myRefTest, "22312312");
methodTestA表示一個(gè)特定的Method對(duì)象。myRefTest表示對(duì)象棒厘。22312312表示參數(shù)纵穿、參數(shù)數(shù)量需要去看Method指定方法的參數(shù)是多少。
3绊谭、多寫(xiě)demo測(cè)試一下政恍,更為直觀,印象更深达传。