在很多情况下,我们需要在运行时对Java类进行分析或操作。Java反射机制提供了这种能力,使得我们可以在运行时动态地访问和操作类、方法和属性。本文将详细介绍Java反射的基本概念和用法,并提供实际的示例代码。
1. 反射概述
反射(Reflection)是Java中一种强大的机制,允许我们在运行时检查和操作类、接口、字段和方法。借助反射,我们可以动态地创建对象、调用方法,以及读取和修改属性值。
2. 获取Class对象
要使用Java反射,首先需要获取表示类的Class对象。有三种主要方法可以获取Class对象:
使用Class.forName(String className)
方法,传入类的全限定名(包括包名)。
调用一个对象的.getClass()
方法。
对于基本类型和void,使用相应的.class
属性。
示例代码:
package cn.bdqn.myreflect.code;
import cn.bdqn.myreflect.entity.Student;
import java.lang.reflect.Constructor;
public class MyReflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
/**
* 反射获取对象的三种方式
* 1. class.forName("全类名");
* 2.类名.class
* 3.对象.getclass();
*
*/
//1.class.forName("全类名"); 全类名为:包名+类名
//这是最为常用的
Class<?> clazz = Class.forName("cn.bdqn.myreflect.entity.Student");
//2.类名.class
//当做参数进行传递时使用
Class<Student> clazz2 = Student.class;
//3.对象.getclass();
//当我们已经有了这个类的对象时才可以使用
Student st = new Student("老大",18);
Class<? extends Student> clazz3 = st.getClass();
}
}
3. 创建对象
通过Class对象,我们可以使用newInstance()方法创建一个类的实例。
示例代码:
package cn.bdqn.myreflect.construct;
import cn.bdqn.myreflect.entity.Student;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
public class demo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> aClass = Class.forName("cn.bdqn.myreflect.entity.Student");
//第一种getConstructor(),只返回访问权限包或公共的单个构造方法
//可以使用Constructor<?> constructor = aClass.getConstructor(数据类型.class)获取指定的构造方法;
Constructor<?> constructor = aClass.getConstructor(String.class,int.class);
//第二种getDeclaredConstructor(),返回单个构造方法对象,私有的构造方法对象也可返回
//可以使用Constructor<?> constructor = aClass.getDeclaredConstructor(数据类型.class)获取指定的构造方法;
Constructor<?> constructor1 = aClass.getDeclaredConstructor();
//第三种getConstructors(),只返回访问权限private外的多个构造方法的数组
Constructor<?>[] constructors = aClass.getConstructors();
//第四种getDeclaredConstructors(),返回所有构造方法对象的数组,私有的构造方法对象也可返回
Constructor<?>[] constructors1 = aClass.getDeclaredConstructors();
System.out.println("第一种getConstructor(),只返回访问权限包或公共的单个构造方法");
System.out.println(constructor+"\n");
System.out.println("第二种getDeclaredConstructor(),返回单个构造方法对象,私有的构造方法对象也可返回");
System.out.println(constructor1+"\n");
System.out.println("第三种getConstructors(),只返回访问权限private外的多个构造方法的数组");
for (Constructor<?> constructor2 : constructors) {
System.out.println(constructor2);
}
System.out.println("第四种返回所有构造方法对象的数组,私有的构造方法对象也可返回");
//使用增强for遍历出constructors1[]数组中得到的构造方法
for (Constructor<?> constructor2 : constructors1) {
System.out.println(constructor2);
}
//获取构造方法中的所有参数
// Parameter[] parameters = constructor.getParameters();
// for (Parameter parameter : parameters) {
// System.out.println(parameter);
// }
//利用class字节码文件的对象创建对象
constructor.setAccessible(true); //临时取消权限的校验,使private修饰的构造方法也能被getConstructor调用
Student st1 = (Student) constructor.newInstance("张三", 15);
System.out.println(st1);
}
}
4. 操作方法和属性
反射允许我们在运行时访问和操作类的方法和属性。以下是操作方法和属性的示例代码:
package cn.bdqn.myreflect.field;
import cn.bdqn.myreflect.entity.Student;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class demo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//创建Class字节码文件
Class<?> clazz = Class.forName("cn.bdqn.myreflect.entity.Student");
//获取所有的成员变量
//getDeclaredField可以获取私有的,而getField不能
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
//获取单个的成员变量
Field fields1 = clazz.getDeclaredField("name");
System.out.println(fields1);
//获取到权限修饰符,返回值为int型,1代表公共,2代表私有
int modifiers = fields1.getModifiers();
System.out.println(modifiers);
//获取成员变量的名字
String name = fields1.getName();
System.out.println(name);
//获取数据类型
Class<?> type = fields1.getType();
System.out.println(type);
//获取成员变量记录的值
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, int.class);
Student stu = (Student) constructor.newInstance("张三", 18);
System.out.println(fields1.get(stu));
//修改成员变量的值
fields1.set(stu,"李四");
System.out.println(stu);
}
}
package cn.bdqn.myreflect.method;
import java.lang.reflect.Method;
public class demo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//创建Class字节码文件
Class<?> clazz = Class.forName("cn.bdqn.myreflect.entity.Student");
//获取所有除private以外的方法(包含父类中所有的公共方法)
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//获取所有除private以外的方法(只能获取到本类中的公有方法而获取不到父类中的公有方法)
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
//获取单个除private以外的方法clazz.getMethod("方法名","形参");
Method eat = clazz.getMethod("eat");
System.out.println(eat);
}
}
注意:反射可能会破坏封装性,务必谨慎使用。
————————————————
原文链接:https://blog.csdn.net/weixin_43854959/article/details/131713425