Java随笔(5):反射API梳理

来源:互联网 发布:新日铁软件 张涛 编辑:程序博客网 时间:2024/06/05 08:59

转载请注意:http://blog.csdn.net/wjzj000/article/details/54179894
本菜开源的一个自己写的Demo,希望能给Androider们有所帮助,水平有限,见谅见谅…
https://github.com/zhiaixinyang/PersonalCollect (拆解GitHub上的优秀框架于一体,全部拆离不含任何额外的库导入)
https://github.com/zhiaixinyang/MyFirstApp(Retrofit+RxJava+MVP)


写在前面

因为水品有限接触到反射的地方基本上都是跟随着注解一起使用。所以今天从JDK API中把反射的一些内容梳理出来,留作记录。
之前写过的一些注解相关的内容,如果各位看官感兴趣可以去瞅上那么一瞅。
http://blog.csdn.net/wjzj000/article/details/54177914
http://blog.csdn.net/wjzj000/article/details/53227352


API概要

以下概述直接来自于Class这个类的API,当然专注于反射类的Constructor也有与之相类似的方法,基本上可以互相对应。

  • 对Class简单的获取信息
Class<? extends U> asSubclass(Class<U> clazz) 强制转换该 Class 对象,以表示指定的 class 对象所表示的类的一个子类。 T cast(Object obj) 将一个对象强制转换成此 Class 对象所表示的类或接口。 static Class<?> forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象。 static Class<?> forName(String name, boolean initialize, ClassLoader loader) 使用给定的类加载器,返回与带有给定字符串名的类或接口相关联的 Class 对象。 Constructor<T> getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 Constructor<?>[] getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。 
  • 注解相关
<A extends Annotation> A getAnnotation(Class<A> annotationClass) 如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。 Annotation[] getAnnotations() 返回此元素上存在的所有注释。 String getCanonicalName() 返回 Java Language Specification 中所定义的底层类的规范化名称。 Class<?>[] getClasses() 返回一个包含某些 Class 对象的数组,这些对象表示属于此 Class 对象所表示的类的成员的所有公共类和接口。 ClassLoader getClassLoader() 返回该类的类加载器。 Class<?> getComponentType() 返回表示数组组件类型的 Class。 
  • 获取对应方法
Method getMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 Method[] getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。 Class<?>[] getDeclaredClasses() 返回 Class 对象的一个数组,这些对象反映声明为此 Class 对象所表示的类的成员的所有类和接口。Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。 Constructor<?>[] getDeclaredConstructors() 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。 Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。Method[] getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 Class<?> getDeclaringClass() 如果此 Class 对象所表示的类或接口是另一个类的成员,则返回的 Class 对象表示该对象的声明类。 
  • 获取字段
Field getField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 Field[] getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。 Field getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 Field[] getDeclaredFields() 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。 Type[] getGenericInterfaces() 返回表示某些接口的 Type,这些接口由此对象所表示的类或接口直接实现。 
  • 获取接口以及简单信息
Class<?>[] getInterfaces() 确定此对象所表示的类或接口实现的接口。 String getName() 以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。 Package getPackage() 获取此类的包。 Class<? super T> getSuperclass() 返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。 TypeVariable<Class<T>>[] getTypeParameters() 按声明顺序返回 TypeVariable 对象的一个数组,这些对象表示用此 GenericDeclaration 对象所表示的常规声明来声明的类型变量。 boolean isAnnotation() 如果此 Class 对象表示一个注释类型则返回 true

API官方翻译

  • forName()
public static Class<?> forName(String className) throws ClassNotFoundException    返回与带有给定字符串名的类或接口相关联的 Class 对象。调用此方法等效于:         Class.forName(className, true, currentLoader)    其中 currentLoader 表示当前类的定义类加载器。     例如,以下代码片段返回命名为 java.lang.Thread 的类的运行时 Class 描述符。         Class t = Class.forName("java.lang.Thread")    调用 forName("X") 将导致命名为 X 的类被初始化。 参数:    className - 所需类的完全限定名。 返回:    具有指定名的类的 Class 对象。 抛出:     LinkageError - 如果链接失败     ExceptionInInitializerError - 如果此方法所激发的初始化失败     ClassNotFoundException - 如果无法定位该类

  • getConstructor()
