文章目录
一、反射机制图解
首先通过下图了解反射机制,然后会对各个部分结合示例详细解释。
二、获取Class类实例化对象的方式
1、Class.forName(“全类名”)
- 将字节码文件加载进内存,返回Class对象。
- 多用于配置文件,将类名定义在配置文件中。读取文件,加载类。
- 推荐使用这种方式。
2、类名.class
- 通过类名的属性class获取。
- 多用于参数的传递。
3、对象.getClass()
- getClass()方法在Object类中定义着。
- 多用于对象的获取字节码文件的方式。
示例代码如下
package com.zzu.reflect;
public class Test {
public static void main(String[] args) throws Exception {
//1.Class.forName("全类名")
Class class1 = Class.forName("com.zzu.reflect.Student");
System.out.println(class1);
//2.类名.class
Class class2 = Student.class;
System.out.println(class2);
//3.对象.getClass()
Class class3 = new Student().getClass();
System.out.println(class3);
System.out.println(class1==class2);
System.out.println(class1==class3);
}
}
运行结果如下图:
结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
三、构造方法
1、获取构造方法
通过Class类中某些方法可以获取对应类中声明的构造方法实例对象,这些方法有:
- Constructor<?>[] getConstructors():返回该Class对象表示类中包含的所有public构造方法(不含继承)所对应的Constructor对象数组。
- Constructor getConstrutor(Class<?>… parameterTypes):返回与该Class对象表示类中参数列表相匹配的public构造方法(不含继承)对应的Constructor对象。
- Constructor<?>[] getDeclaredConstructors():返回该Class对象表示类中声明的所有构造方法(不区分访问权限)所对应的Constructor对象数组。
- Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes):返回与该Class对象表示类中参数列表相匹配的构造方法(不区分访问权限)对应的Constructor对象。
示例代码如下:
Student类
package com.zzu.reflect;
public class Student {
private String name;
private String mobile;
private String a;
protected String b;
String c;
private String d;
public Student() {
}
public Student(String name) {
this.name = name;
}
public Student(String name, String mobile) {
this.name = name;
this.mobile = mobile;
}
public void study(String subject) throws Exception {
System.out.println("学习......"+subject);
}
public void read() {
System.out.println("读书......");
}
@Override
public String toString() {
return "Student [name=" + name + ", mobile=" + mobile + ", a=" + a + ", b=" + b + ", c=" + c + ", d=" + d + "]";
}
}
package com.zzu.reflect;
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) throws Exception {
Class clazz = Student.class;
// 1. Constructor<?>[] getConstructors()
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("——————————");
// 2. Constructor getConstrutor(Class<?>... parameterTypes)
Constructor constructor = clazz.getConstructor(String.class);
System.out.println(constructor);
System.out.println("——————————");
// 3. Constructor<?>[] getDeclaredConstructors()
Constructor[] constructors2 = clazz.getDeclaredConstructors();
for (Constructor constructor2 : constructors2) {
System.out.println(constructors2);
}
System.out.println("——————————");
// 4. Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
Constructor constructor1 = clazz.getDeclaredConstructor(String.class,String.class);
System.out.println(constructor1);
}
}
运行结果如下图:
2、查看构造方法信息
通过Constructor类中某些方法可以获取某个构造方法的信息,这些方法如下:
- Class<T> getDeclaringClass():返回声明Constructor对象对应构造方法的类的Class对象。
- int getModifiers():以整数形式返回Constructor对象表示的构造方法的修饰符。
- String getName() :以字符串形式返回Constructor对象所表示的构造方法的名称。
- Class<?>[] getParameterTypes():返回由Constructor对象所表示的构造方法的形参类型对应Class对象组成的数组 。如果构造方法没有参数,则数组长度为0。
示例代码如下:
package com.zzu.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class Test {
public static void main(String[] args) throws Exception {
Class clazz = Student.class;
Constructor constructor = clazz.getConstructor(String.class);
// 1. Class\<T> getDeclaringClass()
Class class1 = constructor.getDeclaringClass();
System.out.println(class1);
System.out.println("——————————");
// 2. int getModifiers()
int i = constructor.getModifiers();
String string = Modifier.toString(i);
System.out.println(string);
System.out.println("——————————");
// 3. String getName()
String name = constructor.getName();
System.out.println(name);
System.out.println("——————————");
// 4. Class<?>[] getParameterTypes()
Class[] parameterTypes = constructor.getParameterTypes();
for (Class class2 : parameterTypes) {
System.out.println(class2);
}
}
}
运行结果如下图:
3、操作构造方法
通过Constructor类中某些方法可以创建对象,这些方法如下:
- void setAccessible(boolean flag):调用构造方法时是否忽略访问权限的影响,true表示忽略,false表示不忽略。
- T newInstance(Object… initargs):使用此Constructor对象表示的构造方法来创建声明该构造方法类的新对象。initargs为传入该构造方法中的参数,如果该构造方法没有参数,则可设定为null或一个长度为0的数组。
示例代码如下:
package com.zzu.reflect;
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) throws Exception {
Class clazz = Student.class;
Constructor constructor = clazz.getConstructor(String.class);
Object object = constructor.newInstance("帅帅");
System.out.println(object);
}
}
运行结果如下图:
四、成员方法
1、获取成员方法
借助Class类中某些方法可以获取对应类中声明的成员方法实例对象,这些方法有:
- Method[] getMethods():返回该Class对象表示类或接口中所有public方法(含继承的)对应的Method对象数组。
- Method getMethod(String methodName, Class<?>… parameterTypes):返回与该Class对象表示类或接口中方法名和方法形参类型相匹配的public方法(含继承的)的Method对象。
- Method[] getDeclaredMethods():返回该Class对象表示类或接口内声明定义的所有访问权限的方法(不含继承的)对应的Method对象数组。
- Method getDeclaredMethod(String methodName,Class<?>… parameterTypes) :返回与该Class对象表示类或接口中方法名和方法形参类型相匹配方法(不含继承的)对应的Method对象。
示例代码如下:
package com.zzu.reflect;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
Class clazz = Student.class;
// 1. Method[] getMethods()
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("——————————");
// 2. Method getMethod(String methodName, Class<?>... parameterTypes)
Method method = clazz.getMethod("study", String.class);
System.out.println(method);
System.out.println("——————————");
// 3. Method[] getDeclaredMethods()
Method[] methods2 = clazz.getDeclaredMethods();
for (Method method2 : methods2) {
System.out.println(method2);
}
System.out.println("——————————");
// 4. Method getDeclaredMethod(String methodName,Class<?>... parameterTypes)
Method method2 = clazz.getDeclaredMethod("study", String.class);
System.out.println(method2);
}
}
运行结果如下图:
2、查看成员方法信息
通过Method类中某些方法可以获取某个成员方法的信息,这些方法如下:
- Class<?> getDeclaringClass():返回声明Method对象表示方法的类或接口的 Class 对象。
- int getModifiers():以整数形式返回此Method对象所表示方法的修饰符。应该使用Modifier类中的toString方法对所返回的整数进行解码。
- Class<?> getReturnType():返回Method对象所表示的方法的返回值类型所对应的Class对象。
- String getName():返回方法名。
- Class<?>[] getParameterTypes():返回由Method对象代表方法的形参类型对应Class对象组成的数组。如果方法没有参数,则数组长度为 0。
- Class<?>[] getExceptionTypes():返回由Method对象表示方法抛出异常类型对应Class对象组成的数组。如果此方法没有在其 throws子句中声明异常,则返回长度为 0 的数组。
示例代码如下:
package com.zzu.reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Test {
public static void main(String[] args) throws Exception {
Class clazz = Student.class;
Method method = clazz.getMethod("study",String.class);
// 1. Class<?> getDeclaringClass()
Class class1 = method.getDeclaringClass();
System.out.println(class1);
System.out.println("——————————");
// 2. int getModifiers()
int i = method.getModifiers();
String string = Modifier.toString(i);
System.out.println(string);
System.out.println("——————————");
// 3. Class<?> getReturnType()
Class returnType = method.getReturnType();
System.out.println(returnType);
System.out.println("——————————");
// 4. String getName()
String name = method.getName();
System.out.println(name);
System.out.println("——————————");
// 5. Class<?>[] getParameterTypes()
Class [] types = method.getParameterTypes();
for (Class class2 : types) {
System.out.println(class2);
}
System.out.println("——————————");
// 6. Class<?>[] getExceptionTypes()
Class [] types2 = method.getExceptionTypes();
for (Class class2 : types2) {
System.out.println(class2);
}
}
}
运行结果如下图:
3、操作成员方法
通过Method类中某些方法可以调用成员方法,这些方法如下:
- void setAccessible(boolean flag):调用方法时是否忽略访问权限的影响,true表示忽略,false表示不忽略。
- Object invoke(Object obj, Object… args):调用Method对象指代的方法并返回Object类型结果。obj表示该方法所在类实例,如果方法时静态的则obj可以指定为null; args表示传入该方法的参数,如果方法没有参数,则args数组长度可以为0或null 。
示例代码如下:
package com.zzu.reflect;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
Class clazz = Student.class;
Student student = new Student();
Method method = clazz.getMethod("study",String.class);
method.invoke(student, "Math");
}
}
运行结果如下图:
五、成员变量
1、获取成员变量
通过Class类中某些方法可以获取对应类中声明的成员变量实例对象,这些方法有:
- Field[] getFields():返回该Class对象表示类或接口中所有public属性(含继承的)对应的Field对象数组。
- Field getField(String fieldName):返回该Class对象表示类或接口中与指定属性名(含继承的)相同的public 属性对应的Field对象。
- Field[] getDeclaredFields():返回该Class对象表示类或接口内定义的所有属性(不含继承的)对应的Field对象数组。
- Field getDeclaredField(String fieldName) :返回与该Class对象表示类或接口内定义的属性名(不含继承的)相匹配的属性相对应的Field对象。
示例代码如下:
package com.zzu.reflect;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception {
Class clazz = Student.class;
// 1. Field[] getFields()
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("——————————");
// 2. Field getField(String fieldName)
Field field = clazz.getField("a");
System.out.println(field);
System.out.println("——————————");
// 3. Field[] getDeclaredFields()
Field[] fields2 = clazz.getDeclaredFields();
for (Field field2 : fields2) {
System.out.println(field2);
}
System.out.println("——————————");
// 4. Field getDeclaredField(String fieldName)
Field field2 = clazz.getDeclaredField("d");
System.out.println(field2);
}
}
运行结果如下图:
2、查看成员变量信息
通过Field类中某些方法可以获取某个成员变量的信息,这些方法如下:
- Class<?> getDeclaringClass():返回声明Field对象表示字段的类或接口所对应的Class对象。
- int getModifiers():以整数形式返回Field对象表示的字段的修饰符。
- Class<?> getType():返回Field对象所表示字段的数据类型所对应的Class对象(推荐)。
- Type getGenericType():返回此Field对象所表示字段的声明类型。
- String getName():返回Field对象表示字段的名称。
示例代码如下:
package com.zzu.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
public class Test {
public static void main(String[] args) throws Exception {
Class clazz = Student.class;
Field field = clazz.getDeclaredField("d");
// 1. Class<?> getDeclaringClass()
Class class1 = field.getDeclaringClass();
System.out.println(class1);
System.out.println("——————————");
// 2. int getModifiers()
int i = field.getModifiers();
String string = Modifier.toString(i);
System.out.println(string);
System.out.println("——————————");
// 3. Class<?> getType()
Class type = field.getType();
System.out.println(type);
System.out.println("——————————");
// 4. Type getGenericType()
Type type2 = field.getGenericType();
System.out.println(type2);
System.out.println("——————————");
// 5. String getName()
String name = field.getName();
System.out.println(name);
}
}
运行结果如下图:
3、操作成员变量
通过Field类中某些方法获取及设置成员变量的值,这些方法如下:
- void setAccessible(boolean flag):设置或获取属性值时是否忽略访问权限的影响,true表示忽略,false表示不忽略。
- Object get(Object obj):返回Field表示字段的Object类型的值。obj为该属性所在类创建的对象,如果该属性是静态的,则可设置为null。
- void set(Object obj, Object value):为Field对象表示属性设置新值。obj为该属性所在类创建的对象,如果该属性为静态的则设置为null;value为该属性新值。
示例代码如下:
package com.zzu.reflect;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception {
Class<Student> clazz = Student.class;
Student student = (Student) clazz.newInstance();
Field field = clazz.getDeclaredField("d");
field.setAccessible(true);
field.set(student, "Tom");
Object object = field.get(student);
System.out.println(object);
}
}
运行结果如下图: