java.lang.Class使用中文文档

Class类是反射与加载器最常用的核心类,最近计划写一个JAVA加载器框架,决定重新温习相关接口和类的源码文档,实践相关用法以消除心中所存不确定。

  • 目录结构
  1. 类说明
  2. 对象创建
  3. UML类图
  4. 类成员方法
  5. 学习总结

1 类说明

翻译Class类源码英文文档,分段翻译并配合理解和例子加深印象。

英文:Instances of the class {@code Class} represent classes and interfaces in a running Java application.
中文:在一个运行中的JAVA程序,Class类的实例,代表用关键字class或interface声明的对象,如public class AnyObjectpublic interface AnyInterface

英文:An enum is a kind of class and an annotation is a kind of interface.
中文:Enum-枚举是一种Class类型,Annotation-注解是一种接口类型

英文:Every array also belongs to a class that is reflected as a {@code Class} object that is shared by all arrays with the same element type and number of dimensions.
中文:每一个数组属于一个类,按照数组元素类型和维度被反射为一个类对象,这个类对象被具有相同元素类型和维度的数组共享。

应用理解

序号 变量声明 变量声明 是否相同 差异因素
1 String[] o1 = new String[3] String[] o2 = new String[10] 相同
2 String[] o1 = new String[3] String[][] o3 = new String[3][5] 不同 数组维度
3 String[] o1 = new String[3] byte[] o4 = new byte[1024] 不同 元素类型

英文:The primitive Java types ({@code boolean}, {@code byte}, {@code char}, {@code short},{@code int}, {@code long}, {@code float}, and {@code double}), and the keyword {@code void} are also represented as {@code Class} objects.
中文:JAVA原始类型boolean / byte / char / short / int / long / float / double 与void关键字,也都有一种类对象代表。

原始类型与类对象对应表

序号 原始类型 对象类型 类型缩写
1 boolean java.lang.Boolean Z
2 byte java.lang.Byte B
3 char java.lang.Character C
4 short java.lang.Short S
5 int java.lang.Integer I
6 long java.lang.Long J
7 float java.lang.Float F
8 double java.lang.Double D
9 void java.lang.Void V

注意:原始类型与对象类型的Class不一样,类型缩写在.class文件中用到。另外,class或interface的类型缩写为L。

2 对象创建

英文:{@code Class} has no public constructor. Instead {@code Class} objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the {@code defineClass} method in the class loader.
中文:Class没有公有构造器函数,虚拟机装载类对象或被调用ClassLoader的defineClass方法时,Class对象实例被JAVA虚拟机自动构造。

Class对象实例的获取方式

  • 对象实例调用getClass方法
Thread thobj = new Thread();
Class clazz = thobj.getClass();
System.out.println(clazz.getName());

对任何对象类型的实例,调用getClass()函数可以获取对象类型。

  • 类字面量.class方式
Class clazz = String.class;
System.out.println(clazz.getName());

类字面量,就是指用class关键字声明的对象名称,如public class Foo {}Foo就是这个类的类字面量。

  • 静态函数forName
Class<?> clazz = Class.forName("java.lang.ArrayList");

请求参数为对象类型的全限定名称,一般情况,不需要额外制定类加载器。

  • 泛型类型的获取方式
Class<String> clazz = String.class
System.out.println(clazz.getName());

3 UML类图

  • Class类声明
public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type,  AnnotatedElement {
  //主体代码
}

声明分析
1 final关键字,Class类不能被继承;
2 实现AnnotatedElement接口,支持注解功能;
3 支持泛型,Class<T>声明,实现GenericDeclaration,支持获取泛型参数方法getTypeParameter;
4 实现Serializable接口,支持序列化。

  • Class类图
    整理Class类实现的接口,依赖的类与接口。


    ClassUML类图.png

4 类成员方法

4.1 构造函数

函数声明:private Class(ClassLoader loader)

  • 使用说明
    不能直接用new生成Class实例,也不提默认构造函数,直接由JVM在类装载或ClassLoader调用defineClass是调用。

4.2 成员方法

4.2.1 forName方法

  • 方法作用
    静态方法forName通过类的全限定名称加载类对象,常用于反射功能模块。两个函数的区别主要区别在于第二个函数制定了一个类加载器,函数实现时增加对加载器的安全权限检查。
  • 方法声明
public static Class<?> forName(String name) throws ClassNotFoundException
public static Class<?> forName(String name, bool isInit, ClassLoader loader) throws ClassNotFoundException

方法抛出异常还有LinkageError与ExceptionInInitializerError。
forName底层调用静态本地方法forName0函数:

private static native Class<?> forName0(String name,  boolean isInit, ClassLoader loader, Caller<?> caller) throws ClassNotFoundException;

4.2.2 newInstance方法

  • 方法作用
    调用默认构造函数生成对象实例。
  • 方法声明
@CallerSensitive
public T newInstance() throws InstantiationException, IllegalAccessException
  • 函数分析

注解@CallerSensitive,表明函数执行是否成功与调用者权限有关,Class类代码首先调用系统安全管理器检查调用者对本类是否有访问权限;
方法无参数,就是说,只能生成具有默认无参构造函数的类实例;若需要调用含参数列表的构造函数,需要通过反射技术调用Constructor类的newInstance方法;


4.2.3 isInstance方法

  • 方法作用
    判断本类型是否继承或实现参数制定的类或接口。
  • 方法声明
public native boolean isInstance(Object obj);

返回值说明

序号 this类型 obj说明 返回值
1 class obj是该类对象实例或子类型实例 true
2 array obj能执行类型转换为array对象 true
3 interface obj的类或上级类实现此接口 true
4 原始类型 任何情况 false

4.2.4 isAssignedFrom方法

  • 方法作用
    判断本类型是否为参数clazz的相同,或者是其子类或实现类。
  • 方法声明
public native boolean isAssignedFrom(Class<?> clazz);

注意:与isInstance方法不同,这个参数是Class类型,而isInstance的参数是对象实例。

4.2.5 常用判断方法

public native boolean isInterface(); #判断是否为接口对象
public native boolean isArray(); #判断是否为数组对象
public native boolean isPrimitive(); #判断是否为原始类型,如byte, int等
public boolean isAnnotation(); #判断是否为注解类型
public boolean isSynthetic(); #判断是否为合成类,不是手动编写的静态类
public boolean isAnonymousClass(); #判断是否为匿名类
public boolean isLocalClass(); #判断是否为本地类
public boolean isMemberClass(); #判断是否为成员类
public boolean isEnum(); #判断是否为枚举类型

4.2.6 字段操作方法

4.2.6.1 getField

  • 方法作用
    获取类声明的公有成员变量。
  • 方法声明
@CallerSensitive
public Field getField(String name);

根据名称参数name获取类的同名字段,没有名称对应的字段将抛出NoSuchFieldException。

4.2.6.2 getFields

  • 方法作用
    获取类声明的所有公有成员变量,返回Field数组,没有成员变量返回空数组。
  • 方法声明
@CallerSensitive
public Field[] getFields() throws SecurityException;

4.2.6.3 getDeclaredField方法

  • 方法作用
    获取类声明的同名成员变量,不管是公有还是私有,没有此名称成员变量抛出异常。
  • 方法申明
public Field getDeclaredField(String name);

4.2.6.4 getDeclaredFields方法

  • 方法作用
    获取类声明的所有成员变量,无论是公有还是私有,无成员变量返回空数组。
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException;

4.2.7 构造器方法

4.2.7.1 getConstrucutor

  • 方法作用
    获取与参数列表类型匹配的公有构造函数。
  • 方法申明
@CallerSensitive
public Constructor<T> getConstructor(Class<?>... paramTypes) throws NoSuchMethodException, SecurityException

4.2.7.2 getDeclaredConstructor

  • 方法作用
    获取与参数列表类型匹配的构造函数,不论公有私有。
  • 方法声明
@CallerSensitive
public Constructor<T> getDeclaredConstructor(Class<?>... paramTypes) throws NoSuchMethodException, SecurityException

4.2.7.3 getConstructors

  • 方法作用
    获取类声明的所有公有构造函数,返回Constructor数组。
  • 方法声明
@CallerSensitive
public Constructor[] getConstructors() throws SecurityException;

4.2.7.4 getDeclaredConstructors

  • 方法作用
    获取类声明的所有构造函数,不论公有私有,返回Constructor数组。
  • 方法声明
@CallerSensitive
public Constructor[] getDeclaredConstructors() throws SecurityException;

4.2.8 成员方法函数

4.2.8.1 getMethod

  • 方法作用
    获取与参数列表类型匹配的公有方法。
  • 方法申明
@CallerSensitive
public Method getMethod(Class<?>... paramTypes) throws NoSuchMethodException, SecurityException

4.2.8.2 getDeclaredMethod

  • 方法作用
    获取与参数列表类型匹配的方法,不论公有私有。
  • 方法声明
@CallerSensitive
public Method getDeclaredMethod(Class<?>... paramTypes) throws NoSuchMethodException, SecurityException