public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException    返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。    parameterTypes 参数是 Class 对象的一个数组,这些 Class 对象按声明顺序标识构造方法的形参类型。     如果此 Class 对象表示非静态上下文中声明的内部类,则形参类型作为第一个参数包括显示封闭的实例。     要反映的构造方法是此 Class 对象所表示的类的公共构造方法,其形参类型与 parameterTypes 所指定的参数类型相匹配。 参数:    parameterTypes - 参数数组 返回:    与指定的 parameterTypes 相匹配的公共构造方法的 Constructor 对象 抛出:     NoSuchMethodException - 如果找不到匹配的方法。     SecurityException - 如果存在安全管理器 s,并满足下列任一条件:     调用 s.checkMemberAccess(this, Member.PUBLIC) 拒绝访问构造方法     调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

  • getDeclaredConstructor()
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException,SecurityException    返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。    如果此 Class 对象表示非静态上下文中声明的内部类,则形参类型作为第一个参数包括显示封闭的实例。 参数:    parameterTypes - 参数数组 返回:    带有指定参数列表的构造方法的 Constructor 对象 抛出:     NoSuchMethodException - 如果找不到匹配的方法。     SecurityException - 如果存在安全管理器 s,并满足下列任一条件:     调用 s.checkMemberAccess(this, Member.DECLARED) 拒绝访问已声明的构造方法     调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

  • getDeclaredClasses()
public Class<?>[] getDeclaredClasses() throws SecurityException    返回 Class 对象的一个数组,这些对象反映声明为此 Class 对象所表示的类的成员的所有类和接口。    包括该类所声明的公共、保护、默认(包)访问及私有类和接口,但不包括继承的类和接口。    如果该类不将任何类或接口声明为成员,或者此 Class 对象表示基本类型、数组类或 void,则此方法返回一个长度为 0 的数组。 返回:    Class 对象的数组,表示该类的所有 declared 成员 抛出:     SecurityException - 如果存在安全管理器 s,并满足下列任一条件:     调用 s.checkMemberAccess(this, Member.DECLARED) 拒绝访问此类中已声明的类     调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问此类的包 

  • getDeclaredFields()
public Field[] getDeclaredFields() throws SecurityException    返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。    包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。    返回数组中的元素没有排序,也没有任何特定的顺序。如果该类或接口不声明任何字段,或者此 Class 对象表示一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组。 返回:    表示此类所有已声明字段的 Field 对象的数组 抛出:     SecurityException - 如果存在安全管理器 s,并满足下列任一条件:     调用 s.checkMemberAccess(this, Member.DECLARED) 拒绝访问此类中已声明的字段     调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

  • getDeclaredMethods()
public Method[] getDeclaredMethods() throws SecurityException    返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。    返回数组中的元素没有排序,也没有任何特定的顺序。如果该类或接口不声明任何方法,或者此 Class 对象表示一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组。    类初始化方法 <clinit> 不包含在返回数组中。如果该类声明带有相同参数类型的多个公共成员方法,则它们都包含在返回的数组中。 返回:    表示此类所有声明方法的 Method 对象的数组 抛出:     SecurityException - 如果存在安全管理器 s,并满足下列任一条件:     调用 s.checkMemberAccess(this, Member.DECLARED) 拒绝访问该类中已声明的方法     调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

  • getMethod()
