Java基础 | 反射(学习笔记)

文章目录

  • 1. 概述
      • 为什么要使用反射?
  • 2. 理解Class类并实例化Class类对象
    • 2.1 理解Class类
      • 运行时类的由来
      • 类的加载过程
    • 2.2 获取Class对象方法(4种)
  • 3. 运行时创建类对象并获取类的完整结构
    • 3.1 创建运行时类的对象
  • 4. 通过反射调用类的指定方法、指定属性
  • 5. 动态代理
  • 6. 问题
    • 6.1 Java反射可以访问和修改私有成员变量,那封装成private还有意义么?

1. 概述

Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任何对象的内部属性和方法。

为什么要使用反射?

反射的主要作用是在运行时获取类信息和调用类方法,如果有些类的的信息在编译阶段是不确定,需要到运行时才确定的情况时,这个时候就需要使用到类的反射

Java反射机制主要提供以下功能:

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时获取任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的成员变量和方法
  • 生成动态代理

2. 理解Class类并实例化Class类对象

2.1 理解Class类

在《Java编程思想》中,作者告诉我们“万事万物皆是对象”,而这也是Java之中面向对象编程的核心思想。
当我们需要一个对象的时候,我们的第一想法就是先写一个类,然后new一个对象出来,但是我们有没有考虑过,既然说“万事万物皆是对象”,难道在这里类就是例外了吗?它是不是对象呢?

答案是的,我们平时写的类是java.lang.Class类的实例对象

Object类中定义了以下的方法,此方法将被所有子类继承:
public final Class getClass()

以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

运行时类的由来

创建一个类—>通过编译(javax.exe),生成对应的 .class 文件—> 通过加载(JVM的类加载器完成的java.exe)
此.class 文件加载到内存以后,就是一个运行时类,存在缓存区,那么这个运行时类本身就是一个Class的实例

  • Class本身也是一个类
  • Class 对象只能由系统建立对象
  • 一个类在 JVM 中只会有一个Class实例
  • 一个Class对象对应的是一个加载到JVM中的一个.class文件
  • 每个类的实例都会记得自己是由哪个 Class 实例所生成
  • 通过Class可以完整地得到一个类中的完整结构

类的加载过程

当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化

  1. 类的加载:将类的class文件读入内存,并为之创建一个java.lang.Class对象。此过程由类加载器完成
  2. 类的连接: 将类的二进制数据合并到JRE中
  3. 类的初始化:JVM负责对类进行初始化

2.2 获取Class对象方法(4种)

  • 通过运行时类本身的 .class 属性
  • 通过运行时类的对象,调用getClass(),返回其运行时类
  • 通过 Class 的静态方法获取
  • 通过类的加载器
Class c1 = 类名.class;

Class c2 = 实例对象.getClass();

Class c3 = Class.forName("com.类名");

ClassLoader classLoader = this.getClass().getClassLoader();
Class c4 = classLoader.loadClass("com.类名");

3. 运行时创建类对象并获取类的完整结构

3.1 创建运行时类的对象

  • 调用Class对象的newInstance()方法
Class cla = Person.class;
Person p =   (Person)cla.newInstance(); //调用此方法,必须Person类需要有对应的构造方法(如空参构造器)
System.out.println(p);

4. 通过反射调用类的指定方法、指定属性

这里只是举有关于属性和方法的一个例子,具体的没有记录

//1.通过反射调用运行时类的指定的属性、
Field f1 = cla.getField("name");
f1.set(p, "Rose");
System.out.println(p);

//2.通过反射调用运行时类的指定的方法
Method m1 = cla.getMethod("show");
m1.invoke(p);

5. 动态代理

6. 问题

6.1 Java反射可以访问和修改私有成员变量,那封装成private还有意义么?

参考回答

你可能感兴趣的:(学习,Java基础学习)