萤火小屋

优律的知识库

  • 首页
  • 归档
  • 分类
  • 标签
  • 留言
  • 关于

  • 搜索
消息队列 RabbitMQ Redis 双指针 力扣 动态代理 Git YAML SpringBoot SpringMVC 回溯算法 分治算法 归并排序 快排 手撕 事务 MySQL索引 MySQL 小技巧 Spring Framework Spring 动态规划 Linux Android 贪心算法 操作系统 进程调度模拟 IPv6 数据库 计算机组成原理 计算机基础 栈 Java 静态路由 路由器 交换机 数字通信 网络工程 计算机网络 Web http 大学学习技巧 程序设计 算法

Java的反射

发表于 2021-10-22 | 分类于 Java SE | 0 | 阅读次数 151

1 概念

1.1 反射的概念

在Java中的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法,并且对于任意一个对象,都能够调用它的任意一个方法。这种动态获取信息以及动态调用对象方法的功能成为Java语言的反射机制。

Java-Reflection-Mind-map

1.2 动态语言

动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化。比如常见的 JavaScript 就是动态语言,除此之外Ruby,Python等也属于动态语言,而C/C++则不属于动态语言。从反射角度说Java属于半动态语言。

2 反射的应用场景

2.1 编译时类型和运行时类型

在Java程序中,许多对象在运行时都会出现两种类型:编译时类型和运行时类型。 编译时的类型由声明对象时使用的类型来决定,运行时的类型由实际赋值给对象的类型决定。例如:List<String> t = new ArrayList<String>();
其中编译时类型为List,运行时类型为ArrayList。

2.2 编译时类型无法获取具体方法

程序在运行时还可能接收到外部传入的对象,该对象的编译时类型为Object,但是程序有需要调用该对象的运行时类型的方法。为了解决这些问题,程序需要在运行时发现对象和类的真实信息。然而,如果编译时根本无法预知该对象和类属于哪些类,程序只能依靠运行时信息来发现该对象和类的真实信息,此时就必须使用到反射了。(说白了就是向下转型,程序需要知道子类是谁)

3 Java反射的API

3.1 类、接口信息

  1. Class类:反射的核心类,可以获取类的属性,方法等信息。
  2. Field类:java.lang.reflect包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值。
  3. Method类:java.lang.reflect包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。
  4. Constructor类:java.lang.reflect包中的类,表示类的构造方法。

3.2 反射的使用

  1. 获取想要操作的类的Class对象,他是反射的核心,通过Class对象我们可以任意调用类的方法。(获取Class对象)
  2. 调用Class类中的方法,即就是反射的使用阶段。(调用对象方法)
  3. 使用反射API来操作这些信息。

3.2.1 获取Class对象的3种方法

  1. 调用某个对象的getClass()方法
User user = new User();
Class clazz = user.getClass();
  1. 调用某个类的class属性来获取该类对应的Class对象
Class clazz = User.class;
  1. 使用Class类中的forName()静态方法(最安全、最常用、性能最好)
Class clazz = Class.forName("cc.fireflyhut.test.entity.User");

3.2.2 通过类对象查看类信息(方法、属性)

当我们获得了想要操作的类的Class对象后,可以通过Class类中的方法获取并查看该类中的方法和属性。

// 获取类对象
Class clazz = Class.forName("cc.fireflyhut.test.entity.User");

// 获取User类的所有方法信息
Method[] methods = clazz.getDeclaredMethods();
for (Method m : methods) {
	System.out.println(m.toString());
}

// 获取User类的所有成员属性信息
Field[] fields = clazz.getDeclaredFields();
for (Field f : fields) {
	System.out.println(f.toString());
}

// 获取User类的所有构造方法信息
Constructor[] constructors = clazz.getDeclaredConstructors();
for(Constructor c : constructors){
	System.out.println(c.toString());
}

3.2.3 创建对象的两种方法

  1. 调用Class对象的newInstance()方法

    使用Class对象的newInstance()方法来创建该Class对象对应类的实例,但是这种方法要求该Class对象对应的类有默认的空构造器。

// 获取User类的Class对象
Class clazz = Class.forName("cc.fireflyhut.test.entity.User");

// 使用newInstane方法创建对象
User user = (User)clazz.newInstance();
  1. 调用Constructor对象的newInstance()方法

    先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建Class对象对应类的实例,通过这种方法可以选定构造方法创建实例。

//获取User类的Class对象
Class clazz = Class.forName("cc.fireflyhut.test.entity.User");

// 获取构造方法并创建对象(这里选定了两个String参数的构造器)
Constructor c = clazz.getDeclaredConstructor(String.class, String.class);

// 创建对象并设置属性
User user = (User)c.newInstance("admin", "123456");
# 程序设计 # Java
Spring学习笔记-SpringMVC
Java多线程和并发
  • 文章目录
  • 站点概览
优律

优律

优律的知识库

77 日志
20 分类
44 标签
E-mail Twitter Instagram
Links
  • CZLisyx - 浮生志
  • Vedfolnir
0%
© 2019 — 2023 萤火小屋——优律的博客网站
网站已勉强运行 
Halo博客系统技术支持