一、反射
反射是加载类的时候,使用编程方式解剖出类中的各种成分,包括成员变量、方法、构造器等。
一般在框架中使用的较多。
1. 使用
1.1 获取类
// 方法1
Class clazz1 = Student.class;
// 方法2
Class clazz2 = Class.forName("com.package.xx.Student");
// 方法3
Class clazz3 = student.getClass();
1.2 获取构造器
Class clazz = Student.class;
// 方法1: 获取所有public构造器
Constructor[] constructors1 = clazz.getConstructors();
// 方法2: 获取所有构造器,只要存在都可以获取到
Constructor[] constructors2 = clazz.getDeclaredConstructors();
// 方法3: 获取某个public构造器
// 表明获取student类中入参为一个字符串的构造器
Constructor constructor3 = clazz.getConstructor(String.class);
// 方法4: 获取某个构造器,只要存在就可以获取到
// 表明获取student类中入参为一个字符串的构造器
Constructor constructor4 = clazz.getDeclaredConstructor(String.class);
获取构造器之后会初始化对象。
Class clazz = Student.class;
Constructor constructor = clazz.getDeclaredConstructor();
// 注意:如不禁止检查访问控制,则无法调用private的构造器
constructor.setAccessible(true);
// 注意:newInstance返回的是Object对象,需要进行类型转换
Student student = (Student) constructor.newInstance(Object ...initargs);
1.3 获取成员变量
Class clazz = Student.class;
// 方法1: 获取所有public成员变量
Field[] fields1 = clazz.getFields();
// 方法2: 获取所有成员变量,只要存在都可以获取到
Field[] fields2 = clazz.getDeclaredFields();
// 方法3: 获取某个public成员变量
// 表明获取student类中名为xxx的变量
Field field3 = clazz.getField("xxx");
// 方法4: 获取某个成员变量,只要存在就可以获取到
// 表明获取student类中名为xxx的变量
Field field4 = clazz.getDeclaredField("xxx");
1.4. 获取成员方法
Class clazz = Student.class;
// 方法1: 获取所有public成员方法
Method[] methods1 = clazz.getMethods();
// 方法2: 获取所有成员方法,只要存在都可以获取到
Method[] methods2 = clazz.getDeclaredMethods();
// 方法3: 获取某个public成员方法
// 表明获取student类中入参为一个字符串的方法
Method method3 = clazz.getMethod(String.class);
// 方法4: 获取某个成员方法,只要存在就可以获取到
// 表明获取student类中入参为一个字符串的方法
Method method4 = clazz.getDeclaredMethod(String.class);
二、注解
注解一般搭配反射在框架中使用。注解作为Java代码中的特殊标记,对类、成员变量、方法、入参等进行标注,在其他代码片段中根据注解信息来进行对应的逻辑处理。
1. 写法
// 元注解:修饰注解的注解
// @Target声明被修饰的注解在哪些位置可以使用
@Target(ElementType.Method)
// @Retention声明被修饰的注解的保留周期
@Retention(RetentionPolicy.RUNTIME)
public @interface myAnnotaion {
public String name() default "defaultName";
}
2. 相关问题
编译器注解和运行时注解
- 常见的编译器注解
- @Override、@Deprecated、@SupressWarnings
- 常见的运行时注解
- 框架内的大部分是运行时注解,@Autowire @Resoure @Bean等。
- 区别
- 保留阶段不同
- 编译时注解在编译期间生效,运行时无法访问;
- 运行时注解在运行时生效。
- 原理不同
- 编译时注解用注解处理器在编译期处理;
- 运行时注解用反射机制处理。
- 效率不同
- 编译时注解对性能无影响;
- 运行时注解由于使用反射,性能会差一些。
- 场景不同
- 编译时注解一般用于语法检查和错误报告;
- 运行时注解通常用于动态的逻辑处理。
- 生成的class文件不同
- 编译时注解的信息会记录到class文件中;
- 运行时注解的信息不会记录到class文件中。
- 保留阶段不同
@Resource和@Autowired的区别
- 来源不同
- @Resource是Java的注解;
- @Autowired是Spring的注解。
- 查找顺序不同
- @Resource是先根据名称查找(byName),如果找不到再根据类型查找(byType);
- @Autowired是先根据类型查找(byType),存在多个Bean再根据名称查找(byName)。
- 参数不同
- @Resource中支持7个参数,包括name、type等;
- @Autowired中只支持required这1个参数。
- 注入方法不同
- 常见注入方法有属性注入、构造器注入和Setter注入。
- @Resource不支持构造器注入;
- @Autowired均支持。