public Method getMethod(String name,Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
    返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。    name 参数是一个 String,用于指定所需方法的简称。parameterTypes 参数是按声明顺序标识该方法形参类型的 Class 对象的一个数组。如果 parameterTypes 为 null,则按空数组处理。     如果 name 是 "<init>;""<clinit>",则将引发 NoSuchMethodException。否则,要反映的方法由下面的算法确定(设 C 为此对象所表示的类):     在 C 中搜索任一匹配的方法。如果找不到匹配的方法,则将在 C 的超类上递归调用第 1 步算法。 如果在第 1 步中没有找到任何方法,则在 C 的超接口中搜索匹配的方法。如果找到了这样的方法,则反映该方法。     在 C 类中查找匹配的方法:如果 C 正好声明了一个具有指定名称的公共方法并且恰恰有相同的形参类型,则它就是反映的方法。如果在 C 中找到了多个这样的方法,并且其中有一个方法的返回类型比其他方法的返回类型都特殊,则反映该方法;否则将从中任选一个方法。     注意,类中可以有多个匹配方法,因为尽管 Java 语言禁止类声明带有相同签名但不同返回类型的多个方法,但 Java 虚拟机并不禁止。这增加了虚拟机的灵活性,可以用来实现各种语言特性。例如,可以使用桥方法 (brige method)实现协变返回;桥方法以及将被重写的方法将具有相同的签名,不同的返回类型。参数:    name - 方法名    parameterTypes - 参数列表 返回:    与指定的 name 和 parameterTypes 匹配的 Method 对象 抛出:     NoSuchMethodException - 如果找不到匹配的方法,或者方法名为 "<init>""<clinit>"     NullPointerException - 如果 name 为 null     SecurityException - 如果存在安全管理器 s,并满足下列任一条件:     调用 s.checkMemberAccess(this, Member.PUBLIC) 拒绝访问方法     调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

  • Constructor中newInstance
public T newInstance(Object... initargs) throws InstantiationException,                                                 IllegalAccessException,                                                 IllegalArgumentException,                                                 InvocationTargetException    使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。个别参数会自动解包,以匹配基本形参,必要时,基本参数和引用参数都要进行方法调用转换。     如果底层构造方法所需形参数为 0,则所提供的 initargs 数组的长度可能为 0 或 null。     如果构造方法的声明类是非静态上下文的内部类,则构造方法的第一个参数需要是封闭实例;请参阅Java 语言规范 第 15.9.3 节。     如果所需的访问检查和参数检查获得成功并且实例化继续进行,这时构造方法的声明类尚未初始化,则初始化这个类。     如果构造方法正常完成,则返回新创建且已初始化的实例。 参数:    initargs - 将作为变量传递给构造方法调用的对象数组;基本类型的值被包装在适当类型的包装器对象(如 Float 中的 float)中。 返回:    通过调用此对象表示的构造方法来创建的新对象 抛出:     IllegalAccessException - 如果此 Constructor 对象实施 Java 语言访问控制并且底层构造方法是不可访问的。     IllegalArgumentException - 如果实参和形参的数量不同;如果基本参数的解包转换失败;如果在可能的解包后,无法通过方法调用转换将参数值转换为相应的形参类型;如果此构造方法属于枚举类型。     InstantiationException - 如果声明底层构造方法的类表示抽象类。     InvocationTargetException - 如果底层构造方法抛出异常。     ExceptionInInitializerError - 如果此方法引发的初始化失败。
  • 从文档中看这些玩意真的很无聊,所以:

插一个小Demo

public class Reflect{    public static void main(String[] args) {        try {            //加载类。还有俩个其他方法,分别为:1,Money money=new money().getClass();2,Money money=Money.class;            Class class_=Class.forName("test.Money");            //获得带参数的构造方法。            Constructor c = class_.getDeclaredConstructor(new Class[]{int.class,String.class });            //实例化这个类,调用了俩个参数的构造方法。            Money money= (Money) c.newInstance(11,"aa");            Method method = class_.getDeclaredMethod("privateTest");            // 由于调用的方法是 private的,所以需要屏蔽Java语言的访问检查            method.setAccessible(true);            //调用方法            method.invoke(money);    }    //省略很多异常处理}
  • Money类很简单,但是里边很多方法说实话上述的反射也没有调用,就是调用里其中的一个私有方法。
public class Money {    private int amount;// 余额    private String name;// 货币类型    public Money(int amount, String currency) {        this.amount = amount;        name = currency;    }    public Money(){}    public int getAmount() {        return amount;    }    public void setAmount(int amount) {        this.amount = amount;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    private void privateTest(){        System.out.println("我是私有方法中的属性。");    }}

尾声

先记到这,下次结合框架继续梳理。拜拜了您呐~

最后希望各位看官可以star我的GitHub,三叩九拜,满地打滚求star:
https://github.com/zhiaixinyang/PersonalCollect
https://github.com/zhiaixinyang/MyFirstApp

1 0
原创粉丝点击