原理

要想理解 Java 反射,首先要弄清类的加载过程。

比如这行代码 Person p = new Person();

我们想要创建一个 Person 对象,并用 p 作为对象的引用。

在 Java 虚拟机会先执行类的加载,然后才生成对象(分配内存空间)。在类的加载过程中,类加载器负责把类编译好的 class (字节码)文件加入到内存中,并创建一个 Class 对象,这个对象是类 Class 的实例

也就是说,上面的一行的代码看似只是创建了一个 Person 对象,但是如果是第一次使用该类,也即类加载器还未把该类的 class 文件加载到内存中时,还会创建一个Class 对象

在 Java 中,一切都是对象。类是对一类对象的抽象,类是一个概念,而类本身也是一种对象,在 Java 中,它们是 Class 类的对象,当然方法、属性、注解也分别是 Method、Field、Annotation 的对象。

所以,反射干的就是干预程序运行期做的事情。比如创建一个在编译期不能确定的类(子类)。

在编码阶段不知道那个类名,这时候就没有办法硬编码new ClassName(),而必须用到反射才能创建这个对象。

在xml文件或者properties里面写好配置,然后在Java类里面解析xml或properties里面的内容,得到一个字符串。

然后用反射机制,根据这个字符串获得某个类的Class实例,这样就可以动态配置一些东西,不用每一次都要在代码里面去new或者做其他的事情。反射的目的就是为了扩展未知的应用。

使用

获取 Class 对象的三种方法

Class 对象是我们使用反射的关键,而得到这个对象有下面三种方式。

  • 调用 Class 类的 forName() 静态方法
  • 调用类的隐藏类属性 class。
  • 使用对象来获取,调用祖先类 Object 中的方法:public final native Class<?> getClass()

推荐使用第二种方式来获取 Class 对象,因为在编译期就会检查该类是否存在,更加安全,并且因为没有方法调用,使用的是属性,所以性能也更高。

Class 对象中的方法

可以说我们得到了 Class 对象,就得到了这个类的所有信息了。包括各种获取 构造方法、属性、方法、注解 的方法。

其他常用方法

public String getName() // 返回 Class 对象表示的类型(类、接口、数组或基本类型)的完整路径名字符串
public T newInstance() // 此方法是 Java 语言 instanceof 操作的动态等价方法
public ClassLoader getClassLoader() // 获取该类的类加载器
public Class getSuperclass() // 返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class
public boolean isArray() // 如果 Class 对象表示一个数组则返回 true, 否则返回 false
public boolean isInterface() // 判定指定的 Class 对象是否表示一个接口类型
public boolean isPrimitive() // 判定指定的 Class 对象是否表示一个 Java 的基本类型

例子

  1. 在我们写代码时,在对象后面敲一个 . ,IDE 就会自动帮我们列出该对象有的方法,这里其实就是IDE使用了反射,通过对象找到该类对应的 Class 对象,从而就可以找到类中的属性和方法。

  2. JDBC操作数据库第一步加载数据库驱动, Class.forName("com.mysql.jdbc.Driver"),这里是 MySQL 数据库,假如某一天我们想换成 Oracle 数据库,你可能会修改 forName() 方法中的参数为 Oracle 数据库驱动名。

  3. 做一个软件可以安装插件的功能,不知道插件的类型名称,你怎么实例化这个对象呢?所以无法在代码中 New出来 ,但反射可以,通过反射,动态加载程序集,然后读出类,检查标记之后再实例化对象,就可以获得正确的类实例。(写了一个程序,这个程序定义了一些接口,只要实现了这些接口的dll都可以作为插件来插入到这个程序中。就可以通过反射来实现。就是把dll加载进内存,然后通过反射的方式来调用dll中的方法。很多工厂模式就是使用的反射。)

项目应用

配置文件存放需要反射的类信息:

  1. 使用xml或者prop存keyvalue形式
  2. 添加一个这样的类,来专门存放需要反射的映射关系
public class Tables {
public static final Map<String, String> tables = new HashMap<>();
static {
tables.put("PICRECORD", "com.stillcoolme.entity.PICRECORD");
}
}

总结

