Java:反射小记

对 Java 中的 反射,做一个微不足道的小小小小记

概念

Java 反射指的是在 Java 程序运行状态中,对于任何一个类,都可以获得这个类的所有属性和方法;对于给定的一个对象,都能够调用它的任意一个属性和方法。这种动态获取类的内容以及动态调用对象的方法称为反射机制

进一步

首先,每个类都有一个 Class 对象,包含了与类有关的信息。当编译一个新类时,会产生一个同名的 .class 文件,该文件内容保存着 Class 对象。类加载相当于 Class 对象的加载,类在第一次使用时才动态加载到 JVM 中。也可以使用 Class.forName("全限定类名") 这种方式来控制类的加载,该方法会返回一个 Class 对象。

反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的 .class 不存在也可以加载进来。

实现

Class类java.lang.reflect 一起对反射提供了支持java.lang.reflect 类库主要包含了以下三个类:

  1. Field :可以使用 get()set() 方法读取和修改 Field 对象关联的字段;

    // 定义类
    class Person{
    private String name; public Person() {
    } public Person(String name) {
    this.name = name;
    } @Override
    public String toString() {
    return "Person{" +
    "name='" + name + '\'' +
    '}';
    }
    } @Test
    public void test09() throws Exception{
    Person person = new Person("李二甩");
    System.out.println(person);
    Class<? extends Person> c = person.getClass(); // 获得Person类对象 // 定义要修改的属性
    Field name = c.getDeclaredField("name");
    // 暴力反射
    name.setAccessible(true);
    // 修改属性,传入要设置的对象和值
    name.set(person, "李三甩");
    System.out.println(person); // Person{name='李三甩'}
    }
  2. Method :可以使用 invoke() 方法调用与 Method 对象关联的方法;

    class Cat{
    public void speak(String str){
    System.out.println(str);
    } public void run(int i){
    System.out.println(i + "s");
    }
    } @Test
    public void test10() throws Exception{
    Cat cat = new Cat();
    Class<? extends Cat> c = cat.getClass(); // getMethod()方法需要传入方法名,和参数类型
    Method speak = c.getMethod("speak", String.class);
    // invoke()表示调用的意思,需要传入对象和参数
    speak.invoke(cat, "喵喵"); // getMethod()方法需要传入方法名,和参数类型
    Method run = c.getMethod("run", int.class);
    run.invoke(cat,3600);
    }
  3. Constructor :可以用 Constructor 创建新的对象。

    @Test
    public void test11() throws Exception{
    Class<?> c = Class.forName("java.lang.Boolean");
    // 获取构造函数数组
    // Constructor<?>[] constructors = c.getConstructors();
    // 获取构造函数
    Constructor<?> constructor = c.getConstructor(String.class);
    Boolean bool = (Boolean) constructor.newInstance("true");
    System.out.println(bool);
    }

应用举例:工厂模式,使用反射机制,根据全限定类名获得某个类的 Class 实例。

反射的优缺点

优点:运行期类型的判断,class.forName() 动态加载类,提高代码的灵活度;

缺点:尽管反射非常强大,但也不能滥用。如果一个功能可以不用反射完成,那么最好就不用。在我们使用反射技术时,下面几条内容应该牢记于心。

  1. 性能开销 :反射涉及了动态类型的解析,所以 JVM 无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。
  2. 安全限制 :使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如 Applet,那么这就是个问题了。
  3. 内部暴露:由于反射允许代码执行一些在正常情况下不被允许的操作(比如:访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用,这可能导致代码功能失调并破坏可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。

参考

https://www.cnblogs.com/nerxious/archive/2012/12/24/2829446.html

https://mp.weixin.qq.com/s/4E3xRXOVUQzccmP0yahlqA

Java:反射小记的更多相关文章

  1. 第28章 java反射机制

    java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...

  2. Java反射机制

    Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射:     静态编译:在编译时确定类型,绑定对象,即通过 ...

  3. java反射(基础了解)

    package cn.itcast_01; /** *Person类 */ public class Person {    /** 姓名 */    private String name;     ...

  4. java基础知识(十一)java反射机制(上)

    java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...

  5. java基础知识(十一)java反射机制(下)

    1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...

  6. java反射学习之二万能EXCEL导出

    一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...

  7. java反射学习之一反射机制概述

    一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...

  8. java反射 之 反射基础

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

  9. java反射 cglib asm相关资料

    有篇文章对java反射的调用的效率做了测试,写的比较好.猛击下面地址 http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html ...

随机推荐

  1. Django的form组件——自定义校验函数

    from django.shortcuts import render,HttpResponse from django import forms from django.core.exception ...

  2. 20210803 noip29

    考场 第一次在 hz 考试.害怕会困,但其实还好 看完题感觉不太难,估计有人 AK. T3 比较套路,没办法枚举黑点就从 LCA 处考虑,在一个点变成黑点时计算其他点和它的 LCA 的贡献,暴力跳父亲 ...

  3. javascript(2)运算符

    ### js运算符 1.运算符 1.typeof 获取当前变量类型 运算符(特殊) 2.= 赋值运算符 3.== 简要比较运算符(忽略变量的类型) 4.=== 标准比较运算符(严格变量的类型.判断是否 ...

  4. 专项测试-App性能分析

    专项测试 app性能 Activity是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,BroadcastRece ...

  5. 如何实现自定义sk_buff数据包并提交协议栈

    目录 一.自定义数据包的封装流程 1. 分配skb 2.初始定位(skb_reserve) 3.拷贝数据(skb_push / skb_pull / skb_put / ) 4.设置传输层头部 5.设 ...

  6. ysoserial CommonsColletions2分析

    ysoserial CommonsColletions2分析 前言 此文章是ysoserial中 commons-collections2 的分析文章,所需的知识包括java反射,javassist. ...

  7. js-监听网络状态

    <script> // 监听网络状态 window.addEventListener("online", function(){ alert("网络连接了&q ...

  8. Java基础系列(4)- 编译型和解释型

    概念 有一个外国人要看一本中文的书,有两种方式可以看,一种是把这本书翻译成英文版,另外一种是请一个中文翻译,想看哪边,翻译就翻译哪边. 针对上述的描述,翻译成英文版本的书籍对应的就是编译型,将代码编译 ...

  9. Jmeter扩展组件开发(2) - 扩展开发第一个demo的实现

    maven工程src目录介绍 main:写代码 main/java:写Java代码 main/resources:写配置文件 test:写测试代码 test/java demo实现 创建Package ...

  10. Linux系列(29) - rpm包命名规则(1)

    RPM包命名规则 例如包名:httpd-2.2.15-15.el6.centsos.1.i686.rpm 软件包名-httpd 软件版本-2.2.15 发布的次数-15 el6.centos适合的Li ...