4.2.8.3 getMethods

  • 方法作用
    获取类声明的所有公有方法,返回Method数组。
  • 方法声明
@CallerSensitive
public Method[] getMethods() throws SecurityException;

4.2.8.4 getDeclaredMethods

  • 方法作用
    获取类声明的所有方法,不论公有私有,返回Method数组。
  • 方法声明
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException;

4.2.9 getModifiers方法

  • 方法作用
    获取类声明的访问修饰符,如public, protected, final等。
  • 方法声明
public native int getModifiers();

4.2.10 getInterfaces方法

  • 方法作用
    获取类实现的接口列表数组,返回Class<?>数组, 没有实现接口返回空数组。
  • 方法声明
public Class<?>[] getInterfaces();

4.2.11 getClasses方法

  • 方法作用
    获取类继承或实现接口的数组,返回Class<?>数组, 没有集成与实现接口返回空数组。
  • 方法声明
public Class<?> getClasses();

注意:getClasses方法包含getInterfaces方法返回的接口数组,排序与源代码声明顺序一致。

4.2.12 getSuperclass方法

  • 方法作用
    获取类的父类型,Class代表的类型可以是class / interface / 原始类型 / void。
  • 方法声明
public native Class<? super T> getSuperclass();
  • 返回值说明
    如果this是原始类型,父类型返回null;如果this代表一个数组,父类型返回java.lang.Object。

4.2.13 getPackage方法

  • 方法作用
    返回类所在的包对象。
  • 方法声明
public Package getPackage();

4.2.14 getComponentType方法

  • 方法作用
    获取数组元素类型,如果this不是数组类型,返回null。
  • 方法声明
public native Class<?> getComponentType()
  • 应用示例
    数组String[],函数返回数组元素类型java.lang.String。

4.2.15 getName方法

  • 方法作用
    获取this对象的全限定名称。
  • 方法声明
public String getName();
  • 应用示例
  1. 对象类型,如String.class.getName(),返回名称为java.lang.String;
  2. 原始类型,如byte.class.getName(),返回名称与原始类型一样,这里返回"byte";
  3. 数组类型,分两种情况:1)原始类型数组,返回“前缀[ + 类型缩写",如byte[5],返回字符串”[B“;2)对象数组,返回前缀[ + 类型全限定名称”,如String[5], 返回[Ljava.lang.String;
  4. 多维数组,与数组类型格式一致,数组有几维、就有几个前缀[,如long[2][3][4][5],返回字符串“[[[[J”;

4.2.16 注解操作方法

Spring / MyBatis就是调用Class类的注解操作方法,解析BEAN对象等的注解配置的,研究框架得多了解下这几个函数。

4.2.16.1 getAnnotation方法

  • 方法作用
    根据注解的类型获取类声明的注解对象。
  • 方法声明
public <A extends Annotation> A getAnnotation(Class<A> annotationType);
  • 使用示例
@RestController("/message")
class MessageController {
    @RequestMapping(value="annotation")
    public String getAnnotation(){
        RestController obj =(RestController)this.getClass().getAnnotation(RestController.class);
        System.out.println(obj.value());
        return obj.value();
    }
}

4.2.16.2 getAnnotations方法

  • 方法作用
    获取类声明的所有注解对象,返回Annotation数组,没有注解返回空数组。
  • 方法声明
public Annotation[] getAnnotations();

4.2.16.3 isAnnotationPresent方法

  • 方法作用
    返回类是否声明annotationType参数指定的注解。
  • 方法声明
public boolean isAnnotationPresent(Annotation<? extends Annotation> annotationType) ;
  • 方法示例
@Deprecated
public class App{
    public static void main(String[] args){
        /* 判断App类是否被Deprecated注解标识成Deprecated */
        boolean isOld = App.class.isAnnotationPresent(Deprecated.class);
    }
}

4.2.16.4 getAnnotationsByType方法

  • 方法作用
    根据注解类型annotationType获取类声明的所有注解,返回Annotion[]。
  • 方法声明
public <A extends Annotation> A[] getAnnotationsByType(Class<A extends Annotation> annotationType)

4.3 其它函数

Class类的方法还有不少,尤其是要研究几个内部类的作用,如EnclosingMethodInfo、ReflectionData等,了解其缓存优化等特点。

5 学习总结

Class类是反射技术的核心类

掌握forName方法使用,熟练使用构造函数、成员变量、成员变量获取函数

了解getSuperclass、getClasses与getInterfaces方法使用,动态代理过程常用

熟悉注解对象操作函数,框架对象属性配置经常用到

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容