反射的概念

  • java的放射机制:在程序运行时,程序有能力获取一个类的所有方法和属性;并且对于任意一个对象,可以调用它的任意方法或者获取其属性
  • 通俗解析:java文件需要编译成.class文件才能被jvm加载使用,对象的.class数据在jvm里就是Class<T>;我们如果能拿到这个Class<T>对象,

    就能获取该Class<T>对应的对象类型,及在该类型声明的方法和属性值;还可以根据Class<T>创建相应的类型对象,通过Field,Method反过来操作对象
  • java相关类介绍
类名 描述
Class<T> 代表类的实体,在运行的Java应用程序中表示类或者接口
Field 类的成员变量(成员变量也称为类的属性)
Method 类的方法
Constructor<T> 类的构造方法

获取Class的三种方法

  • 1通过已知的类型获取class
  1. // 根据Example 获取Class =》Example.class
  2. public Class<Example> getExample(){
  3. Class<Example> clazz = Example.class;
  4. return clazz;
  5. }
  • 2通过实例对象获取class
  1. public Class<Example> getExampleByInstance(){
  2. Example example = new Example();
  3. // getClass是Object类里面的方法;《?》 是通配符
  4. Class<?> clazz = example.getClass();
  5. return (Class<Example>)clazz;
  6. }
  • 3通过Class.forName获取全路径指定类名的class
  1. /** forName0 本地方法,C++实现,jvm调用
  2. * 1 className 是个类名 2 initialize 是否延迟加载 3 loader 加载器
  3. */
  4. private static native Class<?> forName0(String className, boolean initialize,
  5. ClassLoader loader, Class<?> caller) throws ClassNotFoundException;
  6. public static Class<?> forName(String className) throws ClassNotFoundException {
  7. Class<?> caller = Reflection.getCallerClass();
  8. return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
  9. }
  10. // 两个forName方法最终都会调用forName0方法去加载class
  11. public static Class<?> forName(String name,
  12. boolean initialize, ClassLoader loader) throws ClassNotFoundException {
  13. ....
  14. return forName0(name, initialize, loader, caller);
  15. }
  1. // 示例:通过java.lang.Integer
  2. public Class<Integer> getInteger()throws ClassNotFoundException{
  3. Class<?> clazz = Class.forName("java.lang.Integer");
  4. return (Class<Integer>)clazz;
  5. }

JAVA反射API

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

反射机制应用的场景

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

反射和JDK动态代理

  • 在Java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口。通过这个类和接口可以生成JDK动态代理类或动态代理对象
  1. public interface InvocationHandler {
  2. //所有方法都会调用此代理方法
  3. Object invoke(Object var1, Method var2, Object[] var3) throws Throwable;
  4. }  
  5. public class Proxy implements Serializable
  6. ...
  7. //根据interfaces和InvocationHandler生成代理对象
  8. public static Object newProxyInstance(ClassLoader loader,
  9. Class<?>[] interfaces, InvocationHandler h)
  10. ...

  • JDK的动态代理由Proxy和InvocationHandler实现;而被代理对象必须实现一个接口。代理对象由Proxy生成,可转为接口interface的实现类对象OBJ。当调用OBJ的方法时,则会触发InvocationHandler.invoke,参数依次为代理对象Method对象,和方法Method所需的参数。在invoke方法可以加入拓展的逻辑,如日志记录操作;并可以在invoke里利用反射的技术调用 被代理对象方法
  • 示例
  1. public class ExampleFactory<T> implements InvocationHandler{
  2. private T target;
  3. public T bind(T obj){
  4. target = obj;
  5. return (T)Proxy.newProxyInstance(obj.getClass().getClassLoader(),
  6. obj.getClass().getInterfaces(),this);
  7. }
  8. @Override
  9. public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
  10. //增强逻辑
  11. System.out.println("log start");
  12. //反射调用被代理对象方法
  13. Object result = method.invoke(target,objects);
  14. System.out.println("log end");
  15. return result;
  16. }
  17. }
  18. -----------
  19. public interface Face {
  20. void hello(String name);
  21. }
  22. ---------
  23. //被代理对象必须实现一个接口,并由接口方法对方提供功能
  24. public class Example implements Face {
  25. public void hello(String name) {
  26. System.out.println(name + " Hello!");
  27. }
  28. public static void main(String[] args) {
  29. //ExampleFactory<Face> 相当于一个中介人
  30. ExampleFactory<Face> factory = new ExampleFactory<>();
  31. //example 是代理对象
  32. Face example = exampleProxy.bind(new Example());
  33. example.hello("思婷");
  34. }
  35. }
  36. -----
  37. log start
  38. 思婷 Hello!
  39. log end

