反射的概念

  • java 的放射机制:在程序运行时,程序有能力获取一个类的所有方法和属性;并且对于任意一个对象,可以调用它的任意方法或者获取其属性

  • 通俗解析:java 文件需要编译成. class 文件才能被 jvm 加载使用, 对象的. class 数据在 jvm 里就是 Class;我们如果能拿到这个 Class对象,就能获取该 Class对应的对象类型,及在该类型声明的方法和属性值;还可以根据 Class创建相应的类型对象,通过 Field,Method 反过来操作对象

  • java 相关类介绍

类名 描述
Class 代表类的实体,在运行的 Java 应用程序中表示类或者接口
Field 类的成员变量(成员变量也称为类的属性)
Method 类的方法
Constructor 类的构造方法

获取 Class 的三种方法

  • 1 通过已知的类型获取 class
// 根据Example 获取Class =》Example.classpublic Class getExample(){    Class clazz = Example.class;return clazz;}
  • 2 通过实例对象获取 class
public Class getExampleByInstance(){    Example example = new Example();    // getClass是Object类里面的方法;《?》 是通配符    Class clazz = example.getClass();return (Class)clazz;}
  • 3 通过 Class.forName 获取全路径指定类名的 class
/\*\* forName0 本地方法,C++实现,jvm调用 \* 1 className 是个类名  2 initialize 是否延迟加载  3 loader 加载器 \*/private static native Class forName0(String className, boolean initialize,        ClassLoader loader, Class caller) throws ClassNotFoundException;

public static Class forName(String className) throws ClassNotFoundException {        Class caller = Reflection.getCallerClass();        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);    }// 两个forName方法最终都会调用forName0方法去加载class   public static Class forName(String name,        boolean initialize, ClassLoader loader) throws ClassNotFoundException {        ....        return forName0(name, initialize, loader, caller);    }
// 示例:通过java.lang.Integer public Class getInteger()throws ClassNotFoundException{    Class clazz = Class.forName("java.lang.Integer");return (Class)clazz;}

JAVA 反射 API

  • Class 常用操作方法
//获取所有的构造方法 / private publicpublic Constructor\[\] getDeclaredConstructors()//获取特定的构造方法 / private publicpublic Constructor getDeclaredConstructor(Class... parameterTypes)    //获取类的父类public native Class getSuperclass()    //获取类实现的接口private Class\[\] getInterfaces(boolean cloneArray)  //获取在类内定义的内部类或接口public Class\[\] getDeclaredClasses()//获取所有的方法public Method\[\] getDeclaredMethods() throws SecurityException//根据方法名和参数获得特定的方法public Method getDeclaredMethod(String name, Class... parameterTypes)  //获取类型的定义的所有属性public Field\[\] getFields() throws SecurityException// 根据属性命名获得特定的Fieldpublic Field getField(String name) 
  • Method 常用的操作方法
//获得方法的放回类型public Class getReturnType()   //获得方法的传入参数类型public Class\[\] getParameterTypes()   //obj是实例对象,args是方法,反过来由Method控制对象的方法调用public Object invoke(Object obj, Object... args)
  • Field 常用的操作方法
//属性与obj相等则返回truepublic boolean equals(Object obj)//获得obj中对应的属性值public Object get(Object obj)//设置obj中对应属性值public void set(Object obj, Object value) 
  • Constructor
//根据传递的参数创建类的对象:initargs 构造方法参数public T newInstance(Object... initargs) 
  • 1 根据 class 创建对象
//方式一 clazz.newInstance()Class clazz = Example.class;Example example = clazz.newInstance();//方式二 先获取再由Constructor:clazz.getConstructors()/getConstructor(...) //再由Constructor.newInstance 方法构造对象-----------------------------------------public class Example {    private int value;    public Example(){ } // 如果只声明有参构造函数,clazz.newInstance()会报错    public Example(Integer value){  this.value  = value;  }    static public void main(String\[\] args) throws Exception{        Class clazz = Example.class;        //根据指定构造函数参数获取Constructor        Constructor constructor = clazz.getConstructor(Integer.class);        Example example = constructor.newInstance(100);        System.out.println(example.value);    }}    
  • 2 由 class 获取 Field,并操作实例的属性