反射可以使我们的代码更具灵活性(运行期类型的判断,动态类加载,动态代理(以后再聊这个)),但是反射也会消耗更多的系统资源,所以如果不需要动态创建一个对象,那么就不需要用到反射。

Java知识系列 -- 反射的更多相关文章

  1. 学习Spring必学的Java基础知识(1)----反射(转)

    引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...

  2. 学习Spring必学的Java基础知识(1)----反射

    引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...

  3. C# 基础知识系列- 10 反射和泛型(二)

    0. 前言 这篇文章延续<C# 基础知识系列- 5 反射和泛型>,继续介绍C#在反射所开发的功能和做的努力.上一篇文章大概介绍了一下泛型和反射的一些基本内容,主要是通过获取对象的类型,然后 ...

  4. java Reflection(反射)基础知识讲解

    原文链接:小ben马的java Reflection(反射)基础知识讲解 1.获取Class对象的方式 1.1)使用 "Class#forName" public static C ...

  5. JAVA基础系列:反射

    1. 定义 在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这 种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. ...

  6. Java基础系列 - 泛型和反射机制

    package com.test5; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * Java泛型和反射机 ...

  7. Java知识总结:Java反射机制(用实例理解)

    概念理解: 反射是指一类应用,它们能够自描述和自控制.也就是说,这类应用通过采用某种机制来 实现对自己行为的描述( self-representation )和检测( examination) ,并能 ...

  8. 【java虚拟机系列】java虚拟机系列之JVM总述

    我们知道java之所以能够快速崛起一个重要的原因就是其跨平台性,而跨平台就是通过java虚拟机来完成的,java虚拟机属于java底层的知识范畴,即使你不了解也不会影响绝大部分人从事的java应用层的 ...

  9. Java 基础系列合集

    Java基础知识你知道多少? Java特性 Java三大特性:封装,继承,多态 Java 抽象类与接口 Java 浅拷贝和深拷贝 Java static和final Java 内部类.静态内部类.匿名 ...

随机推荐

  1. linux系统更新rpm包问题 ,报错rhn-check-2.0.2-5.el7.noarch has missing requires of yum-rhn-plugin >= ('0', '1.6.4', '1')

    报错信息: rhn-check-2.0.2-5.el7.noarch has missing requires of yum-rhn-plugin >= ('0', '1.6.4', '1') ...

  2. <、>&、<& 重定向符

    <.>&.<& 重定向符 这三个命令也是管道命令,但它们一般不常用,你只需要知道一下就ok了,当然如果想仔细研究的话,可以自己查一下资料.(本人已查过,网上也查不到相 ...

  3. jsfl 巧用获取jsfl绝对路径,导入配置文件,注意配置文件无法改变舞台宽高

    //获取jsfl下的AS3.xml配置文件的路径 var jsflURL_arr=fl.scriptURI.split("/"); jsflURL_arr.splice(jsflU ...

  4. 前端开发-5-HTML-总结

    1.总体 资源:https://www.processon.com/view/link/5ad1c2d0e4b0b74a6dd64f3c html head标签 title 显示网站的标题 meta ...

  5. mysql插入json数据

    data_dict = {"a":1, "b":2}  data_json = json.dumps(data_dict) data_escape = MySQ ...

  6. mysql case, if

    if语句: 用法和excel的if函数很像 if(expr1, value_if_expr1_is_true, value_if_expr1_is_false) select if(tag = 3, ...

  7. 复习:使用HTML编写简单程序

    今天我试着用HTML编写了九九乘法表 代码如下 浏览器显示如下 2.输出静夜思 代码如下 2.浏览器显示

  8. k8s 问题

    kubelet: Orphaned pod "4db449f0-4eaf-11e8-94ab-90b8d042b91a" found, but volume paths are s ...

  9. C#操作Excel 单元格的格式处理[xyytIT]

    一. C# 操作 Excel 单元格自动填充,居中对齐,字体颜色等格式设置: Excel.Range titleRange = worksheet.get_Range(worksheet.Cells[ ...

  10. python作业(第十一周)基于RabbitMQ rpc实现的主机管理

    作业需求: 可以对指定机器异步的执行多个命令 例子: >>:run "df -h" --hosts 192.168.3.55 10.4.3.4 task id: 453 ...