目录
什么是反射?
java反射通俗来讲就是解剖类,并允许以编程的方式解剖类中的各个成分(构造器,成员变量,方法)。
反射我们要学习什么?
获取类的信息,并操作他们
第一步:加载类,获取类的字节码:Class对象
第二步:获取类的构造器:Constructor对象
第三步:获取类的成员变量:Field对象
第四步:获取类的成员方法:Method对象
获取class对象的三种方式
- 类名.class
- 调用class提供方法:public static class forName(String package); //package为全类名
- Object提供的方法:public Class getClass(); Class c = 对象.getClass();
public static void main(String[] args) throws Exception {
Student stu = new Student();
//第一种方式,类名.的方式
Class<Student> studentClass = Student.class;
//通过类对象,获得类名
String simpleName = studentClass.getSimpleName();
//通过类对象,获取全类名
String name = studentClass.getName();
//第二种方式,调用Class提供的方法
Class studentClass2 = Class.forName("com.example.com.yunlong.test4.Student");
//第三种方式,Object提供的方法:public Class getClass();
Class studentClass3 = stu.getClass();
}
获取构造器
第一步:获取class对象
第二步:通过 Class 对象,我们可以获取构造器信息。
getConstructors():
获取全部的公共构造器。getDeclaredConstructors():
获取全部的构造器,包括私有的。getConstructor(Class<?>... parameterTypes)
:获取指定参数类型的公共构造器。getDeclaredConstructor(Class<?>... parameterTypes)
:获取指定参数类型的所有构造器,包括私有构造器。
获取成员变量
第一步:获取class对象
第二步:通过 Class 对象,我们可以获取成员变量信息。
getField
s():
获取全部的公共字段。getDeclaredFields():
获取全部的字段,包括私有的。getField(String name)
:获取指定名称的公共字段。getDeclaredField(String name)
:获取指定名称的所有字段,包括私有字段。
import java.lang.reflect.Field;
class MyClass {
public String publicField;
private int privateField;
public MyClass(String publicField, int privateField) {
this.publicField = publicField;
this.privateField = privateField;
}
}
public class Main {
public static void main(String[] args) throws Exception {
// 创建 MyClass 类的实例
MyClass obj = new MyClass("publicValue", 123);
// 获取 MyClass 类的 Class 对象
Class<?> clazz = MyClass.class;
// 获取指定名称的公共字段
Field publicField = clazz.getField("publicField");
// 获取指定名称的所有字段,包括私有字段
Field privateField = clazz.getDeclaredField("privateField");
// 设置字段的可访问性,以便访问私有字段
privateField.setAccessible(true);
// 获取字段的值
Object publicValue = publicField.get(obj);
Object privateValue = privateField.get(obj);
// 输出字段的值
System.out.println("Public Field Value: " + publicValue);
System.out.println("Private Field Value: " + privateValue);
}
}
获取类方法
第一步:获取class对象
第二步:通过 Class 对象,我们可以获取类中方法信息。
getMethods()
:获取类的全部公共方法。getDeclaredMethods()
:获取类的全部方法,包括私有。
getMethod(String name, Class<?>... parameterTypes)
:获取指定名称和参数类型的公共方法。getDeclaredMethod(String name, Class<?>... parameterTypes)
:获取指定名称和参数类型的所有方法,包括私有方法。
import java.lang.reflect.Method;
class MyClass {
public void publicMethod(String param1, int param2) {
System.out.println("Public Method: " + param1 + ", " + param2);
}
private void privateMethod() {
System.out.println("Private Method");
}
}
public class Main {
public static void main(String[] args) throws Exception {
// 创建 MyClass 类的实例
MyClass obj = new MyClass();
// 获取 MyClass 类的 Class 对象
Class<?> clazz = MyClass.class;
// 获取指定名称和参数类型的公共方法
Method publicMethod = clazz.getMethod("publicMethod", String.class, int.class);
// 获取指定名称和参数类型的所有方法,包括私有方法
Method privateMethod = clazz.getDeclaredMethod("privateMethod");
// 设置私有方法可访问
privateMethod.setAccessible(true);
// 调用公共方法
publicMethod.invoke(obj, "param1", 123);
// 调用私有方法
privateMethod.invoke(obj);
}
}
反射的作用:
基本作用:可以得到一个类的全部成分然后操作。
可以破坏封装性:因为它可以访问和操作类的私有成员,而不受java语言访问修饰符的限制
最重要的用途:适合做java的框架,基本上,主流的框架都会基于反射设计出一些通用的功能。
反射的应用:
Java 反射广泛应用于以下几个领域:
- 框架开发:许多框架使用反射来实现自动配置和扩展点的加载,比如 Spring 框架。
- 动态代理:通过反射可以动态地创建代理对象,实现 AOP(面向切面编程)等功能。
- 工具类编写:比如 ORM(对象关系映射)框架需要通过反射获取实体类的信息。
- 调试和诊断工具:通过反射可以查看类的结构信息,帮助调试和诊断问题。
实例
使用反射做一个简易版的框架
需求:对于任意一个对象,该框架都可以把对象的字段名和对应的值,保存到文件中去。
public class MyFrame {
public static void saveObject(Object obj) throws Exception {
PrintStream ps = new PrintStream(new FileOutputStream("E:\\workspacelong\\Thred\\src\\data.txt",true));
//第一步,拿到class对象
Class<?> a = obj.getClass();
String simpleName = a.getSimpleName();//拿到类名
ps.println("------------"+simpleName+"-------------");
//第二步,拿到类中成员变量
Field[] declaredFields = a.getDeclaredFields();
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);
//第三步,拿到成员变量的名字
String name = declaredField.getName();
//第四步,拿到成员变量的值,转化为String
String value = declaredField.get(obj)+"";
ps.println(name+"="+value);
}
ps.close();
}
}
Java 反射的优缺点
尽管 Java 反射提供了强大的功能,但也存在一些优缺点:
优点:
- 提供了灵活性和动态性,使得编程更加灵活和易扩展。
- 可以在运行时获取类的信息,使得一些框架和工具的开发更加简便。
缺点:
- 性能开销较大,因为反射操作是在运行时进行的,而不是编译时。
- 降低了代码的可读性和可维护性,因为反射使得代码更加动态和难以理解。