目录
1:反射是什么
反射机制是Java语言中的一种高级特性,它可以在程序运行时动态获取类的信息、实例化对象、调用方法、访问和修改属性等。与之相对的是静态编译时期的程序设计方式,也是Java最初的设计方式
2:反射的作用是什么
1. 依赖注入框架
依赖注入(DI)框架可以通过反射机制来创建实例对象,并通过注解或XML配置来设置对象的属性和方法。例如Spring框架中的@Autowired注解就是通过反射机制来实现依赖注入。
2. ORM框架
对象关系映射(ORM)框架可以通过反射机制来将数据库中的表映射成Java类,并进行相关的增删改查操作。例如Hibernate框架就是使用反射机制来将数据库表映射为Java对象。
3. 实现动态代理
动态代理技术可以通过反射机制动态生成代理对象,并进行相关的操作。例如在AOP编程中,就可以通过动态代理技术实现统一的日志、事务等操作。
4. 实现自动化测试
通过反射机制,可以在运行时获取类的信息和方法信息,从而实现自动化测试的功能。例如JUnit框架就是通过反射机制来获取测试类和测试方法的信息,并进行测试操作。
5. 实现插件化
通过反射机制,可以实现插件化的功能。例如在Eclipse IDE中,就可以通过定义扩展点和插件来实现插件化的功能。
2.1:动态地获取和使用类的信息
反射机制可以在程序运行时动态地获取类的信息,例如类的名称、字段、方法、注解等信息,从而进行一些动态操作,例如在JUnit中实现自动化测试时,通过反射获取类的所有测试方法,然后自动进行测试。
2.2:动态地创建和使用类的实例对象
通过反射机制,我们可以动态地在程序运行时创建类的实例对象,这种方式使得代码更加灵活,可以根据业务需求动态地创建对象。例如在Spring框架中,就通过反射机制实现了依赖注入,并动态创建Bean实例。
2.3:动态地调用和修改类的方法和字段
反射机制也可以处理类的方法和字段,通过反射机制,我们可以动态地调用和修改类的方法和字段,这种方式使得代码更加灵活和扩展性更强。例如在使用AOP技术时,就可以通过反射机制动态地调用目标方法,并实现一些统一的处理。
2.4:实现更加灵活的框架和工具
反射机制可以为框架和工具提供更加灵活、可扩展和易用的接口,从而实现更加高效和智能的应用程序。例如在ORM框架中,通过反射机制可以将数据库中的表映射成Java类,从而实现快速地对表进行操作。
反射机制可以为Java应用程序提供更加灵活、高效和智能的开发方式,通过反射机制,我们可以在程序运行时动态地调用和使用类的信息、方法和字段,从而实现更加高效和智能的应用程序
3:如何使用反射?
在学习怎么使用反射机制之前,我们需要知道Java反射机制的核心是类类类
- 在Java的反射机制中,"类类"通常指Class类。Class类是Java中用来表示一个类的类
- 在Java程序运行时,每个类都会对于一个Class对象,Class对象包含了该类的各种元信息,例如类的名称、字段、方法等
- 借助Class对象,Java程序可以在运行时动态地创建类的实例、调用类的方法等操作,这就是反射机制的基本功能之一
- Class类中定义了很多方法,包括获取类的基本信息、实例化对象、获取字段和方法、修改字段和调用方法等,是Java反射机制的重要组成部分
3.1:如何获取类类?
//使用类的全路径名字
Class class1 = Class.forName("com.wenhao.Student");
//实例化一个对象。通过对象.getClass
Student s= new Student();
Class class2 = s.getClass();
// System.out.println(class2);//得到类的全路径名
//通过类名.class
Class class3= Student.class;
// System.out.println(class3);//得到类的全路径名字
3.2:反射构造方法的调用(反射实例化)
实体类以下面的Student类为例子
package com.wenhao;
public class Student {
private String sid;
private String sname;
public Integer age;
static{
System.out.println("加载进jvm中!");
}
public Student() {
super();
System.out.println("调用无参构造方法创建了一个学生对象");
}
public Student(String sid) {
super();
this.sid = sid;
System.out.println("调用带一个参数的构造方法创建了一个学生对象");
}
public Student(String sid, String sname) {
super();
this.sid = sid;
this.sname = sname;
System.out.println("调用带二个参数的构造方法创建了一个学生对象");
}
@SuppressWarnings("unused")
private Student(Integer age) {
System.out.println("调用Student类私有的构造方法创建一个学生对象");
this.age = age;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public void hello() {
System.out.println("你好!我是" + this.sname);
}
public void hello(String name) {
System.out.println(name + "你好!我是" + this.sname);
}
@SuppressWarnings("unused")
private Integer add(Integer a, Integer b) {
return new Integer(a.intValue() + b.intValue());
}
}
现在我们开始操作
package com.wenhao;
import java.lang.reflect.Constructor;
/**
* 一切的反射操作都从获取类开始
* @author liwen
*
*/
public class demo1 {
//三种方式获取类类
public static void main(String[] args) throws Exception {
//使用类的全路径名字
// Class class1 = Class.forName("com.wenhao.Student");
//实例化一个对象。通过对象.getClass
// Student s= new Student();
// Class class2 = s.getClass();
// System.out.println(class2);//得到类的全路径名
//通过类名.class
// Class class3= Student.class;
// System.out.println(class3);//得到类的全路径名字
/**
* 反射实例化:
* 所有的实力类,添加了有参构造器,一定记得补一个无参的构造器
*
*/
//一切反射从类类开始
Class class1 = Class.forName("com.wenhao.Student");
//调用反射的方法
//调用无参构造器,反射实例化
Student fs1 = (Student) class1.newInstance();
//如果没有无参构造的方法的话,那么就不可以得到student的反射对象,会报错
System.out.println(fs1);//得到了Student的反射对象
//调用一个参数的有参构造器
//通过类类获取构造器对象,参数需要传一个参数的类别,可以看到我们的student中的一个参数的构造器,就是String类型,所以我们此时要拿到String类
Constructor c= class1.getConstructor(String.class);
//Constructor,就是有参构造器
//再通过这个构造器new一个反射器,拿到反射的构造方法,,通过构造器实例化反射器
Student fs2 =(Student) c.newInstance("s001");
System.out.println(fs2);//拿到了一个参数构造器里的反射反射方法
//调用两个构造器的实例化对象
Constructor c2= class1.getConstructor(String.class,String.class);
Student fs3 = (Student) c2.newInstance("s002","wenhao");
System.out.println(fs3);
//调用私有化的带一个参数的构造器实例化对象
// Constructor c3= class1.getConstructor(Integer.class);
// Student fs4 = (Student) c3.newInstance(1);
// System.out.println(fs4);//此时一定报错,因为getConstructor拿不到这个私有的方法
Constructor c4= class1.getDeclaredConstructor(Integer.class);
//因为是私有的,所以不能实例化
///打开私有修饰符的访问权限
c4.setAccessible(true);
Student fs5 = (Student) c4.newInstance(1);
System.out.println(fs5);//Exception in thread "main" java.lang.IllegalAccessException: Class com.wenhao.demo1 can not access a member of class com.wenhao.Student with modifiers "private"
//构造方法是方法吗,是,反射实例化了,是不是就可以调用其中的构造方法了,可以
}
}
3.3:反射动态方法调用
package com.wenhao;
import java.lang.reflect.Method;
/**
* 反射的动态方法调用
* @author liwen
*
*/
public class demo2 {
public static void main(String[] args) throws Exception {
//一切反射从类类开始
Class class1= Student.class;
//通过类类反射实例化
Student s1 = (Student) class1.newInstance();
//反射调用无参的方法,先获取到方法对象
//name:方法名,参数,调用这个方法要传的参数类型
Method m1= class1.getMethod("hello");
//类实例化,中间放参数值,返回的是方法的返回值
Object invoke = m1.invoke(s1);
System.out.println(invoke);
//获取到一个参数的方法对象,,方法名,参数类型
Method m2= class1.getMethod("hello", String.class);
//将反射实例化对象放进去,并且传参数
Object invoke2 = m2.invoke(s1, "wenhao");
System.out.println(invoke2);
//获取到私有化的一个参数的方法对象
Method m3= class1.getDeclaredMethod("add", Integer.class,Integer.class);
//同样打开访问权限
m3.setAccessible(true);
Object invoke3 = m3.invoke(s1,1,1);
System.out.println(invoke3);
}
}
3.4:反射读取属性
package com.wenhao;
import java.lang.reflect.Field;
/**
* 反射读写属性
* @author liwen
*
*/
public class demo4 {
public static void main(String[] args) throws Exception{
//一切反射从类类开始
Class class1= Student.class;
// 实例化一个对象
Student s= new Student();
//通过反射获取到对象中的所有私有的属性对象
Field[] declaredFields = class1.getDeclaredFields();
for (Field field : declaredFields) {
//这里是拿到所有属性对象的属性名字
System.out.println(field.getName());
//因为是私有的,当我要操作的时候,所以我们需要打开权限
field.setAccessible(true);
//现在我们拿到属性对象中的属性名字加上属性值
System.out.println(field.getName()+":"+field.get(s));
}
//全部拿到了,从这里我们可以优化之前的增删改查了
/**
* req.getParameterMap:得到一个map集合
* Student s= new Student();
*遍历map集合,
* for(entry:map.entryset()){
* 根据key,也就是对象名字,得到整个属性对象
* field f =class1.getDeclaredField(key)
* 打开权限
* f.setAccessible(true)
* f.set(s,value)
* }
*
*
*
*
*/
}
}