概念:在某些特殊場合中編寫代碼時不確定要創(chuàng)建什么類型的對象掂之,也不確定要調(diào)用什么樣的方法掠哥,這些都希望通過運行時傳遞的參數(shù)來決定霞赫,該機制叫做動態(tài)編程技術(shù)梁棠,也就是反射機制
通俗來說置森,反射機制就是用于動態(tài)創(chuàng)建對象并且動態(tài)調(diào)用方法的機制
Class類:
- Class類的實例可以用于描述Java應(yīng)用程序中的類和接口,也就是一種數(shù)據(jù)類型
- 該類沒有公共構(gòu)造方法掰茶,該類的實例由Java虛擬機和類加載器自動構(gòu)造完成暇藏,本質(zhì)上就是加載到內(nèi)存中的運行時類
獲取Class對象的方式:
- 使用數(shù)據(jù)類型.Class的方式可以獲取對應(yīng)類型的Class對象(較常用)
//1. 使用數(shù)據(jù)類型.class的方式可以獲取對應(yīng)類型的Class對象
Class c1 = String.class;
System.out.println("c1 = " + c1); //自動調(diào)用toString方法,返回類的完全限定名: class java.lang.String
c1 = int.class;
System.out.println("c1 = " + c1); //返回基本數(shù)據(jù)類型的名稱 int
c1 = void.class;
System.out.println("c1 = " + c1); //返回void void
- 使用引用/對象.getClass()的方式可以獲取對應(yīng)類型的Class對象
//2. 使用對象.getClass()的方式獲取對應(yīng)的Class對象
String str1 = new String("hello");
c1 = str1.getClass();
System.out.println("c1 = " + c1); //class java.lang.String
Integer it1 = 20;
c1 = it1.getClass();
System.out.println("c1 = " + c1); //class java.lang.Integer
int num = 5;
//num.getClass(); //基本數(shù)據(jù)類型的變量不能調(diào)用方法
- 使用包裝類.TYPE的方式可以獲取對應(yīng)基本數(shù)據(jù)類型的Class對象
//3. 使用包裝類.TYPE的方式來獲取對應(yīng)基本數(shù)據(jù)類型的Class對象
c1 = Integer.TYPE;
System.out.println("c1 = " + c1); //int
- 使用Class.forName()的方式來獲取參數(shù)指定類型的Class對象(完整名稱:包名.類名濒蒋,不能獲取基本數(shù)據(jù)類型的Class對象)(較常用)
//4. 調(diào)用Class類中的forName方法來獲取對應(yīng)的Class對象
//c1 = Class.forName("String"); //Error 必須寫完整的包名
//c1 = Class.forName("int"); //不能獲取基本數(shù)據(jù)類型的Class對象
c1 = Class.forName("java.lang.String");
System.out.println("c1 = " + c1); //class java.lang.String
- 使用類加載器ClassLoader的方式獲取指定類型的Class對象
//5. 使用類加載器的方式來獲取Class對象
ClassLoader classLoader = ClassTest.class.getClassLoader();
c1 = classLoader.loadClass("java.lang.String");
System.out.println("c1 = " + c1);
常用方法:
- static Class<?> forName(String className):用于獲取參數(shù)指定類型對應(yīng)的Class對象并返回
- T newInstance():用于創(chuàng)建該Class對象所表示類的新實例(已過時)
/**
* 用于測試的簡單Person類
*/
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//1. 使用原始方式以無參形式構(gòu)造Person類的對象并打印
Person p1 = new Person();
System.out.println("無參方式創(chuàng)建的對象是:" + p1);
System.out.println("----------------------------------------------");
//2. 使用反射機制以無參行駛構(gòu)造Person類型的對象并打印
Class c1 = Class.forName("Person");
System.out.println("無參方式創(chuàng)建的對象是:" + c1.newInstance());
Constructor類:主要用于描述獲取到的構(gòu)造方法信息
class類常用方法:
- Constructor<T> getConstructor(Class<?>... parameterTypes):用于獲取此Class對象所表示類型中參數(shù)指定的公共構(gòu)造方法
//1. 使用原始方式以無參形式構(gòu)造Person類的對象并打印
Person p1 = new Person();
System.out.println("無參方式創(chuàng)建的對象是:" + p1);
System.out.println("----------------------------------------------");
//2. 使用反射機制以無參行駛構(gòu)造Person類型的對象并打印
Class c1 = Class.forName("Person");
//System.out.println("無參方式創(chuàng)建的對象是:" + c1.newInstance());
//獲取Class對象對應(yīng)類中的無參構(gòu)造方法盐碱,也就是Person類中的無參構(gòu)造方法
Constructor constructor = c1.getConstructor();
//使用獲取到的無參構(gòu)造方法來構(gòu)造對應(yīng)類型的對象,也就是Person類型的對象
System.out.println("無參方式創(chuàng)建的對象是:" + constructor.newInstance());
System.out.println("----------------------------------------------");
//3. 使用原始方式以有參方式構(gòu)造Person類的對象并打印
Person p2 = new Person("張三", 20);
System.out.println("有參構(gòu)造方式創(chuàng)建的對象是:" + p2);
System.out.println("----------------------------------------------");
//4. 使用反射機制以有參方式構(gòu)造Person類型的對象并打印
//獲取Class對象對應(yīng)類中的有參構(gòu)造方法沪伙,也就是Person類中的有參構(gòu)造方法
Constructor constructor1 = c1.getConstructor(String.class, int.class);
//使用獲取到的有參構(gòu)造方法來構(gòu)造對應(yīng)類型的對象瓮顽,也就是Person類型的對象
//newInstance方法中的實參是用于給有參構(gòu)造方法的形參進行初始化的,也就是給name和age進行初始化的
System.out.println("有參構(gòu)造方式創(chuàng)建的對象是:" + constructor1.newInstance("張三", 20));
- Constructor<?>[] getConstructors():用于獲取此Class對象所表示類型中所有的公共構(gòu)造方法
//5. 使用反射機制獲取Person類中所有的公共構(gòu)造方法并打印
Constructor[] constructors = c1.getConstructors();
for (Constructor ct : constructors) {
System.out.println("構(gòu)造方法的訪問修飾符是:" + ct.getModifiers());
System.out.println("構(gòu)造方法的方法名稱是:" + ct.getName());
Class[] parameterTypes = ct.getParameterTypes();
System.out.println("構(gòu)造方法的所有參數(shù)類型是:");
for (Class cs : parameterTypes) {
System.out.print(cs + " ");
}
System.out.println();
System.out.println("----------------------------------------------");
Construcotr類常用方法:
- T newInstance(Object... initargs):使用此Constructor對象描述的構(gòu)造方法來構(gòu)造Class對象代表類型的新實例
- int getModifiers():獲取方法的訪問修飾符
- String getName():獲取方法的名稱
- Class<?>[] getParameterTypes():獲取方法的所有參數(shù)的類型
Field類:主要用于描述獲取到的單個成員變量信息
class類常用方法:
- Field getDeclaredField(String name):用于獲取此Class對象所表示類中參數(shù)指定的單個成員變量信息
- Field[] getDeclaredFields():用于獲取此Class對象所表示類中所有成員變量信息
//1. 使用原始方式來構(gòu)造對象以及獲取成員變量的數(shù)值并打印
Person p1 = new Person("張三", 20);
System.out.println("獲取到的成員變量數(shù)值為:" + p1.getName()); //張三
System.out.println("------------------------------------------------");
//2. 使用反射機制來構(gòu)造對象以及獲取成員變量的數(shù)值并打印
//2.1 獲取Class對象
Class c1 = Class.forName("Person");
//2.2 根據(jù)Class對象獲取對應(yīng)的有參構(gòu)造方法
Constructor constructor = c1.getConstructor(String.class, int.class);
//2.3 使用有參構(gòu)造方法來得到Person類型的對象
Object object = constructor.newInstance("張三", 20);
//2.4 根據(jù)Class對象獲取對應(yīng)的成員變量信息
Field field = c1.getDeclaredField("name");
//2.5 使用Person類型的對象來獲取成員變量的信息
//獲取對象object中名字為field成員變量的數(shù)值围橡,也就是成員變量name的數(shù)值
System.out.println("獲取到的成員變量數(shù)值為:" + field.get(object));
Field類常用方法:
Object get(Object obj):獲取參數(shù)對象obj中此Field對象所表示成員變量的數(shù)值
void set(Object obj, Object value):將參數(shù)對象obj中此Field對象表示成員變量的數(shù)值修改為參數(shù)value的數(shù)值
void setAccessible(boolean flag):當實參傳遞true時暖混, 則反射對象在使用時應(yīng)該取消Java語言訪問檢查
int getModifiers():獲取成員變量的訪問修飾符
Class<?> getType():獲取成員變量的數(shù)據(jù)類型
String getName():獲取成員變量的名稱
//3. 使用原始方式修改指定對象中成員變量的數(shù)值后再次打印
p1.setName("李四");
System.out.println("修改后成員變量的數(shù)值為:" + p1.getName());
System.out.println("------------------------------------------------");
//4. 使用反射機制修改指定對象中成員變量的數(shù)值后再次打印
//表示修改對象object中名字為field成員變量的數(shù)值為李四,也就是成員變量name的數(shù)值為李四
field.set(object, "李四");
System.out.println("修改后成員變量的數(shù)值為:" + field.get(object));
System.out.println("------------------------------------------------");
//5. 獲取Class類對象對應(yīng)類中所有的成員變量
Field[] declaredFields = c1.getDeclaredFields();
for (Field ft : declaredFields) {
System.out.println("獲取到的訪問修飾符為:" + ft.getModifiers());
System.out.println("獲取到的數(shù)據(jù)類型為:" + ft.getType());
System.out.println("獲取到的成員變量名稱是:" + ft.getName());
System.out.println("------------------------------------------------");
Method類:主要用于描述獲取到的單個成員方法信息
Class類常用方法:
- Method getMethod(String name, Class<?>... parameterTypes):用于獲取該Class對象表示類中名字為name翁授,參數(shù)為parameterTypes的指定公共成員方法
- Method[] getMethods():用于獲取該Class對象表示類中所有公共成員方法
Method類常用方法:
- Object invoke(Object obj, Object... args):使用對象obj來調(diào)用此Method對象所表示的成員方法拣播,實參傳遞args
- int getModifiers():獲取方法的訪問修飾符
- Class<?> getReturnType():獲取方法的返回值類型
- String getName():獲取方法的名稱
- Class<?>[] getParameterTypes():獲取方法所有參數(shù)的類型
- Class<?>[] getExceptionTypess():獲取方法的異常信息
//1. 使用原始方式構(gòu)造對象并調(diào)用方法打印結(jié)果
Person p1 = new Person("張三", 20);
System.out.println("調(diào)用方法的返回值是:" + p1.getName());
System.out.println("--------------------------------------------");
//2. 使用反射機制構(gòu)造對象并調(diào)用方法打印結(jié)果
//2.1 獲取Class對象
Class c1 = Class.forName("Person");
//2.2 根據(jù)Class對象來獲取對應(yīng)的有參構(gòu)造方法
Constructor constructor = c1.getConstructor(String.class, int.class);
//2.3 使用有參構(gòu)造方法構(gòu)造對象并記錄
Object object = constructor.newInstance("張三", 20);
//2.4 根據(jù)Class對象來獲取對應(yīng)的成員方法
Method method = c1.getMethod("getName");
//2.5 使用對象調(diào)用成員方法進行打印
//表示使用object對象調(diào)用method表示的方法晾咪,也就是調(diào)用getName來獲取姓名
System.out.println("調(diào)用方法的返回值是:" + method.invoke(object));
System.out.println("--------------------------------------------");
//3. 使用反射機制來獲取類中的所有成員方法并打印
Method[] methods = c1.getMethods();
for (Method mt : methods) {
System.out.println("成員方法的修飾符是:" + mt.getModifiers());
System.out.println("成員方法的返回值類型是:" + mt.getReturnType());
System.out.println("成員方法的名稱是:" + mt.getName());
System.out.println("成員方法的形參列表是:");
Class<?>[] parameterTypes = mt.getParameterTypes();
for (Class<?> ct : parameterTypes) {
System.out.println(ct + "");
}
System.out.println("成員方法的異常類型列表是:");
Class<?>[] exceptionTypes = mt.getExceptionTypes();
for (Class<?> ct : exceptionTypes) {
System.out.println(ct + " ");
}
System.out.println();
System.out.println("--------------------------------------------");
}
獲取其他結(jié)構(gòu)信息的方法:
- Package getPackage():獲取所在的包的信息
- Class<? super T> getSuperclass():獲取繼承的父類的信息
- Class<?>[] getInterfaces():獲取實現(xiàn)的所有接口
- Annotation[] getAnnotations():獲取注解信息
- Type[] getGenericInterfaces():獲取泛型信息
/**
* Student類
* @param <T>
* @param <E>
*/
@MyAnnotation
public class Student<T, E> extends Person implements Comparable<String>, Serializable {
@Override
public int compareTo(String o) {
return 0;
}
}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* 自定義注解
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
//獲取Student類型的Class對象
Class c1 = Class.forName("Student");
System.out.println("獲取到的包信息是:" + c1.getPackage());
System.out.println("獲取到的父類信息是:" + c1.getSuperclass());
System.out.println("獲取到的接口信息是:");
Class[] interfaces = c1.getInterfaces();
for (Class ct : interfaces) {
System.out.println(ct + "");
}
System.out.println();
System.out.println("-----------------------------------------------");
System.out.println("獲取到的注解信息是:");
Annotation[] annotations = c1.getAnnotations();
for (Annotation at : annotations) {
System.out.println(at + " ");
}
System.out.println();
System.out.println("-----------------------------------------------");
System.out.println("獲取到的泛型信息是:");
Type[] genericInterfaces = c1.getGenericInterfaces();
for (Type tt : genericInterfaces) {
System.out.println(tt + " ");
}
System.out.println();