public class Example {    private int value , count;    static public void main(String\[\] args) throws Exception{        Class clazz = Example.class;        //获取所有的属性,getField只能获取public的属性        Field\[\] fs = clazz.getDeclaredFields();        //根据名称获取指定 Field        Field value = clazz.getDeclaredField("value");        Example example = clazz.newInstance();        //使用反射机制可以打破封装性,导致了java对象的属性不安全          value.setAccessible(true); //setAccessible(true)让private的参数可赋值操作        //由Field反过去设置example的值        value.set(example,100);        System.out.println(example.value);    }}
  • 3 由 class 获取 Method,并反射调用实例方法
public class Example {    public static void main(String\[\] args) throws Exception {        Class clazz = Example.class;        Example example = clazz.newInstance();        Method\[\] methods = clazz.getDeclaredMethods();        //getDeclaredMethod和getMethod是:getMethod只能返回public的方法        Method method = clazz.getDeclaredMethod("hello", String.class);        method.setAccessible(true);        method.invoke(example, "cscw");    }    private void hello(String name) { System.out.println(name + " Hello!"); }}-----cscw Hello!

反射机制应用的场景

  • 1 动态拓展:假设有同一组类是实现相同的接口,并且类的加载方式不限制。当我们需要那种具体类实现的功能时,只需加载. class 文件,并获取对应的 Class对象。可以由 Class 或者 Constructor 实例化对象 instance;根据接口定义,可以获取 Class里的某一方法 Method,并配合 instance 反射调用功能方法

  • 2 Spring 的 IOC 就是基于反射机制实现

  • 3 JDK 的动态代理

反射和 JDK 动态代理

  • 在 Java 的 java.lang.reflect 包下提供了一个 Proxy 类和一个 InvocationHandler 接口。通过这个类和接口可以生成 JDK 动态代理类或动态代理对象
public interface InvocationHandler { //所有方法都会调用此代理方法    Object invoke(Object var1, Method var2, Object\[\] var3) throws Throwable;}  public class Proxy implements Serializable{ ...    //根据interfaces和InvocationHandler生成代理对象    public static Object newProxyInstance(ClassLoader loader,      Class\[\] interfaces, InvocationHandler h)     ...    }
  • JDK 的动态代理由 Proxy 和 InvocationHandler 实现;而被代理对象必须实现一个接口。代理对象由 Proxy 生成,可转为接口 interface 的实现类对象 OBJ。当调用 OBJ 的方法时,则会触发 InvocationHandler.invoke,参数依次为「代理对象」「Method 对象」, 和「方法 Method 所需的参数」。在 invoke 方法可以加入拓展的逻辑,如日志记录操作;「并可以在 invoke 里利用反射的技术调用被代理对象方法」

  • 示例

public class ExampleFactory implements InvocationHandler{    private T target; //被代理对象    public T bind(T obj){        target = obj;return (T)Proxy.newProxyInstance(obj.getClass().getClassLoader(),           obj.getClass().getInterfaces(),this);    }    /\*\* Object o 是代理对象; o的方法调用 -> ExampleFactory.invoke     \*  invoke(...) -> 在invoke方法里面 反射调用代理对象方法+增强逻辑    \*/    @Override    public Object invoke(Object o, Method method, Object\[\] objects) throws Throwable {        //增强逻辑        System.out.println("log start");        //反射调用被代理对象方法        Object result = method.invoke(target,objects);        System.out.println("log end");return result;    }}-----------public interface Face {    void hello(String name);}---------//被代理对象必须实现一个接口,并由接口方法对方提供功能public class Example implements Face { public void hello(String name) {        System.out.println(name + " Hello!");    }    public static void main(String\[\] args)  {       //ExampleFactory 相当于一个中介人        ExampleFactory factory = new ExampleFactory<>();        //example 是代理对象        Face example = exampleProxy.bind(new Example());        example.hello("思婷");    }}-----log start思婷 Hello!log end

欢迎指正文中错误

java 反射机制_基础篇:深入解析JAVA反射机制相关推荐

  1. java peek函数_基础篇:JAVA.Stream函数,优雅的数据流操作

    写在开头:本文是转载于掘金上的一篇文章,已获得原作者授权,我会在文章最后放上原作者和原文链接. 前言 平时操作集合数据,我们一般都是for或者iterator去遍历,不是很好看.java提供了Stre ...

