Java知识系列 -- 反射
原理
要想理解 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 的基本类型
例子
在我们写代码时,在对象后面敲一个 . ,IDE 就会自动帮我们列出该对象有的方法,这里其实就是IDE使用了反射,通过对象找到该类对应的 Class 对象,从而就可以找到类中的属性和方法。
JDBC操作数据库第一步加载数据库驱动, Class.forName("com.mysql.jdbc.Driver"),这里是 MySQL 数据库,假如某一天我们想换成 Oracle 数据库,你可能会修改 forName() 方法中的参数为 Oracle 数据库驱动名。
做一个软件可以安装插件的功能,不知道插件的类型名称,你怎么实例化这个对象呢?所以无法在代码中 New出来 ,但反射可以,通过反射,动态加载程序集,然后读出类,检查标记之后再实例化对象,就可以获得正确的类实例。(写了一个程序,这个程序定义了一些接口,只要实现了这些接口的dll都可以作为插件来插入到这个程序中。就可以通过反射来实现。就是把dll加载进内存,然后通过反射的方式来调用dll中的方法。很多工厂模式就是使用的反射。)
项目应用
配置文件存放需要反射的类信息:
- 使用xml或者prop存keyvalue形式
- 添加一个这样的类,来专门存放需要反射的映射关系
public class Tables {
public static final Map<String, String> tables = new HashMap<>();
static {
tables.put("PICRECORD", "com.stillcoolme.entity.PICRECORD");
}
}
总结
反射可以使我们的代码更具灵活性(运行期类型的判断,动态类加载,动态代理(以后再聊这个)),但是反射也会消耗更多的系统资源,所以如果不需要动态创建一个对象,那么就不需要用到反射。
Java知识系列 -- 反射的更多相关文章
- 学习Spring必学的Java基础知识(1)----反射(转)
引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...
- 学习Spring必学的Java基础知识(1)----反射
引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...
- C# 基础知识系列- 10 反射和泛型(二)
0. 前言 这篇文章延续<C# 基础知识系列- 5 反射和泛型>,继续介绍C#在反射所开发的功能和做的努力.上一篇文章大概介绍了一下泛型和反射的一些基本内容,主要是通过获取对象的类型,然后 ...
- java Reflection(反射)基础知识讲解
原文链接:小ben马的java Reflection(反射)基础知识讲解 1.获取Class对象的方式 1.1)使用 "Class#forName" public static C ...
- JAVA基础系列:反射
1. 定义 在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这 种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. ...
- Java基础系列 - 泛型和反射机制
package com.test5; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * Java泛型和反射机 ...
- Java知识总结:Java反射机制(用实例理解)
概念理解: 反射是指一类应用,它们能够自描述和自控制.也就是说,这类应用通过采用某种机制来 实现对自己行为的描述( self-representation )和检测( examination) ,并能 ...
- 【java虚拟机系列】java虚拟机系列之JVM总述
我们知道java之所以能够快速崛起一个重要的原因就是其跨平台性,而跨平台就是通过java虚拟机来完成的,java虚拟机属于java底层的知识范畴,即使你不了解也不会影响绝大部分人从事的java应用层的 ...
- Java 基础系列合集
Java基础知识你知道多少? Java特性 Java三大特性:封装,继承,多态 Java 抽象类与接口 Java 浅拷贝和深拷贝 Java static和final Java 内部类.静态内部类.匿名 ...
随机推荐
- SHOW CREATE语句
show create table tablename 查看某表的建表语句 同理查看存储过程 show create procedure sp_name
- 8. 启动Tomcat闪退无法启动原因解决
原因可能是由于下面问题导致的: 1.Tomcat环境在不同电脑上引用的jdk路径不同 比如:在A电脑上Tomcat引用的jdk路径为:C:\Java\jdk1.6.0_10 而在B电脑上jdk的安装路 ...
- 24.OGNL与ValueStack(VS)-集合对象初步
转自:https://wenku.baidu.com/view/84fa86ae360cba1aa911da02.html 首先在LoginAction中增加如下字段并提供相应的get/set方法: ...
- Java Future 和 FutureTask 源码Demo
Future 是一个接口,看源码有Future 和 FutreTask 使用Demo package java.util.concurrent; /** * A <tt>Future< ...
- Python之风湿理论值函数即变量
一,风湿历练:函数即变量,这样执行程序是不会报错的 def foo(): print ("from foo") bar() def bar(): print "form ...
- clamav杀毒软件的安装
Linux Unix.Trojan.Elknot (Linux.BackDoor.Gates.5)木马清理 此恶意软件结合了传统后门程序和DDoS攻击木马的功能 前两天性能测试服务器被种马,cpu一直 ...
- 2017.1.9版给信息源新增:max_len、max_db字段
2017.1.8a版程序给信息源增加max_len.max_db字段,分别用于控制:获取条数.数据库保留条数. max_len的说明见此图: max_db的说明见此图: 当max_len和max_db ...
- go slice和数组的区别
1.使用方式 数组和slice长的很像,操作方式也都差不多,并且slice包含了数组的基本的操作方式,如下标.range循环,还有一些如len()则是多种类型共用,所以根据操作根本搞不清数组和切片的区 ...
- input:file属性
1.accept 只能选择png和gif图片 <input id="fileId1" type="file" accept="image/png ...
- grep匹配字符串出现的次数
背景:想要匹配一个html页面中某个字符出现的次数 遇到的问题: 用grep -c “xxx字符”得到的是行数,如果一行中有多个匹配到的字符,只会算作一个 解决方法: 使用grep - ...