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方法直接生成

 Class<?> classType = String.class;
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方法生成

 Class<?> classType = Customer.class;
//Class[]数组对应形参类型、个数,这里为空
Constructor cons = classType.getConstructor(new Class[]{});
//Object[]数组对应传入的实参的类型、个数,这里为空
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方法生成

 Class<?> classType = Customer.class;
//Class[]数组对应形参类型、个数,这里为Integer.TYPE,Xenos.class,String.class
Constructor cons = classType.getConstructor(new Class[]{Integer.TYPE, Xenos.class, String.class});
//Object[]数组对应传入的实参的类型、个数,这里为1, new Xenos(), "Think"
Object obj = cons.newInstance(new Object[]{1, new Xenos(), "Think"});

Java 反射 Class类的更多相关文章

  1. java 反射提取类信息, 动态代理 和过滤某些方法演示

    java 反射提取类信息, 动态代理 和过滤某些方法演示 package org.rui.classts.reflects; import java.lang.reflect.Constructor; ...

  2. Java 反射 分析类和对象

    Java 反射 分析类和对象 @author ixenos 摘要:优化程序启动策略.在运行时使用反射分析类的结构和对象 优化程序启动策略 在启动时,包含main方法的类被加载.它会加载所有它需要的类. ...

  3. 【java】java反射 Field类的研究使用

    java反射 Field类的研究使用 user.getClass().getFields() 和 user.getClass().getDeclaredFields(); 的区别是什么?

  4. 利用Java反射根据类的名称获取属性信息和父类的属性信息

    代码: import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java ...

  5. 利用java反射调用类的的私有方法--转

    原文:http://blog.csdn.net/woshinia/article/details/11766567 1,今天和一位朋友谈到父类私有方法的调用问题,本来以为利用反射很轻松就可以实现,因为 ...

  6. java反射工具类

    package com.yingchao.kgou.core; import java.lang.reflect.Field; import java.lang.reflect.InvocationT ...

  7. 深入分析Java反射(五)-类实例化和类加载

    前提 其实在前面写过的<深入分析Java反射(一)-核心类库和方法>已经介绍过通过类名或者java.lang.Class实例去实例化一个对象,在<浅析Java中的资源加载>中也 ...

  8. Java反射获取类和对象信息全解析

    反射可以解决在编译时无法预知对象和类是属于那个类的,要根据程序运行时的信息才能知道该对象和类的信息的问题. 在两个人协作开发时,你只要知道对方的类名就可以进行初步的开发了. 获取类对象 Class.f ...

  9. java反射获取类的类名、属性名、属性类型、方法、执行方法、构造函数

    public class Demo02 { @SuppressWarnings("all") public static void main(String[] args) thro ...

随机推荐

  1. VS辅助工具

    tfs签入策略修改工具Team Foundation Server 2015 Power Tools(tfpt) 添加签入禁止策略 \*/bin \*/obj \*/Release \*/Debug ...

  2. Maven之(八)约定优于配置

    maven的配置文件看似很复杂,其实只需要根据项目的实际背景,设置个别的几个配置项而已.maven有自己的一套默认配置,使用者除非必要,并不需要去修改那些约定内容.这就是所谓的"约定优于配置 ...

  3. [Q]“获取AutoCAD安装信息时失败...”解决方法

    “获取AutoCAD安装信息时失败...”解决方法:在“setup.exe”上右键,以管理员权限运行即可.

  4. 报错找不到org.apache,http...的解决办法

    在build.gradle中加入 android { useLibrary 'org.apache.http.legacy' }

  5. Jenkins slave image

    Add a new shell script configure_slave.sh as following: #!/bin/bash dnf -openjdk git wget openssh-se ...

  6. 给RelativeLayout设置背景,无效果bug解决

    drawable文件夹下面 tomyshop_selector.xml文件 <?xml version="1.0" encoding="utf-8"?&g ...

  7. swift 经典代码收集 和 赏析

    代码1:protocol PickableEnum { var displayName: String { get } var permanentID: String { get } static v ...

  8. Abstract和Virtual

    在C#的学习中,容易混淆virtual方法和abstract方法的使用,现在来讨论一下二者的区别. 它们有一个共同点:二者都是用来修饰父类的,只能作为基类使用,通过覆盖父类的定义,让子类与overri ...

  9. Form提交时隐藏Token验证

    前端声称一个Token @Html.AntiForgeryToken() 后台对Token进行验证 AntiForgery.Validate();

  10. Jquery实现双击表单元格可编辑

    <script type="text/javascript"> function doTableTdEditClick(param){ doTdEditable(par ...