一、概述
我们都听说过java有个反射机制,通过反射机制我们可以更深入的控制程序的运行过程。例如,在程序进入到运行期间,由用户输入一个类名,然后我们可以动态获取到该类拥有的所有类结构、属性名和方法,甚至还可以任意调用类的任意方法。听起来是不是很牛?我也觉得比较牛,挺有意思的,所以对于不太熟悉的小伙伴而言,那就来听我一一道来。
所以此期我们就来重点学习一下java的反射机制。
二、本期教学目标
- 了解什么是反射?
- 了解反射的优缺点
- 熟悉通过反射获取java对象的方法
- java常用的反射机制api
- java通过反射执行方法
- 反射实例演示
三、正文
本文首先介绍一下java中class类与java反射的基础用法,然后再结合应用具体介绍反射。
1️⃣概念
什么是反射?在介绍反射之前,我们先来了解两个概念,编译器和运行期。
- 编译器:编译器是把源代码交给编译器编译成计算机可执行的字节码文件的过程。
- 运行期:运行期是把编译好的字节码文件交给计算机(在内存)去执行的过程,直到运行结束。
而java反射,就是在程序处于运行状态中,对于任意一个类,都能够动态的获取到这个类的所有属性、方法;对于任意一个对象,都能调用它的任意方法和内部属性。这种动态获取信息以及动态调用对象方法属性的功能就被成为java的反射机制。总而言之,java反射指的是程序在运行时能获取自身的所有信息,比如类名、类路径、包路径、构造方法、私有属性等等。
所以对于java程序,只要你给定一个类名,你就可以通过java反射获取到该类的所有信息。
2️⃣功能
对于java反射机制而言,它主要提供了以下功能,且这些功能都位于java.lang.reflect包中。
如下是对于程序中,该reflect截图。
如下我就给大家诺列以下:
- 获取任意一个对象所属的类(运行期)
- 构造任意一个类的对象(运行期)
- 判断任意一个类所具有的成员变量和方法(运行期)
- 调用任意一个对象的方法(运行期)
- 生成动态代理。
而想要知道一个类的属性和方法,你必须先获取到该类的字节码文件对象。获取类信息时,使用的就是class类的方法。所以你先要获取到每一个字节码文件对应的class类型对象。比如:
java
Class aClass = dog1.getClass();
3️⃣常用Api
利用class类的对象aClass可以获取到的该类的所有信息,比如类信息、Object信息。如下是列举出来的是通过反射可获取到的常用信息,具体如下:
- getPackage():获取该类的存放路径。
- getName():获取该类的名称。
- getSuperclass():获取该类继承的类
- getlnterfaces():获取该类实现的所有接口
- getMethods():获取所有权限为 public 的方法
- getDeclaredMethods():获取当前对象的所有方法
- getClasses():获取所有权限为 public 的内部类
- getFields():获取所有权限为 public 的成员变量
4️⃣优缺点
对于反射,虽然利大于弊,但是不排除任意一个东西开发出来,都没有任何缺点。比如对于java的反射机制。
- 优点:能够程序运行时动态获取类的实例,大大提高了系统的灵活性和扩展性。且对于java先编译后运行的机制而言,更加方便灵活创建代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加的贴切面向对象。
- 缺点:反射会消耗一定的系统资源。因此如果不需要动态的创建一个对象,那就不需要使用反射。而且通过反射手法,在调用对象方法时可以忽略权限检查就能获取到该类的私有属性私有方法,可能会导致破坏类的封装性而导致安全问题。
5️⃣实例演示
如下我就通过列举一个类通过实例化后来通过反射机制来动态获取该对象的一些信息。
具体演示代码如下:
java
@Data
public class Dog extends Animal {//子类
private String active;
@Override
public void eat() {
System.out.println("我是狗狗,吃骨头!");
}
//独有功能
public void lockHome() {
System.out.println("我是狗狗,我会看家");
}
}
然后我再来定义一个main函数进行测试获取一下该对象名称:
java
public static void main(String[] args) {
Animal dog = new Dog();//向上转型
Class dogClass = dog.getClass();
System.out.println("该类的名称为:"+dogClass.getName());
}
运行截图如下:
获取该dog对象包名:
java
public static void main(String[] args) {
Animal dog = new Dog();//向上转型
Class dogClass = dog.getClass();
System.out.println("该类的包名为:"+dogClass.getPackage());
}
运行截图如下:
获取该dog对象的所有方法。
java
public static void main(String[] args) {
Animal dog = new Dog();//向上转型
Class dogClass = dog.getClass();
Method[] methods = dogClass.getDeclaredMethods();
System.out.println("该类的所有方法为:"+methods);
}
运行截图如下:
获取所有权限为 public 的内部类。
java
public static void main(String[] args) {
Animal dog = new Dog();//向上转型
Class dogClass = dog.getClass();
Class[] classes = dogClass.getClasses();
System.out.println("获取所有权限为public 的内部类:" + classes);
}
运行截图如下: