java 反射机制_基础篇:深入解析JAVA反射机制

88865cd1a956e36a1cf233252c79e9ab.gif

362414cdf445cefd39f997f8f3440672.png

反射的概念

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

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

  • java 相关类介绍

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

获取 Class 的三种方法

  • 1 通过已知的类型获取 class
// 根据Example 获取Class =》Example.class
public 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 public
public Constructor\[\] getDeclaredConstructors()
//获取特定的构造方法 / private public
public 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
// 根据属性命名获得特定的Field
public Field getField(String name) 
  • Method 常用的操作方法
//获得方法的放回类型
public Class getReturnType()   
//获得方法的传入参数类型
public Class\[\] getParameterTypes()   
//obj是实例对象,args是方法,反过来由Method控制对象的方法调用
public Object invoke(Object obj, Object... args)
  • Field 常用的操作方法
//属性与obj相等则返回true
public 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

欢迎指正文中错误

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/396703.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

构建之法阅读笔记01

本学期阅读计划有两个&#xff0c;一个是《构建之法》&#xff0c;另一个是《大道至简》。 在快速阅读构建之法后&#xff0c;我想提一下几个问题&#xff1a; 1、软件程序软件工程&#xff0c;那么只会软件工程是怎样具体详细的将程序变成合格的软件的&#xff1f; 2、效能分析…

html div float center,跨浏览器实现float:center

跨浏览器实现float:center互联网 发布时间&#xff1a;2008-10-17 19:26:11 作者&#xff1a;佚名 我要评论原文&#xff1a;http://www.macji.com/blog/article/to-achieve-cross-browser-css-float-center/to-achieve-cross-browser-css-float-center/我们都知道float…

博弈论中:纳什均衡、纯策略纳什均衡、混合策略纳什均衡、占优策略

纳什均衡 纳什均衡是由约翰福布斯纳什&#xff08;John Forbes Nash&#xff09;在20世纪50年代提出的博弈论概念&#xff0c;用于描述博弈中的一种稳定状态。在纳什均衡状态下&#xff0c;每个参与者都假定其他参与者的策略是已知的&#xff0c;他们选择的策略是最优的&#…

工具_HBuilder使用快捷方式

HBuilder常用快捷键大概共9类&#xff08;【4 13 3】文件、编辑、插入&#xff1b;【4 9 8】选择、跳转、查找&#xff1b;【1 1 6】运行、工具、视图&#xff09; 1.文件(4) 新建 Ctrl N 关闭 Ctrl F4 全部关闭 Ctrl Shift F4 属性 Alt Enter 2.编辑(13) 激活代码助…

oracle左连接没用_一周零基础学完Oracle数据库第三天02

四、 多表查询1 什么是多表查询多表查询&#xff1a;当查询的数据并不是来源一个表时&#xff0c;需要使用多表链接操作完成查询。根据 不同表中的数据之间的关系查询相关联的数据。多表链接方式&#xff1a; 内连接&#xff1a;连接两个表&#xff0c;通过相等或不等判断链接列…

weblogic启动项目报错找不到类_启动类报错是经常出现的事但是单一的从一个地方找原因会越找越错...

Error starting ApplicationContext. To display the conditions report rerun your application with debug enabled.当我们看到这个报错的时候有的说是jar包重复&#xff0c;有的说是Controller包和Application包处于平行位置&#xff0c;还有的觉得是RequestMapping的valu…

fis

fis3实时刷新 npm install -g fis3 进入相关目录 发布&#xff1a; fis3 release 启动&#xff1a; fis3 server start // 服务启动后&#xff0c;会一直存在&#xff0c;重启或者fis3 server stop 才会关闭服务 自动刷新 fis3 release -wL关闭服务 fis3 server stop …

深入理解javascript原型和闭包(7)——原型的灵活性

在Java和C#中&#xff0c;你可以简单的理解class是一个模子&#xff0c;对象就是被这个模子压出来的一批一批月饼&#xff08;中秋节刚过完&#xff09;。压个啥样&#xff0c;就得是个啥样&#xff0c;不能随便动&#xff0c;动一动就坏了。 而在javascript中&#xff0c;就没…

微型计算机一般不采用的控制方式,微型计算机控制作业.doc

作业一PID控制器引言在实际的过程控制与运动控制系统中&#xff0c;PID家族占据有相当的地位&#xff0c;据统计&#xff0c;工业控制的控制器中PID类控制占有90%以上。PID控制器是最早出现的控制器类型&#xff0c;因为其结构简单&#xff0c;各个控制器参数有着明显的物理意义…

