Java之反射机制

目录

1:反射是什么

2:反射的作用是什么

2.1:动态地获取和使用类的信息

2.2:动态地创建和使用类的实例对象

2.3:动态地调用和修改类的方法和字段

2.4:实现更加灵活的框架和工具

3:如何使用反射?

3.1:如何获取类类?

3.2:反射构造方法的调用(反射实例化)

3.3:反射动态方法调用

3.4:反射读取属性


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)
		 * }
		 * 
		 * 
		 * 
		 * 
		 */
	}
	
}

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值