java反射知识点总结(框架灵魂篇)

怼烎@ 2023-03-13 02:35 20阅读 0赞

反射库(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”

  3. 还可以调用静态方法 forName 获得类名对应的 Class 对象。

    String className = “java.util.Random”;
    Class cl = Class.forName(className) ;

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

  1. String className = "java.util.Random";
  2. Class cl = null;
  3. try {
  4. cl = Class.forName(className);
  5. } catch (ClassNotFoundException e) {
  6. // TODO Auto-generated catch block
  7. e.printStackTrace();
  8. }

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

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

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

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

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

四、调用任意方法

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

我们来看代码:

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

  1. public class Student {
  2. private int age;
  3. @Override
  4. public String toString() {
  5. return "Student [age=" + age + "]";
  6. }
  7. }

2)、

  1. public class TestReflect {
  2. public static void main(String[] args) {
  3. Student student = new Student();
  4. try {
  5. Field age = Student.class.getDeclaredField("age");
  6. //设置可访问非常重要
  7. age.setAccessible(true);
  8. age.set(student,20);
  9. System.out.println(student);
  10. System.out.println(age.get(student));
  11. } catch (NoSuchFieldException e) {
  12. // TODO Auto-generated catch block
  13. e.printStackTrace();
  14. } catch (IllegalAccessException e) {
  15. // TODO Auto-generated catch block
  16. e.printStackTrace();
  17. }
  18. System.out.println("------------------------------------------------");
  19. try {
  20. Method toString = Student.class.getDeclaredMethod("toString");
  21. Object invoke;
  22. invoke = toString.invoke(student);
  23. System.out.println(invoke);
  24. } catch (IllegalAccessException e) {
  25. // TODO Auto-generated catch block
  26. e.printStackTrace();
  27. } catch (NoSuchMethodException e) {
  28. // TODO Auto-generated catch block
  29. e.printStackTrace();
  30. }catch (InvocationTargetException e) {
  31. // TODO Auto-generated catch block
  32. e.printStackTrace();
  33. }
  34. }
  35. }

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

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

五、反射的用途

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

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

拓展:

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

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

发表评论

表情:
评论列表 (有 0 条评论,20人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java知识总结《努力下》

    本文主要编辑小白学习 Java 时感觉重要的、容易忘掉的的细节小知识或者知识补充。想着会对学习和使用 Java 的查漏补缺很有帮助,就一点点记录下来了,内容比较多的知识点...

    相关 Java反射——框架设计的灵魂

    java反射概念: [JAVA反射][JAVA]机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种