1.概述
1.1 什么是反射
反射是一种机制/功能,利用该机制/功能可以在程序运行过程中对类进行解剖并操作类中的构造方法,成员方法,成员属性。
反射乃框架之灵魂
反射就是把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对象所表示的类的一个新实例。
//字节码对象里面常见的方法
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);// 根据构造方法创建对象
//反射构造方法
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);暴力反射,设置为可以直接访问私有类型的属性
// 反射字段
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(student.getName());
}
6.方法的反射
6.1概述
Method是方法类,类中的每一个方法都是Method的对象,通过Method对象可以调用方法。
6.2Class类中与Method相关方法
1. Method[] getMethods()
获取所有的public修饰的成员方法,包括父类中
2. Method[] getDeclaredMethods()
获取当前类中所有的方法,包含私有的,不包括父类中
3. Method getMethod("方法名", 方法的参数类型... 类型)
根据方法名和参数类型获得一个方法对象,只能是获取public修饰的
4. Method getDeclaredMethod("方法名", 方法的参数类型... 类型)
根据方法名和参数类型获得一个方法对象,包括private修饰的
6.3Method类中常用方法
1. Object invoke(Object obj, Object... args)
根据参数args调用对象obj的该成员方法
如果obj=null,则表示该方法是静态方法
2. void setAccessible(true)
暴力反射,设置为可以直接调用私有修饰的成员方法
@Test
// 反射方法
public void fun() throws Exception {
//1. 获得字节码
Class clazz = Class.forName("com.itheima.bean.Student");
//2. 获得公共的方法(包含父类的)
Method[] methods = clazz.getMethods();
for (Method method : methods) {
//System.out.println("方法名="+method.getName());
}
//3. 获得所有的方法(包含私有的,但是不包含父类的)
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method method : declaredMethods) {
//System.out.println("方法名="+method.getName());
}
//4. 反射某一个特点的方法
//eg:public void speak()
Method method = clazz.getMethod("speak");
//method.invoke(clazz.newInstance());
//eg: private void speak(String name)
Method declaredMethod = clazz.getDeclaredMethod("speak", String.class);
declaredMethod.setAccessible(true);//暴力破解
declaredMethod.invoke(clazz.newInstance(),"李四");
}
反射main方法
@Test
public void fun() throws Exception{
Class clazz = Class.forName("com.demo4.Student");
Method method = clazz.getDeclaredMethod("main", String[].class);
//method.setAccessible(true);
method.invoke(null, (Object)new String[]{"aaa","bbb","ccc"});
}