一、反射是什么?
Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
二、反射的优缺点
1、优点:在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
2、缺点:
(1)反射会消耗一定的系统资源,因此如果不需要动态地创建一个对象,那么就不需要用反射;
(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。
三、反射的api
3.1、反射类
- Class类: 代表类的实体,在运行的Java应用程序中表示类和接口
- Field类: 代表类的成员变量(成员变量也称为类的属性)
- Method类: 代表类的方法
- Constructor 类: 代表类的构造方法
3.2、反射方法
- getField : 获取指定字段
- getMethod : 获取指定方法
- getCostructor :获取指定构造器
- getFields :获得类中的所有 public 字段(包括父类)
- getMethods :获得类中的所有 public 方法 (包括父类)
- getCostructors :获得类中的所有 public 构造器数 (包括父类)
- getDeclatedFields : 获得类中的所有字段 (包括 private 不包括父类)
- getDeclatedMethods : 获得类中的所有方法 (包括 private 不包括父类)
- getDeclaredConstructors : 获得类中的所有构造器 (包括 private 不包括父类)
- getName() : 获取方法名 / 字段名(作用于 Method / Field)
- getReturnType() : 获取方法返回值 (作用于 Method)
- getParameterTypes() : 获取传入参数 (作用于 Method)
- setAccessible(true) : 允许访问私有成员(设置在 Field 字段上)
四、反射的 3种创建反射
// 第一种方式(类的全路径):
Class c1 = Class.forName("Employee");
// 第二种方式(.calss):
// java中每个类型都有class 属性.
Class c2 = Employee.class;
// 第三种方式( 类.getCalss()):
// java语言中任何一个java对象都有getClass 方法 ,c3是运行时类 (e的运行时类是Employee)
Employee e = new Employee();
Class<?> c3 = e.getClass();
五、使用示例
5.1、反射给实体类赋值
Class<?> forName = Class.forName("class_demo.User");
// 创建此Class 对象所表示的类的一个新实例 调用了User的.
Object newInstance = forName.newInstance();
User user1 = (User) newInstance;
user1.setUsername("阿英");
user1.setAge(1);
System.out.println(user1.toString()+"----反射--无参数构造创建user实列");
5.2、反射调用有参构造方法
Class<?> forName2 = Class.forName("class_demo.User");
// 调用了User的有参数构造方法. 参数对应有参构造器的参数的数据类型.class ,必须按顺序
Constructor<?> constructor2 = forName2.getConstructor(String.class, Integer.class);
Object newInstance2 = constructor2.newInstance("阿瑶",1);
User user2 = (User) newInstance2;
System.out.println(user2.toString()+"----反射--有参数构造创建user实列");
5.3、反射给私有属性赋值
// 获取当前类class地址
Class<?> forName3 = Class.forName("class_demo.User");
// 使用反射实例化对象 无参数构造函数
Object newInstance3 = forName3.newInstance();
// 获取当前类的 username,age字段
Field username = forName3.getDeclaredField("username");
Field age = forName3.getDeclaredField("age");
// 允许操作私有成员
username.setAccessible(true);
age.setAccessible(true);
// 设置值
username.set(newInstance3, "ws_兮");
age.set(newInstance3, 19);
User user3 = (User) newInstance3;
System.out.println(user3.toString()+"----反射给私有属性赋值");
5.4、反射获取该类的所有方法
// 获取当前类class地址
Class<?> forName4 = Class.forName("class_demo.User");
//本类所有方法
Method[] declaredMethods = forName4.getDeclaredMethods();
//遍历
for(Method de : declaredMethods) {
//打印方法名及返回值类型
System.out.println(de.getName()+"--"+de.getReturnType());
}
5.5、反射获取该类的所有属性
Class<?> forName6 = Class.forName("class_demo.User");
Field[] declaredFields = forName6.getDeclaredFields();
for(Field de : declaredFields) {
System.out.println(de.getName());
}