原理

要想理解 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. Jenkins + testNg + maven 项目持续集成

    搞了一整天,梳理下关键点: 1.项目的pom.xml要配置插件,同时指定testng.xml文件的位置.就被这个卡了好久 <properties> <maven-surefire-p ...

  2. Js 正则限制只能输入数字或中文的代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. setlocal 与 变量延迟

    setlocal 与 变量延迟 本条内容引用[英雄出品]的批处理教程: 要想进阶,变量延迟是必过的一关!所以这一部分希望你能认真看. 为了更好的说明问题,我们先引入一个例子.例1: @echo off ...

  4. as3 air 获取文件夹下的所有文件

    private function getFile(directory:File) { var files:Array = directory.getDirectoryListing(); for(va ...

  5. UI5-文档-4.19-Reuse Dialogs

    在此步骤中,我们将扩展重用概念,并在组件级别调用对话框. 在步骤16中,我们创建了一个对话框作为片段,以使其可跨视图或跨整个应用程序重用.但是我们将检索对话框实例和分别打开和关闭对话框实例的逻辑放置在 ...

  6. Mysql 5.8安装报错

    1 mysql安装过程中报下面这个错 解决方法:只要将目录改成反斜杠即可. 2 修改密码错误:ERROR 1064 (42000): You have an error in your SQL syn ...

  7. hibernate中1对1的注解配置

    hibernate中1对1的注解配置分为:外键关联映射和主键关联映射 1.外键配置 //一方@Entity@Table(name="test_classinfo")public c ...

  8. Anaconda中python加入环境变量

    1.我的电脑---高级系统设置 2.选中环境变量,保存. 3.在系统环境变量PATH中,加入Anaconda3及Script路径加入其中 4.测试python

  9. 域名相关:DNS A记录 NS记录 MX记录 CNAME记录

    1. DNSDNS:Domain Name System 域名管理系统 域名是由圆点分开一串单词或缩写组成的,每一个域名都对应一个惟一的IP地址,这一命名的方法或这样管理域名的系统叫做域名管理系统.D ...

  10. hibernate经常报的几个不起眼的错误, 都是因为不细心或者手滑了输入有误造成了

    最近会经常用到hibernate了, 也经常报错, 看着屏幕上一根大红条是非常不爽的, 这几天集合了一下经常报的错误, 整合一下放到这里, 以后再出现这个错误直接去解决就好了 1, org.hiber ...