框架必经之路:java反射知识点总结

反射库(reflection library) 提供了一个非常丰富且精心设计的工具集, 以便编写能够动态操纵 Java 代码的程序。这项功能被大量地应用于 JavaBeans 中,它是 Java 组件的体系结构。 - - - - - - - - - - - - - - - - - - -源于Java核心技术(卷Ⅰ)的引用

在理解反射之前需要了解类加载机制

一、什么是反射

能够分析类能力的程序称为反射(reflective)。

二、获得class类对象的三种方式

在程序运行期间,Java 运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。 虚拟机利用运行时类型信息选择相应的方法执行。
然而,可以通过专门的 Java 类访问这些信息。保存这些信息的类被称为 Class, 这个名字很容易让人混淆。Object 类中的 getClass( ) 方法将会返回一个 Class 类型的实例。

  1. 类名.class(例如:Student.class)
  2. 对象.getClass()
Random generator = new Random():
Class cl = generator.getClass() ;
String name = cl.getName(); // name is set to "java.util.Random"
  1. 还可以调用静态方法 forName 获得类名对应的 Class 对象。
String className = "java.util.Random";
Class cl = Class.forName(className) ;

如果类名保存在字符串中, 并可在运行中改变, 就可以使用这个方法。当然, 这个方法只有在 dassName 是类名或接口名时才能够执行。 否则,forName 方法将抛出一个 checkedexception ( 已检查异常)。无论何时使用这个方法, 都应该提供一个异常处理器(exception handler) 。

String className = "java.util.Random";
Class cl = null;
try {
	cl = Class.forName(className);
} catch (ClassNotFoundException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}
		

三、通过反射来创建对象(生成类的实例)

//通过反射创建,需要注意此处是需要抛出异常的
Student student = Student.class.newInstance();

//通过new
Student student1 = new Student();

两者创建对象是等价的,由此我们可以看出创建对象不一定非等通过new 来实现。

那么我们就要想既然可以通过new来生成实例,为什么还需要反射呢?
解释:我们知道通过new来创建对象比反射生成的实例要快,但是我们可能遇到过一种情况,new没办法使用的时候,比如说我们在使用框架的时候事先不知道这些类,没办法通过new来创建实例,只能通过反射来生成实例。我们是迫不得已的时候才使用反射来生成实例。
还有就是比如我们在使用tomcat开启动web项目的时候,tomcat开发者不知道项目中会有什么类,无法通过new来生成类的实例,所以tomcat容器写了一个类的模板,运行的时候利用反射获取类信息,然后生成对应的实例,然后执行调用方法。

附:简易类加载机制图
在这里插入图片描述

四、调用任意方法

在 C 和 C++ 中, 可以从函数指针执行任意函数。从表面上看, Java 没有提供方法指针,即将一个方法的存储地址传给另外一个方法, 以便第二个方法能够随后调用它。事实上,Java 的设计者曾说过:方法指针是很危险的,并且常常会带来隐患。 他们认为 Java 提供的接口(interface) 是一种更好的解决方案。然而, 反射机制允许你调用任意方法

我们来看代码:

1)、我先定义了一个学生类,注意age属性是私有的

public class Student {
	private int age;

	@Override
	public String toString() {
		return "Student [age=" + age + "]";
	}
	
}

2)、

public class TestReflect {
	public static void main(String[] args) {
		Student student = new Student();
		
		try {
			Field age = Student.class.getDeclaredField("age");
			
			//设置可访问非常重要
            age.setAccessible(true);
		
			age.set(student,20);
            System.out.println(student);
            System.out.println(age.get(student));
            
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		System.out.println("------------------------------------------------");
		
		try {
			Method toString = Student.class.getDeclaredMethod("toString");
			Object invoke;
			invoke = toString.invoke(student);
			System.out.println(invoke);
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

运行结果:
在这里插入图片描述

1、我们通过第一个try-catch可以看到即使是对象中的私有属性通过反射也是可以访问到的,前提是设置可访问的属性。
2、通过第二个try-catch的应用我们便实现了利用反射机制中的invoke方法来调用对象中的方法,也就是我们通常所说的代理,从这里我们可以看到,反射和代理是在一起使用的。

五、反射的用途

说了这么多,反射的用途到底是什么,反射主要的作用是什么?

通过以上的介绍我们可以总结两句话:
1、通过反射获取类信息;
2、根据类信息生成实例(实例化功能);
3、反射最终的目的是拿到类的实例。

拓展:

反射除了这些,在我们的Spring框架中的应用是很多很多的,比如说ioc和aop,springMVC原理等等都用到了反射机制,反射在框架中应用很广,这是一个非常重要的知识点,对于我们学习web是必须要掌握的。

如果大家有兴趣可以阅读Java核心技术(卷Ⅰ)这本书,里面有对反射机制更详细的讲解。

©️2020 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值