  2. java的博_小博老师解析Java核心技术 ——I/O流

    [引言] 我们在学习Java编程的时候,经常会遇到文件数据的各类操作,这类操作一般都会借助于JDK中的I/O流对象.我们知道JDK中I/O流的实现类有很多种类型,那么在实际操作中我们该如何取舍呢?今天 ...

  3. java参数化查询_小博老师解析Java核心技术 ——JDBC参数化查询(二)

    [步骤阅读四]SQL注入 按照以上方式开发,确实已经完成了基本的用户登录业务需求,但是这么做的话可以会出现一个比较严重的问题,那就是容易被SQL注入.所谓SQL注入,就是在需要用户填写信息,并且这些信 ...

  4. invader的java学习第一天基础篇

    invader的java学习第一天基础篇 一.java主要历史 ①java是Sun公司的产品,09年被Oracle公司收购. ②java语言之父:詹姆士高斯林 二.jdk.jre.jvm三者关系 jd ...

  5. 你所需要的java基础篇深入解析大汇总

    java基础篇深入解析大总结 java基础(一) 深入解析基本类型 java基础(二) 自增自减与贪心规则 java基础(三) 加强型for循环与Iterator java基础(四) java运算顺序 ...

  6. 东华大学2020考研计算机复试准备上机题解析答案_基础篇 前言

    东华2020考研复试准备上机题解析答案_基础篇 前言 大家好,我是今年参加东华大学研究生入学考试的学生,前不久东华大学发布了关于复试上机的通知,还有题库供大家练习.我于是刷完了所有的题目,并且把题目和 ...

  7. java语言程序设计基础篇课后答案_《Java语言程序设计:基础篇》课后复习题答案-第十五章.pdf...

    <Java语言程序设计:基础篇>课后复习题答案-第十五章 Chapter15Graphics 1. Theycoordinateshouldincreaseandthexcoordinat ...

  8. 学习笔记:Java 并发编程①_基础知识入门

    若文章内容或图片失效,请留言反馈. 部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 视频链接:https://www.bilibili.com/video/av81461839 视频下载: ...

  9. Spring5源码 - 13 Spring事件监听机制_@EventListener源码解析

    文章目录 Pre 概览 开天辟地的时候初始化的处理器 @EventListener EventListenerMethodProcessor afterSingletonsInstantiated 小 ...

最新文章

  1. JS 处理鼠标滚轮事件
  2. 整数划分递归相关问题
  3. C#_获取文件路径中的文件名_扩展名
  4. crosstool-ng 编译交叉工具链的常见错误及解决办法
  5. Java面试题:单例设计模式、适配器模式的不同方式
  6. 浅谈算法和数据结构: 二 基本排序算法
  7. 面试必考:秒杀系统的9个核心知识点,一次性打包给你
  8. 活动验证码/兑换码生成
  9. viper4android最新,蝰蛇音效viper4android rx-ViPER4Android FX开发版下载v2.6.0.2安卓正式版-西西软件下载...
  10. 固定表头和固定列表格解决方案
  11. linux下libreoffice增加字体,Linux下Libreoffice增加字体
  12. c++:过滤多余的空格
  13. form表单内子元素组件按钮button事件冲突 - Vue
  14. 智密-腾讯云直播 MLVB 插件优化教程:六步提升拉流速度+降低直播延迟
  15. 无线攻击及密码破解的四种方式详解
  16. IDEA中WEB项目结构和Artifacts设置
  17. 并行接口电路8255A的基本使用——三种工作方式的时序图的具体讲解
  18. SSM框架和SSH框架的详细对比
  19. 尝试在电脑端使用调试模式修改手机游戏的参数达到外挂效果
  20. 【半导体先进工艺制程技术系列】FinFET和UTB-SOI简介

热门文章

  1. iis下php 500错误
  2. 今天听说了一个压缩解压整型的方式-group-varint
  3. 十进制小数转换二进制的问题
  4. linux运维(五)
  5. JAVA流程控制学习总结
  6. Linux下查看TOMCAT控制台
  7. Oracle 索引的维护
  8. 在 Linux 中使用动态磁盘
  9. 1713. 得到子序列的最少操作次数
  10. leetcode面试题 16.04. 井字游戏