js根据毫米/厘米算像素px

<html><meta http-equiv"content-type" content"text/html;charsetutf-8"><body> 纸张宽度(毫米mm)&#xff1a;<input type"text" id"width" value"10"> <span id"width_px"><…

c语言为什么有这么多的编程环境?_为什么98%的程序员学编程都会从C语言开始?...

在互联网蓬勃发展的时代&#xff0c;有一类人做出了巨大的贡献&#xff0c;这一群人被大家称之为程序员&#xff0c;怎样才能成为一名优秀的程序员呢&#xff0c;为什么每一个程序员都需要学习C语言呢&#xff1f;就让我来跟大家分享分享&#xff1a;壹第一&#xff1a;相比较其…

怎么把电脑上的python软件卸载干净_怎么把一个软件卸载干净_把一个软件卸载干净的两种方法-系统城...

平时使用电脑肯定有卸载软件的操作&#xff0c;一般人直接用户桌面的快捷方式删除&#xff0c;表示软件已经卸载干净了&#xff0c;因为在桌面已经看不见了。其实大部分都没有卸载干净&#xff0c;如果没卸载干净&#xff0c;下载就无法安装了&#xff0c;因为之前还有残留文件…

2.x最终照着教程,成功使用OpenGL ES 绘制纹理贴图,添加了灰度图

在之前成功绘制变色的几何图形之后&#xff0c;今天利用Openg ES的可编程管线绘制出第一张纹理。学校时候不知道OpenGL的重要性&#xff0c;怕晦涩的语法。没有跟老师学习OpenGL的环境配置&#xff0c;现在仅仅能利用cocos2dx 2.2.3 配置好的环境学习OpenGL ES。源码来自《coco…

C# Dapper 简单实例

/// <summary>/// 分页信息/// </summary>public class PageInfo<T>{/// <summary>/// 分页信息/// </summary>public PageInfo(){}/// <summary>/// 总页数/// </summary>public long TotalCount{get; set;}/// <summary>///…

Angular 星级评分组件

一、需求演变及描述&#xff1a; 1. 有一个“客户对公司的总体评价”的字段&#xff08;evalutation&#xff09;。字段为枚举类型&#xff0c;0-5&#xff0c;对应关系为&#xff1a;0-暂无评价&#xff0c;1-很差&#xff0c;2-差&#xff0c;3-一般&#xff0c;4-好&#xf…

计算机网络怎么查看连接打印机驱动,如何检测网络打印机是否已成功连接到计算机[检测方法]...

大概很多婴儿都像以前的编辑一样. 使用网络打印机时&#xff0c;有时它们可​​以打印打印机没有和电脑连接&#xff0c;有时却不能. 那么如何检测网络打印机是否已成功连接到计算机&#xff1f;跟随编辑器往下看.系统反复提示“无法打印”&#xff0c;因此本来很忙的小修几乎快…

eclipse python插件_pydev插件下载-eclipse中的python插件下载6.0.0 官网最新版-西西软件下载...

在eclipse中安装python所需的插件。PyDev for Eclipse 是一个功能强大且易用的 Eclipse Python IDE 插件。利用 PyDev 插件把 Eclipse 变为功能强大且易用的 Python IDE&#xff0c;如何利用其进行 Python 程序的开发和调试。安装方法&#xff1a;一种比较随意的方法就是把压缩…

a - 数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历_数据结构--图

故事凌 今天基本知识点图可说是所有数据结构里面知识点最丰富的一个, 自己笨的知识点如下:阶(oRDER), 度: 出度(out-Degree), 入度(in-Degree)树(Tree), 森林(Forest), 环(Loop)有向图(Directed Graph), 无向图(Undirected Graph), 完全有向图, 完全无向图连通图(Connected Gra…

vim: vimrc

2019独角兽企业重金招聘Python工程师标准>>> 打造vim CIDE http://blog.csdn.net/doc_sgl/article/details/47205779 转载于:https://my.oschina.net/u/2528742/blog/843176

计算机二级考试试题在线看,【TOP182015年全国计算机二级考试试题题库.doc文档免费在线阅读材料】...

TOP182015年全国计算机二级考试试题题库.doc文档免费在线阅读《2015年全国计算机二级考试试题题库.doc》由会员分享&#xff0c;可免费在线阅读全文&#xff0c;更多与《TOP182015年全国计算机二级考试试题题库.doc文档免费在线阅读》相关文档资源请在帮帮文库(www.woc88.com)数…