美文网首页
2020-07-14 反射机制原理及使用

2020-07-14 反射机制原理及使用

作者: fjasmin | 来源:发表于2020-07-14 23:27 被阅读0次

最近在研究蓝牙源码时发现,有部分类是被 @hide 掉的,例如 通过蓝牙获取通讯录及通话记录,是通过蓝牙 Pbap 协议,具体实现是在 BluetoothPbapClient 中实现,而该类是 hide 的,注释为当前未完成,后期变动可能会比较大,所以hide掉不会放在 sdk 里使用。

这种情况下,一般是通过修改源码重新编译来实现该需求,不过我为了快速完成需求,考虑使用反射来调用 BluetoothPbapClient 中的接口。

在此记录下反射的使用及原理。

反射,是能够在程序运行时修改程序的行为。

反射的使用

Class

获取 Class

Class 就是一个对象,它用来代表运行在 Java 虚拟机中的类和接口。

获取三种的方式:

student.getClass();

Student.class;

Class.forName("com.xx.Student");

获取 Class 修饰符

TestModifier.class.getModifiers()// 1025

Modifier.toString(TestModifier.class.getModifiers()))// public abstract

Field

获取 Filed

// 获取当前类所有的成员变量,包括私有或者非私有的,不包括从祖先类继承的非私有成员变量

getDeclaredFields();

getDeclaredField(String name);

// 获取所有当前类及从祖先类继承的非私有成员变量

getFields();

getField(String name);// 获取当前类所有的成员变量,包括私有或者非私有的,不包括从祖先类继承的非私有成员变量

getDeclaredFields();

getDeclaredField(String name);

// 获取所有当前类及从祖先类继承的非私有成员变量

getFields();

getField(String name);

获取 Field 的类型

// 该方法可以获取到泛型类型

getGenericType()

getType()

获取Field 修饰符

// 同 Class 获取修饰符

getModifiers()

Field 内容的读取与赋值

// get

publicObjectget(Object obj);

publicintgetInt(Object obj);

publiclonggetLong(Object obj)

throwsIllegalArgumentException, IllegalAccessException;

publicfloatgetFloat(Object obj)

throwsIllegalArgumentException, IllegalAccessException;

publicshortgetShort(Object obj)

throwsIllegalArgumentException, IllegalAccessException;

publicdoublegetDouble(Object obj)

throwsIllegalArgumentException, IllegalAccessException;

publicchargetChar(Object obj)

throwsIllegalArgumentException, IllegalAccessException;

publicbytegetByte(Object obj)

throwsIllegalArgumentException, IllegalAccessException;

publicbooleangetBoolean(Object obj)

throwsIllegalArgumentException, IllegalAccessException

// set

publicvoidset(Object obj, Object value);

publicvoidgetInt(Object obj,intvalue);

publicvoidgetLong(Object obj,longvalue)

throwsIllegalArgumentException, IllegalAccessException;

publicvoidgetFloat(Object obj,floatvalue)

throwsIllegalArgumentException, IllegalAccessException;

publicvoidgetShort(Object obj,shortvalue)

throwsIllegalArgumentException, IllegalAccessException;

publicvoidgetDouble(Object obj,doublevalue)

throwsIllegalArgumentException, IllegalAccessException;

publicvoidgetChar(Object obj,charvalue)

throwsIllegalArgumentException, IllegalAccessException;

publicvoidgetByte(Object obj,byteb)

throwsIllegalArgumentException, IllegalAccessException;

publicvoidgetBoolean(Object obj,booleanb)

throwsIllegalArgumentException, IllegalAccessException

注:在反射中访问了private修饰的成员,需要添加访问权限

fieldb.setAccessible(true);

Method

获取 Method

getDeclaredMethods()

getDeclaredMethod(String name, Class<?>... parameterTypes)

getMethods()

getMethod(String name, Class<?>... parameterTypes)

获取方法参数

publicParameter[] getParameters() {}

publicClass[] getParameterTypes() {}

publicType[] getGenericParameterTypes() {}

Parameter.java:

publicStringgetName(){}

publicClass getType() {}

publicintgetModifiers(){}

获取返回值类型

publicClass getReturnType() {}

