1. 反射的概念

反射 机制指的是,程序在运行时能够获取自身的信息。在 java 中只要给定类的名字,就能够获取类的所有属性和方法

反射是 Java 中很多高级特性的基础,比如 注解、动态代理 以及 Spring Ioc、AOP 等技术都需要借助反射来实现。

2. Class 对象的创建

java 中 java.lang.Class 是反射机制的基础,当我们想要在运行期获取一个类中的相关信息的时候,必须先获取其 Class 类。Jvm 会自动将已加载类的 Class 对像载入。

获取 Class 对象的三种方式:

  • 对象实例.getClass()

    MyObject obj = new MyObject();

    Class clazz = obj.getClass();

  • 类名.Class

    Class clazz = MyObject.Class;
  • Class.forName()

    Class clazz = Class.forName("MyObject");

3. 通过反射创建实例

java 中,最常使用的创建实例方法是通过 new 关键字来实现的。使用反射,也有两种可以 创建实例 的方式。

使用 Class 对象的 newInstance() 方法

Class clazz = MyObject.class;
MyObject myObject = clazz.newInstance();

使用 java.lang.reflet.Constructor 中的 newInstance() 方法

Constructor<MyObject> constructor = MyObject.class.getConstructor();
MyObject myObject = constructor.newInstance();

说明:其实 clazz.newInstance() 创建实例的内部也是通过 Constructor 创建实例的方式来实现的

4. 通过反射获取类的属性、方法、注解、构造器

Class 类中有获取类的所有 属性、方法、注解、构造器的相关方法。如下:

获取 非私有的 属性、方法、注解、构造器

Field[] getFields();    // 获取属性
Method[] getMethods(); // 获取方法
Annotation[] getAnnotations(); // 获取注解
Constructor<?>[] getConstructors(); // 获取构造器

获取** 私有的** 属性、方法、注解、构造器

Field[] getDeclaredFields();    // 获取私有属性
Method[] getDeclaredMethods(); // 获取私有方法
Annotation[] getDeclaredAnnotations(); // 获取私有注解
Constructor<?>[] getDeclaredConstructors(); // 获取私有构造器

使用示例:

Class clazz = MyObject.class;
Methods[] methodList = clazz.getFields();

5. 反射机制的一些缺点

  • 反射会破坏封装性:由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用--代码有功能上的错误,降低可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。

  • 反射的性能问题:反射包括了一些动态类型,所以 JVM 无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被 执行的代码或对性能要求很高的程序中使用反射。

  • 安全性问题:使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如 Applet,那么这就是个问题了。

6. 反射对单例的破坏

单例是为了控制 类示例 在内存中只存在一个的机制。他本身的构造方法是 private 的,对外提供 getSingleton() 方法,统一管理实例的获取。

而反射可以通过获取到类中的私有构造方法, 并将其变为可用,通过构造方法生成新的实例,这样就造成了单例的破坏。

双重校验锁的单例模式:

public class Singleton {
private static volatile Singleton singleton(); private Singleton() {
} public static Singleton getSingleton() {
if(singleton == null) {
synchronized (Singleton.class) {
if(singleton == null) {
singleton = new Singleton();
}
}
} return singleton;
}
}

通过反射破坏单例:

Singleton singleton1 = Singleton.getSingleton();
// 通过反射获取构造函数
Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
// 将构造方法设置为可访问
constructor.setAccessible(true);
// 通过构造方法创建一个新的实例
Singleton singleton2 = constructor.newInstance(); System.out.print(singleton1 == singleton2); // false

解决方案:在单例类的构造方法中加判断,当实例已存在的时候,不再创建新的实例

private Singleton() {
if(singleton != null) {
throw new RuntimeException("单例对象只能创建一次...");
}
}

