016-Java reflection反射详解

一、反射的概述

1.1、反射的介绍

  1. 反射机制允许程序在执行期借助于Reflection API 取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到。
  2. 加载完类之后,在堆中就产生了一个Class 类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个对象就像一面镜子,透过一个镜子看见类的结构,所以,形象的称之为:反射。
  3. Java反射机制原理示意图
    在这里插入图片描述
    在这里插入图片描述

1.2、反射机制作用

  1. 运行时动态获取类的信息:在编写代码时,对于类的信息是必须在编译时确定的,但在运行时,有时需要根据某些条件,动态获取某个类的信息,这时就可以使用Java中的反射机制。

  2. 动态生成对象:反射机制可以在运行时生成对象,这样就可以根据参数的不同,动态的创建不同的类的实例对象。

  3. 动态调用方法:通过反射机制可以调用类中的方法,不论这些方法是否是公共的,也不论这些方法的参数个数和类型是什么,反射机制都具有这样的能力。

  4. 动态修改属性:利用反射机制可以获取到类中的所有成员变量,并可以对其进行修改。

  5. 实现动态代理:利用反射机制可以实现代理模式,通过代理对象完成原对象对某些方法的调用,同时也可以在这些方法的调用前后做一些额外的处理。

1.3、反射机制优点

  1. 增加灵活性和扩展性:使用反射机制可以在程序运行时动态加载、修改、创建、调用类和方法等,从而增加了程序的灵活性和可扩展性。

  2. 提高代码的通用性:通过反射机制可以动态的获取类信息,从而可以编写通用的代码,使得不同的类能够以相同的方式来处理。

  3. 规范代码结构:反射机制可以使代码结构清晰明了,减少了代码中的冗余部分。

  4. 实现框架和插件:反射机制在很多框架和插件中都有广泛的应用,比如Spring框架、JUnit测试框架等。

  5. 动态代理:反射机制的另一个重要应用是实现动态代理,可以在不修改原来代码的情况下,通过代理对象对原对象的方法进行增强。

优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支撑。

缺点:使用反射基本是解释执行,对执行速度有影响。

二、反射机制重要相关的类

在这里插入图片描述

2.1、Class类

Class代表类的实体,在运行的Java应用程序中表示类和接口。在这个类中提供了很多有用的方法,这里对他们简单的分类介绍。

获得类相关的方法
在这里插入图片描述
获得类中属性相关的方法
在这里插入图片描述

获得类中构造器相关的方法

在这里插入图片描述

获得类中方法相关的方法
在这里插入图片描述

2.2、Class类-代码示例

Student实体为实例


/**
 * 学生实体
 */
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());
	}
}

获取Class的三种方式
1.Class.forname–应用在jdbc数据库连接中
2.类实例.getclass()—通用增删改
3.类名.class–通用查询

/**
 * 类类的获取方式
 * 一切反射的操作都是从类对象开始
 */
public class Demo1 {
	public static void main(String[] args) throws Exception {
		//1.Class.forname--应用在jdbc数据库连接中
		Class<?> forName = Class.forName("com.ctb.reflect.Student");
		System.out.println(forName);
		Student stu=new Student();
		//2.类实例.getclass()---通用增删改
		Class<? extends Student> class1 = stu.getClass();
		System.out.println(class1);
		//3.类名.class--通用查询
		 Class<Student> class2 = Student.class;
		System.out.println(class2);
	}
 
}

反射实例化
newInstance()方法内部实际上调用了无参数构造方法,必须保证无参构造存在才可以。
否则会抛出java.lang.InstantiationException异常。

 
/**
 * 反射实例化
 * 添加有参构造器,一定要补一个无参构造器
 */
public class Demo2 {
	
	public static void main(String[] args) throws Exception {
		//一切反射从类类开始
		Class<Student> c1=Student.class;
		Student stu=new Student();
		//调用无参构造器反射实例化
		Object o=c1.newInstance();
		System.out.println(o);
		//调用1个参数的构造器反射实例化
		Constructor<Student> ct = c1.getConstructor(String.class);
		Student student = ct.newInstance("5869");
		System.out.println(student);
		//调用2个参数的构造器反射实例化
		 Constructor<Student> ct1 = c1.getConstructor(String.class,String.class);
	        Student s2 = ct1.newInstance("66744", "小文子");
	        System.out.println(s2);
	        //getConstructor方法只能获取到公有的构造器对象
	        //调用私有化的构造器反射实例化
	        Constructor<Student> ct2 = c1.getDeclaredConstructor(Integer.class);
	        //打开私有修饰的访问权限
	        ct2.setAccessible(true);
	        Student ss = ct2.newInstance(89);
	        System.out.println(ss);
	}
 
}

2.3、Method类

在这里插入图片描述

2.4、Method类-代码示例

/**
 * 反射动态方法调用
 */
public class Demo3 {
	public static void main(String[] args) throws Exception {
		 Student stu = new Student();
	        Class c = stu.getClass();
	        //反射的无参数方法调用
	        //getMethod(?,?)方法名,调用方法要传参数类型
	        Method m1 = c.getMethod("嘿嘿");
	        //invoke(?,?)类实例,参数值
	        Object invoke = m1.invoke(stu);
	        System.out.println(invoke);
 
	        //反射的有参数方法调用
	        Method m2 = c.getMethod("嘿嘿", String.class);
	        System.out.println(m2.invoke(stu, "牛马"));
 
	        //反射的私有化有参数方法调用
	        Method m3 = c.getDeclaredMethod("add", Integer.class, Integer.class);
	        m3.setAccessible(true);
	        System.out.println(m3.invoke(stu, 90, 10));
 
 
	}
 
}

2.5、Field类

在这里插入图片描述

2.6、Field类-代码示例

/**
 * 反射读写属性
 */
public class Demo4 {
	public static void main(String[] args) throws Exception {
		Student stu = new Student("5499", "酰基");
		stu.age = 3040;
		Class clz = stu.getClass();
		//获取stu实例对象中的所有属性值
		//反射存值
		Field sname = clz.getDeclaredField("sname");
		sname.setAccessible(true);
		sname.set(stu, "犹记");
 
		//反射获取属性值
		Field[] fields = clz.getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);
			System.out.println(field.getName() + ":" + field.get(stu));
		}
	}
 
}

三、Java反射机制应用场景

3.1、应用场景

  1. 框架开发:许多流行的Java框架,比如Spring、Hibernate、Struts等,都使用了反射机制,以提供更灵活、可扩展的特性。

  2. 应用程序开发:反射机制常常用于某些需要动态加载或访问类信息的应用程序中,比如动态配置,插件管理等。

  3. 单元测试:JUnit测试框架中,反射机制被广泛应用,可以方便地创建测试对象和调用测试方法。

  4. 动态代理:反射机制可以实现动态代理,实现不改变原来代码的情况下,对原来对象的方法进行增强。

  5. JavaBean工具:JavaBean工具中,使用反射机制可以获取类的属性名、属性值、调用属性的setter和getter方法等信息,方便进行对象的序列化与反序列化操作。

3.2、哪些类型有Class对象

  1. 外部类,成员内部类,静态内部类,局部内部类,匿名内部类
  2. interface: 接口
  3. 数组
  4. enum: 枚举
  5. annotation : 注解
  6. 基本数据类型
  7. void
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤独的深山老人

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值