zoukankan      html  css  js  c++  java
  • Java 反射 Class类

    Java 反射 Class类

    @author ixenos

     摘要:Class类在反射中的地位、构造Class对象的三种方式、Class对象构造对应类型对象的三种方式

    Class类在反射中的地位 


     位于java.lang下的Class类是位于java.lang.reflect下的Constructor类、Method类、Field类和Array类的入口类

    -Class类  代表一个类

    -Field类  代表类的成员变量(也成为类的属性、域)

    -Array类  提供了动态创建数组、以及访问数组元素的静态方法

    -Method类  代表类的方法

    -Constructor类  代表类的构造方法

    构造Class对象的三种方式


     0.前言

    为了使用类而做的准备工作包括三个步骤:

    1)加载类加载器查找字节码(一般在classpath中找),从字节码创建一个Class对象

    2)链接:验证字节码,为静态域(只是static修饰的域,不包含static final )分配存储空间,解析此类对其他类的所有引用

    3)初始化:若该类有超类,对其初始化,执行静态初始化器静态初始化块。这是对类的初始化

    -----------------------------

    ***static final int = 47 是编译期常量,不需要对类进行初始化就可以读取

    ***static final int = Random.nextInt(100)  是运行时常量,这种一般要在对象创建后才会运行,超过初始化的阶段了!

    ***static int = 47 是非常数的静态域,不是常量,更不是编译期常量,链接阶段只分配存储空间,初始化阶段才初始化

    1.Class类的forName静态方法(自动初始化)

    只知道对应类型名时,使用Class.forName(String name) 动态生成Class<String>对象,name是完全限定名

    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 - 如果无法定位该类
    API文档描述

    2.Object类对象自带getClass方法(已经初始化)

    通过已经存在的对象,即持有对应类型对象的引用时使用对象的getClass()(属于根类Object的一部分),如new Integer(1).getClass()将返回Integer.class,而此时的类型对象也必定是在运行中了,所以已经初始化

    3.使用类字面常量(不会自动初始化)

    例如 Fancy.class、String.class、Integer.TYPE

    1)类字面常量应用于:普通类(包含包装类哟)、接口、数组、基本数据类型

    ***基本数据类型 使用标准字段TYPE,这是个指向基本数据类型的Class对象的引用

    ***例如int.class等价于Integer.TYPE,但是不等价于Integer.class

    2)使用".class"来创建Class对象的引用时,不会自动地初始化该Class对象。

    为什么不会自动初始化呢?由补充内容可知初始化被延迟到了对静态(static)方法(构造器等同于隐式静态)或者非常数(final)静态域进行首次引用时才执行,而引用类字面常量在运行时只是到了加载和链接的阶段

    Class对象构造对应类型对象的三种方式


    无参构造 

    1.Class对象的newInstance方法(不能传递参数)

    先获得Class对象,然后通过Class对象的newInstance方法直接生成

    1 Class<?> classType = String.class;
    2 Object obj = classType.newInstance();
    newInstance
    public T newInstance()
                  throws InstantiationException,
                         IllegalAccessException创建此 Class 对象所表示的类的一个新实例。如同用一个带有一个空参数列表的 new 表达式实例化该类。如果该类尚未初始化,则初始化这个类。 
    注意,此方法传播 null 构造方法所抛出的任何异常,包括已检查的异常。使用此方法可以有效地绕过编译时的异常检查,而在其他情况下编译器都会执行该检查。 Constructor.newInstance 方法将该构造方法所抛出的任何异常包装在一个(已检查的)InvocationTargetException 中,从而避免了这一问题。 
    
    
    返回:
    此对象所表示的类的一个新分配的实例。 
    抛出: 
    IllegalAccessException - 如果该类或其 null 构造方法是不可访问的。 
    InstantiationException - 如果此 Class 表示一个抽象类、接口、数组类、基本类型或 void; 或者该类没有 null 构造方法; 或者由于其他某种原因导致实例化失败。 
    ExceptionInInitializerError - 如果该方法引发的初始化失败。 
    SecurityException - 如果存在安全管理器 s,并满足下列任一条件: 
    调用 s.checkMemberAccess(this, Member.PUBLIC) 拒绝创建该类的新实例 
    调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 
    API文档描述

    2.Contructor对象的newInstance方法(不填参数就和1.一样)

    先获得Class对象,然后通过Class对象生成Constructor对象,通过Constructor对象的newInstance方法生成

    1 Class<?> classType = Customer.class;
    2 //Class[]数组对应形参类型、个数,这里为空
    3 Constructor cons = classType.getConstructor(new Class[]{}); 
    4 //Object[]数组对应传入的实参的类型、个数,这里为空
    5 Object obj = cons.newInstance(new Object[]{});
    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() 的调用拒绝访问该类的包 
    从以下版本开始: 
    JDK1.1 
    API-getConstructor
    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 - 如果此方法引发的初始化失败。
    API-Cons-newInstance

    含参构造

    3.Contructor对象的newInstance方法(填入形参类型和实际参数)

    先获得Class对象,然后通过Class对象生成Constructor对象,通过Constructor对象的newInstance方法生成

    1 Class<?> classType = Customer.class;
    2 //Class[]数组对应形参类型、个数,这里为Integer.TYPE,Xenos.class,String.class
    3 Constructor cons = classType.getConstructor(new Class[]{Integer.TYPE, Xenos.class, String.class}); 
    4 //Object[]数组对应传入的实参的类型、个数,这里为1, new Xenos(), "Think"
    5 Object obj = cons.newInstance(new Object[]{1, new Xenos(), "Think"});
  • 相关阅读:
    time 模块学习
    day 14 自定义模块,常用模块 time .datetime ,time 模块
    day 13 课后作业
    day 12 课后作业
    day 11课后作业
    树状数组最值
    hdu 1059 Dividing bitset 多重背包
    XVII Open Cup named after E.V. Pankratiev. XXI Ural Championship
    最长公共子序列板/滚动 N^2
    Uva 10635
  • 原文地址:https://www.cnblogs.com/ixenos/p/5689878.html
Copyright © 2011-2022 走看看