Java无所不能的反射在Android中须要熟练的知识

什么是反射?

反射 (Reflection) 是 Java 的特征之一,它容许运行中的 Java 程序获取自身的信息,而且能够操做类或对象的内部属性 简而言之,经过反射,咱们能够在运行时得到程序或程序集中每个类型的成员和成员的信息。程序中通常的对象的类型都是在编译期就肯定下来的,而 Java 反射机制能够动态地建立对象并调用其属性,这样的对象的类型在编译期是未知的。因此咱们能够经过反射机制直接建立对象,即便这个对象的类型在编译期是未知的。 反射的核心是 JVM 在运行时才动态加载类或调用方法/访问属性,它不须要事先(写代码的时候或编译期)知道运行对象是谁。 Java 反射主要提供如下功能:java

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具备的成员变量和方法(经过反射甚至能够调用private方法);
  • 在运行时调用任意一个对象的方法 重点:是运行时而不是编译时

反射的运用

得到 Class 对象

  • 使用 Class 类的 forName 静态方法
public static Class<?> forName(String className)
复制代码
  • 直接获取某一个对象的 class
Class<?> klass = int.class;
Class<?> classInt = Integer.TYPE;
复制代码
  • 调用某个对象的 getClass() 方法
StringBuilder str = new StringBuilder("123");
Class<?> klass = str.getClass();
复制代码

判断是否为某个类的实例

通常地,咱们用 instanceof 关键字来判断是否为某个类的实例。同时咱们也能够借助反射中 Class 对象的 isInstance() 方法来判断是否为某个类的实例,它是一个 native 方法:面试

public native boolean isInstance(Object obj);
复制代码

建立实例

经过反射来生成对象主要有两种方式。数组

  • 使用Class对象的newInstance()方法来建立Class对象对应类的实例。
Class<?> c = String.class;
Object str = c.newInstance();
复制代码
  • 先经过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来建立实例。这种方法能够用指定的构造器构造类的实例。
//获取String所对应的Class对象
Class<?> c = String.class;
//获取String类带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//根据构造器建立实例
Object obj = constructor.newInstance("23333");
System.out.println(obj);
复制代码

获取构造器信息

获得构造器的方法安全

Constructor getConstructor(Class[] params) -- 得到使用特殊的参数类型的公共构造函数, 
Constructor[] getConstructors() -- 得到类的全部公共构造函数 
Constructor getDeclaredConstructor(Class[] params) -- 得到使用特定参数类型的构造函数(与接入级别无关) 
Constructor[] getDeclaredConstructors() -- 得到类的全部构造函数(与接入级别无关)
复制代码

获取类构造器的用法与上述获取方法的用法相似。主要是经过Class类的getConstructor方法获得Constructor类的一个实例,而Constructor类有一个newInstance方法能够建立一个对象实例:bash

public T newInstance(Object ... initargs)
复制代码

获取类的成员变量(字段)信息

得到字段信息的方法微信

Field getField(String name) -- 得到命名的公共字段 
Field[] getFields() -- 得到类的全部公共字段 
Field getDeclaredField(String name) -- 得到类声明的命名的字段 
Field[] getDeclaredFields() -- 得到类声明的全部字段 
复制代码

调用方法

得到方法信息的方法架构

Method getMethod(String name, Class[] params) -- 使用特定的参数类型,得到命名的公共方法 
Method[] getMethods() -- 得到类的全部公共方法 
Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,得到类声明的命名的方法 
Method[] getDeclaredMethods() -- 得到类声明的全部方法 
复制代码

当咱们从类中获取了一个方法后,咱们就能够用 invoke() 方法来调用这个方法。invoke 方法的原型为:函数

public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
复制代码

利用反射建立数组

数组在Java里是比较特殊的一种类型,它能够赋值给一个Object Reference 其中的Array类为java.lang.reflect.Array类。咱们经过Array.newInstance()建立数组对象,它的原型是:ui

public static Object newInstance(Class<?> componentType, int length)
        throws NegativeArraySizeException {
        return newArray(componentType, length);
    }
复制代码

newArray 方法是一个 native 方法,它在 HotSpot JVM 里的具体实现咱们后边再研究,这里先把源码贴出来:spa

private static native Object newArray(Class<?> componentType, int length)
        throws NegativeArraySizeException;
复制代码

注意事项

  • 反射会额外消耗必定的系统资源,所以若是不须要动态地建立一个对象,那么就不须要用反射
  • 反射调用方法时能够忽略权限检查,所以可能会破坏封装性而致使安全问题

最后

读到这的朋友以为不错能够点赞关注下,感谢您的支持,之后会不停更新更多精选干货及资讯分享,欢迎你们在评论区留言讨论!

欢迎关注享学课堂online微信公众号,天天会持续更新技术干货,热点,吐槽等文章,还有免费的Android架构视频资料和面试专题资料免费领取分享,后台回复关键字【Android资料】,免费获取Android架构面试专题文档资料、电子书及更多架构进阶视频资料(视频+笔记)

相关文章
相关标签/搜索