学习目标
- 能够通过反射技术获取Class字节码对象
- 能够通过反射技术获取构造方法对象,并创建对象。
- 能够通过反射获取成员方法对象,并且调用方法。
- 能够通过反射获取属性对象,并且能够给对象的属性赋值和取值。
- 能够使用Beanutils常用方法操作JavaBean对象
- 能够说出常用的元注解及其作用
- 能够完成注解的MyTest案例
一,反射【重点】
1.概述
1.1什么是反射
反射是一种机制/功能,利用该机制/功能可以在程序运行过程中对类进行解剖并操作类中的构造方法,成员方法,成员属性。
反射乃框架之灵魂 JavaEE
反射就是把Java的各种成分(字段,方法)映射成相应的Java类.
1.2反射的应用场景
- 开发工具中写代码时的提示
开发工具之所能够把该对象的方法和属性展示出来就使用利用了反射机制对该对象所有类进行了解剖获取到了类中的所有方法和属性信息,这是反射在IDE中的一个使用场景。
- 各种框架的设计
以上三个图标上面的名字就是Java的三大框架,简称SSH。
这三大框架的内部实现也大量使用到了反射机制,所以要想学好这些框架,则必须要求对反射机制熟练了
2.获得Class的三种方法
- 对象.getClass()
- 使用Class类的forName(“类的全限定名”) 最常见的方式
- 使用“类.class”
//a. 获得字节码对象
public void fun01() throws Exception {
//1. 对象.getClass()
Student student = new Student();
Class clazz = student.getClass();
//2. Class.forName("类的全限定名");
Class clazz02 = Class.forName("com.itheima.bean.Student");
//3. 类.class(JDBCTemplate里面就用过)
Class clazz03 = Student.class;
}
3.获取Class对象的信息
- 获取简单类名
String getSimpleName(); 获取简单类名,只是类名,没有包
- 获取完整类名
String getName(); 获取完整类名,包含包名 + 类名
- 创建对象(依赖无参构造)
T newInstance() ; 创建此 Class对象所表示的类的一个新实例。
示例代码
//b. 字节码对象里面常见的方法
public void fun02() throws Exception {
//1. Class.forName("类的全限定名");
//Class clazz = Class.forName("com.itheima.bean.Student");
Class clazz = Student.class;
//2. 获得类名(简单类名) Student
System.out.println(clazz.getSimpleName());
//3. 获得完整的类名 com.itheima.bean.Student
System.out.println(clazz.getName());
//4. 通过字节码创建对象(要求: 依赖的是无参构造)-- new Student();
Student student = (Student) clazz.newInstance();
student.speak();
}
4.构造函数的反射
4.1概述
Constructor是构造方法类,类中的每一个构造方法都是Constructor的对象,通过Constructor对象可以实例化对象。
4.2 Class类中与Constructor相关方法
clazz.getDeclaredConstructors(); //获得所有的构造方法(包含私有的)
clazz.getConstructor(Class... paramType); //获得特定的构造方法
constructor.newInstance(Object...params);// 根据构造方法创建对象
示例代码
//c. 反射构造方法
public void fun03() throws Exception {
//1. Class.forName("类的全限定名");
Class clazz = Class.forName("com.itheima.bean.Student");
//2. 获得所有的构造方法(包含私有的)
Constructor[] constructors = clazz.getDeclaredConstructors();
System.out.println(constructors.length);
//3. 反射获得某一个特定的构造方法
//eg: public Student(String name, int age, String sex)
Constructor constructor = clazz.getConstructor(String.class, int.class, String.class);
Student student = (Student) constructor.newInstance("张三",18,"男");//根据构造方法创建一个对象
System.out.println(student.getAge());
}
5.属性的反射
5.1概述
Field是属性类,类中的每一个属性都是Field的对象,通过Field对象可以给对应的属性赋值和取值。
5.2 Class类中与Field相关方法
1. Field[] getFields()
获取所有的public修饰的属性对象,返回数组
2. Field[] getDeclaredFields()
获取所有的属性对象,包括private修饰的,返回数组
3. Field getField(String name)
根据属性名获得属性对象,只能获取public修饰的
4. Field getDeclaredField(String name)
根据属性名获得属性对象,包括private修饰的
5.3Field类中常用方法
set(obj,value);通用方法都是给对象obj的属性设置使用
get(obj); 通用方法是获取对象obj对应的属性值的
void setAccessible(true);暴力反射,设置为可以直接访问私有类型的属性
示例代码
//d. 反射字段
public void fun04() throws Exception {
Student student = new Student("张三", 18, "男");
//1. Class.forName("类的全限定名");
Class clazz = Class.forName("com.itheima.bean.Student");
//2. 获得所有的字段(包含私有的)
Field[] fields = clazz.getDeclaredFields();
//System.out.println(fields.length);
for (Field field : fields) {
//取值
//field.get()
//设置值
//field.set();
}
//3. 获得某一个特定的字段 String name;
Field nameFiled = clazz.getDeclaredField("name");
nameFiled.setAccessible(true);//暴力破解(可以访问私有的字段或者方法)
//取值
Object nameValue = nameFiled.get(student);
System.out.println(nameValue);
//赋值
nameFiled.set(student,"李四");
System.out.println