欢迎指正文中错误

关注公众号,一起交流

参考文章

基础篇:深入解析JAVA反射机制的更多相关文章

  1. Java 基础之详解 Java 反射机制

    一.什么是 Java 的反射机制?   反射(Reflection)是Java的高级特性之一,是框架实现的基础,定义:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: ...

  2. 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制

    你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...

  3. Java开发培训基础知识解析之反射机制

    Java是老牌编程语言,是当前应用最广泛的编程语言之一.想要学习Java你就一定要掌握Java基础知识,而反射对于初学Java的人来说绝对是非常重要的知识点.什么是反射?如何理解反射机制?如何使用反射 ...

  4. 深入解析Java反射(1) - 基础

    深入解析Java反射(1) - 基础 最近正筹备Samsara框架的开发,而其中的IOC部分非常依靠反射,因此趁这个机会来总结一下关于Java反射的一些知识.本篇为基本篇,基于JDK 1.8. 一.回 ...

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

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

  6. java反射机制(基础版)

    package com.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import ja ...

  7. 深入解析Java反射基础

    博客原文:http://www.sczyh30.com/posts/Java/java-reflection-1/ - 这老哥写的特别好 一.回顾:什么是反射? 反射(Reflection)是Java ...

  8. 【java基础】Java反射机制

    一.预先需要掌握的知识(java虚拟机)  1)java虚拟机的方法区:  java虚拟机有一个运行时数据区,这个数据区又被分为方法区,堆区和栈区,我们这里需要了解的主要是方法区.方法区的主要作用是存 ...

  9. Java反射机制(Reflect)解析-----https://www.cnblogs.com/fzz9/p/7738381.html

    Java反射机制(Reflect)解析-----https://www.cnblogs.com/fzz9/p/7738381.html

随机推荐

  1. JVM大作业5——指令集

    JVM的每一个线程都有一个虚拟机栈,方法调用时,JVM会在虚拟机栈内为该方法创建一个栈帧. 一条线程,只有正在执行的方法对应的栈帧时可活动的,这个栈帧被称为当前栈帧,当前栈帧对应的方法被称为当前方法, ...

  2. 一张图对比React、Angular、Vue.js

    文章原文地址:https://baijiahao.baidu.com/s?id=1609374985643812253&wfr=spider&for=pc

  3. laravel中elastisearch安装和测试运行是否成功(注意是windows下的操作)

    1.去elasticsearch官网下载,如果太慢可以在我上一个随笔看下载地址 2.下载完解压缩,在cmd中找到到elasticsearch的bin目录下执行.\elasticsearch.bat - ...

  4. Android开发之Eclipse与Android Studio的java类 作者版权模板

    /** * 作者:${USER} on ${DATE} ${HOUR}:${MINUTE} * * 联系QQ:986945193 * * 微博:http://weibo.com/mcxiaobing ...

  5. 攻防世界——web新手练习区解题总结<2>(5-8题)

    第五题cookie: 所需工具:burpsuite(需自行下载) 老规矩看完题,先获取在线场景,得到如下网页 那么什么是cookie呢?大体上就是网站为了识别用户身份而储存在用户本地终端上的数据,类型 ...

  6. bzoj1590 Secret Message

    Description 贝茜正在领导奶牛们逃跑.为了联络,奶牛们互相发送秘密信息. 信息是二进制的,共有M(1≤M≤50000)条.反间谍能力很强的约翰已经部分拦截了这些信息,知道了第i条二进制信息的 ...

  7. python3笔记-字典

    5 1 # 创建字典 6 2 d=dict(name='lily',age=18,phone='') 7 3 print(d) 4 # {'name': 'lily', 'age': 18, 'pho ...

  8. Git在windows上的设置详解

    这几天在学习使用Git版本管理工具,发现期间的各种配置还是挺繁琐的,而且好多命令的确记不住,于是写个blog记录下来,方便以后查阅. 1. 首先到GitHub官网上下载最新的Git,然后装上,装的过程 ...

  9. hdu6704 2019CCPC网络选拔赛1003 K-th occurrence 后缀数组

    题意:给你一个长度为n的字符串,有q个询问,每次询问一个子串s(l,r)第k次出现的位置,若子串出现次数少于k次输出-1. 解题思路:先把SA跑出来,然后对于每次询问可以由l和rank[]找到l在所有 ...

  10. 阿里面试:dubbo的服务引用过程

    点赞再看,养成习惯,微信搜一搜[三太子敖丙]关注这个喜欢写情怀的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系 ...