// 获取返回值类型包括泛型

publicTypegetGenericReturnType(){}

获取修饰符

// 同 Class

publicintgetModifiers(){}

获取异常类型

publicClass[] getExceptionTypes() {}

publicType[] getGenericExceptionTypes() {}

方法执行

publicObjectinvoke(Object obj, Object... args){}

Constructor

获取 Constructor

注:Constructor 不能从父类继承,所以就没有办法通过 getConstructor() 获取到父类的 Constructor。

getDeclaredConstructors()

getDeclaredConstructor(Class<?>... parameterTypes)

getConstructors()

getConstructor(Class<?>... parameterTypes)

获取对象

在 Java 反射机制中有两种方法可以用来创建类的对象实例:Class.newInstance() 和 Constructor.newInstance()。官方文档建议开发者使用后面这种方法,下面是原因。

Class.newInstance() 只能调用无参的构造方法,而 Constructor.newInstance() 则可以调用任意的构造方法。

Class.newInstance() 通过构造方法直接抛出异常,而 Constructor.newInstance() 会把抛出来的异常包装到 InvocationTargetException 里面去,这个和 Method 行为一致。

Class.newInstance() 要求构造方法能够被访问,而 Constructor.newInstance() 却能够访问 private 修饰的构造器。

反射的原理

java让我们在运行时识别对象和类的信息,主要有2种方式:一种是传统的RTTI(Run-Time Type Identification),它假定我们在编译时已经知道了所有的类型信息,另一种是反射机制。

它允许我们在运行时发现和使用类的信息,也就是这里要说的,通过 Class 类与 reflect 类库一起对反射进行支持,该类库包括 Field、Method 和 Constructor 类。这些类的对象由JVM在启动时创建,用以表示未知类里对应的成员。这样可以使用 Contructor 创建新的对象,用 get() 和 set() 方法获取、修改类中成员等,用 invoke() 调用 Method 对象关联的方法等等。

这样对象信息可以在运行时完全确定下来,而在编译时不需要知道任何关于类的信息。

反射机制并没有很神奇之处,当通过反射对一个未知类型的对象做处理时,JVM只是简单的检查这个对象属于哪个特定的类,因此那个类的 .class 对于JVM是肯定可以获取的。

综上,对于 RTTI 和 反射的区别只在于:

.RTTI 是编译器在编译时打开和检查 .class 文件

.反射 是在运行时打开和检查 .class 文件

相关文章

  • 2020-07-14 反射机制原理及使用

    最近在研究蓝牙源码时发现,有部分类是被 @hide 掉的,例如 通过蓝牙获取通讯录及通话记录,是通过蓝牙 Pbap...

  • iOS底层学习文章

    iOS黑魔法-Method Swizzling Objective-C 反射机制 KVC原理剖析 KVO原理分析及...

  • Java基本知识

    java反射机制 大白话说Java反射:入门、使用、原理[https://www.cnblogs.com/chan...

  • OC的反射机制

    目录 1 反射机制的概念 2 反射机制原理 首先还是按照惯例和大家解释下什么反射机制? 反射的概念是由Smith在...

  • 【反射机制】Java反射机制原理和基本使用

    1、概况: 是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意...

  • 2019自己遇到的面试题(java后端)

    voliatle 原理及特性 spring ioc 含义及使用 spring aop 变成含义及使用 gc机制 s...

  • Java笔记之——反射

    这篇文章来谈谈Java基础——反射的内容。主要通过以下几点进行介绍:反射机制、反射的使用及有关反射的API。 一、...

  • Chapter 13 . 反射机制

    阅读原文 Chapter 13 . 反射机制 13.1 Java反射机制研究及应用 Java Reflection...

  • Java 反射 reflection

    spring源代码,其基本原理如依赖注入、aop、以及xml技术,动态反射机制 Reflection 学习反射原理...

  • Java反射机制及API使用

    原文地址 反射简单来说,就是动态加载对象,并对对象进行剖析。在Java中的反射机制是指在运行状态中,对于任意一个类...

网友评论

      本文标题:2020-07-14 反射机制原理及使用

      本文链接:https://www.haomeiwen.com/subject/psoqhktx.html