Java中的反射机制及反射的优缺点的更多相关文章

  1. Java 反射机制[Method反射]

    Java 反射机制[Method反射] 接着上一篇Java 反射机制[Field反射],通过调用Person类的setName方法将obj的name字段的Value设置为"callPerso ...

  2. Java 反射机制[Field反射]

    Java 反射机制[Field反射] 1.  反射概念及功能 反射就是把Java类中的各种成分映射成对应的Java类.比如一个Java类中用一个Class类的对象来表示. 一个类中的组成部分分为成员变 ...

  3. java中wait/notify机制

    通常,多线程之间需要协调工作.例如,浏览器的一个显示图片的线程displayThread想要执行显示图片的任务,必须等待下载线程 downloadThread将该图片下载完毕.如果图片还没有下载完,d ...

  4. 【Java】深入理解Java中的spi机制

    深入理解Java中的spi机制 SPI全名为Service Provider Interface是JDK内置的一种服务提供发现机制,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用 ...

  5. 【夯实基础】- Java中的fail-fast机制

    转载自:Java中的fail-fast机制 遍历删除List中的元素有很多种方法,当运用不当的时候就会产生问题.下面主要看看以下几种遍历删除List中元素的形式: 1.通过普通的for删除删除符合条件 ...

  6. 结合实战和源码来聊聊Java中的SPI机制?

    写在前面 SPI机制能够非常方便的为某个接口动态指定其实现类,在某种程度上,这也是某些框架具有高度可扩展性的基础.今天,我们就从源码级别深入探讨下Java中的SPI机制. 注:文章已收录到:https ...

  7. 一篇文章看懂java反射机制(反射实例化对象-反射获得构造方法,获得普通方法,获得字段属性)

    Class<?> cls = Class.forName("cn.mldn.demo.Person"); // 取得Class对象传入一个包名+类名的字符串就可以得到C ...

  8. Java核心技术梳理-类加载机制与反射

    一.引言 反射机制是一个非常好用的机制,C#和Java中都有反射,反射机制简单来说就是在程序运行状态时,对于任意一个类,能够知道这个类的所有属性和方法,对于任意一个对象,能够调用它的任意属性和方法,其 ...

  9. Java中的代理机制

    Java的三种代理模式 代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能. 简言之,代理模 ...

  10. JAVA中关于锁机制

    本文转自 http://blog.csdn.net/yangzhijun_cau/article/details/6432216 一段synchronized的代码被一个线程执行之前,他要先拿到执行这 ...

随机推荐

  1. Centos7新增静态路由

    文章转载自:https://blog.51cto.com/loong576/2417561 环境说明: 一.临时方式 1. 查看路由和ip [root@centos7 ~]# route -n Ker ...

  2. Solutions:Elastic SIEM - 适用于家庭和企业的安全防护 ( 五)

  3. docker 生成mysql镜像启动时自动执行sql

    文章转载自:https://www.jianshu.com/p/12fc253fa37d 在docker 创建 mysql 容器时,往往需要在创建容器的过程中创建database 实例,代码如下: # ...

  4. vue通过插件实现PDF生成以及下载

    第一步: 安装插件 npm install --save html2canvas //将html转换成图片 npm install jspdf --save //将图片生成pdf 第二步: 在需要的地 ...

  5. 谣言检测(PLAN)——《Interpretable Rumor Detection in Microblogs by Attending to User Interactions》

    论文信息 论文标题:Interpretable Rumor Detection in Microblogs by Attending to User Interactions论文作者:Ling Min ...

  6. Python函数-2V2

    一.导入 $$ f ( x , y ) = 2 x + 3 y $$ 上面括号里面的就是数学公式里的自变量,自变量就相当于函数里的参数. 二.为什么要有参数 如果一个大楼里有两种尺寸不一的窗户,显然在 ...

  7. 追求性能极致:Redis6.0的多线程模型

    Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) Redis系列5: ...

  8. Js实现一键复制小功能

    function copyToClipboard(textToCopy) { // navigator clipboard 需要https等安全上下文 if (navigator.clipboard ...

  9. 快速上手Mybatis项目

    快速上手Mybatis项目 思路流程:搭建环境-->导入Mybatis--->编写代码--->测试 1.搭建实验数据库 CREATE DATABASE `mybatis`; USE ...

  10. 在js中正则表达式验证小时分钟,将输入的字符串转换为对应的小时和分钟

    文章目录 1.预备知识 2.在js中的代码片段 3.测试结果 1.预备知识 splict()方法 Date()的相关方法 setHours()的用法 2.在js中的代码片段 //验证小时和分钟 var ...