Class类概述与使用

Class类简介

java.lang.Class类是Java RTTI机制的重要组成部分。每当编写并编译一个新类时,就会产生一个Class对象,并且会被保存到一个.class文件中。类的大量常规操作,如创建对象、转型等都是依靠这个类对应的Class对象完成的。
为了与Class类配合,运行Java程序的Java虚拟机(JVM)具有一个被称为“类加载器”的子系统,它能够在程序运行时动态地加载需要使用的类。当程序需要使用某个类时,类加载器会首先检查这个类的Class对象是否已经加载。如果尚未加载,默认的类加载器会根据类名查找.class文件,并将其载入内存。之后,这个Class对象就会被用于创建这个类的所有对象。
Class类提供了大量的实例方法,用于获取类的各种类型信息,比如类的类型(普通类、接口、枚举、注解)、构造器、方法、域等。这些方法为Java的反射与注解提供了支持。

获取Class对象

想要在运行时使用类型信息,第一步必须获取恰当的Class对象的引用。这里先创建一个简单的类,位于test包内:

package test;

public class Color {
    static{
        System.out.println("Loading Color");
    }
}

有以下几种方法可以获得Color类的Class对象:
(1)Object.getClass()
如果已经有了一个Color类的对象,那么直接通过Object类提供的getClass()方法即可:

Color color = new Color();
Class<?> clazz = color.getClass();

关于Class

try {
    Class<?> clazz = Class.forName("test.Color");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

可以看到,只需要把包名+类名作为一个字符串传入Class.forName()方法中即可。这个方法除了返回指定名称的类的Class对象,还负责在类尚未被加载的情况下加载类。如果找不到要加载的类,会抛出一个ClassNotFoundException异常。
(3)类字面常量
还有一种简单的方法可以不通过对象实例获取Class对象,就是利用类字面常量,如下:

Class<?> clazz = Color.class;

如果使用这种方法,那么编译器会自动识别类名是否可用,不可用的话就会报错。还有一点,使用这种方法获取Class对象时不会自动加载该类,类的加载会在首次使用该类时完成。

泛化的Class引用

Class类引入了泛型,用于限定Class引用指向的Class对象的类型。常用的有以下几种:

//可以指向任意Class对象
Class<?>

//指向某个类(此处为Father)的子类的Class对象
Class<? extends Father>

//指向某个类(此处为Child)的超类的Class对象
Class<? super Child>

运行时获取类型信息

获得Class对象的引用后,就可以利用Class类提供的一系列实例方法动态地获取类型信息了。下面将常用的方法进行一下分类整理。
(1)getName系列,用于获取该类的名称

String getCanonicalName ()

String getName ()

String getSimpleName ()

它们的区别难以描述,下面看一个实例:

public static void showName(Class<?> clazz){
    System.out.println("getCanonicalName(): " + clazz.getCanonicalName());
    System.out.println("getName(): " + clazz.getName());
    System.out.println("getSimpleName(): " + clazz.getSimpleName());
    System.out.println("-------------------------------------------");
}

public static void main(String[] args) {
    showName(int.class);
    showName(int[].class);
    showName(int[][].class);
    showName(String.class);
    showName(String[].class);
}

输出:

getCanonicalName(): int
getName(): int
getSimpleName(): int
-------------------------------------------
getCanonicalName(): int[]
getName(): [I
getSimpleName(): int[]
-------------------------------------------
getCanonicalName(): int[][]
getName(): [[I
getSimpleName(): int[][]
-------------------------------------------
getCanonicalName(): java.lang.String
getName(): java.lang.String
getSimpleName(): String
-------------------------------------------
getCanonicalName(): java.lang.String[]
getName(): [Ljava.lang.String;
getSimpleName(): String[]
-------------------------------------------

(2)is系列,用于判断该类的类型。

//是否是注解类。
boolean isAnnotation ()

//指定的注解是否存在,等同于getAnnotation(annotationClass) != null。
boolean isAnnotationPresent (Class<? extends Annotation> annotationClass)

//是否是匿名类。
boolean isAnonymousClass ()

//是否是数组类。
boolean isArray ()

//如果该Class对象指向的类与参数cls指向的类相同,或者是它的超类或超接口,该方法就返回true,否则返回false。
boolean isAssignableFrom (Class<?> cls)

//是否是枚举类。
boolean isEnum ()

//如果obj不为null,并且可以被转成该Class对象指向的类型,该方法就返回true。和instanceof类似。
boolean isInstance (Object obj)

//是否是接口类。
boolean isInterface ()

//是否是局部类(块、构造器、方法中定义的类)。
boolean isLocalClass ()

//是否是成员类(一个类内部声明的类,不包括局部类和匿名类)。
boolean isMemberClass ()

//是否是原始类型(boolean, byte, char, short, int, long, float, double)。
boolean isPrimitive ()

(3)get系列,用于获取可访问的成员(即public),包括继承得到的。注意和下面的getDeclared系列区分。

//获取该类指定类型的注解。
<A extends Annotation> A getAnnotation(Class<A> annotationClass)

//获取该类所有注解。
Annotation[] getAnnotations ()


//获取该类指定类型的所有注解(重复注解是Java 8新特性)。
<A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass)

//获取该类的ClassLoader
ClassLoader getClassLoader ()

//获取该类所有public的成员类与成员接口的Class对象。
Class[]<?> getClasses ()

//返回一个数组的内部元素的Class对象,若该Class对象不代表数组则返回null。
Class<?> getComponentType ()

//获取该类指定参数列表的一个public的构造器。
//需要注意的是,如果该Class对象代表一个非静态内部类,那么需要将这个内部类所属的类的Class对象放在参数列表首位。
Constructor<T> getConstructor (Class...<?> parameterTypes)

//获取该类所有public的构造器。以下情况下会返回null:
//该类没有public的构造器;该类是数组类;该类代表原始类型;该类代表void。
Constructor[]<?> getConstructors ()

//返回声明该类的类的Class对象,如果该类不是一个成员类(局部类、匿名类)则返回null。注意和下面的区分。
Class<?> getDeclaringClass ()

//如果该类是一个内部类(无论是否是静态的),则返回它所属的类的Class对象,否则返回nullClass<?> getEnclosingClass ()

//如果该类是一个在构造器中定义的局部类或匿名类,返回这个构造器,否则返回nullConstructor<?> getEnclosingConstructor ()

//如果该类是一个在方法中定义的局部类或匿名类,返回这个方法,否则返回nullMethod getEnclosingMethod ()

//返回该类所有枚举,若该类不是枚举类则返回nullT[] getEnumConstants ()

//返回该类一个指定名称的public的域,查找顺序如下:
//①若该类中能够找到,则返回;
//②若该类中找不到,则递归地到该类的所有超接口中查找,查找顺序和声明顺序一致;
//③若还是找不到,则递归地到该类的超类中查找④抛出NoSuchFieldException。这个方法不会查找到数组类的length域。
Field getField (String name)

//返回该类所有public的域。
//数组类、原始类型、void会返回一个长度为0的数组。
Field[] getFields ()

//获取所有接口,注意只会返回该类直接实现的。
Class[]<?> getInterfaces ()

//获得该类指定名称与参数列表的public的成员方法。
//如果该类中找不到,会递归地向该类的超类以及实现的接口中找。
//注意:超类和超接口中的静态方法不属于该类的成员方法。
//如果有多个对应方法,那么会返回返回值最具体的那个,
//若还区分不了则会随机返回一个。
//这个方法不会查找到数组类的clone()方法。
Method getMethod (String name, 
                Class...<?> parameterTypes)

//返回该类所有成员方法。
//注意:超类和超接口中的静态方法不属于该类的成员方法。
Method[] getMethods ()

//返回一个int,包含该类的标识信息(public, protected, private, final, static, abstract, interface等)。
//可以利用java.lang.Modifier解析。
int getModifiers ()

//获取该类所属的包。
Package getPackage ()

//获取该类的保护域。
ProtectionDomain getProtectionDomain ()

//根据名称(实际上也可以带路径)获取某个资源。
//参考http://swiftlet.net/archives/868
URL getResource (String name)
InputStream getResourceAsStream (String name)

//获取该类的签名者。
Object[] getSigners ()

//获取该类的超类的Class对象。
//若该类是Object、接口、原始类型或者void则会返回null,若该类是数组类则返回Object的Class对象。
Class<? super T> getSuperclass ()

(4)getDeclared系列,用于获取在该类内声明的(不包括继承得到的)成员,并且不限制访问权限(即无论是public、package private、protected还是private都能获取到),注意和get系列区分开。除了上面两点之外,这些方法和get系列里面对应的方法效果一致。

//获取指定注解,必须是直接标注在该类上的。
A getDeclaredAnnotation (Class<A> annotationClass)

//获取所有注解,必须是直接标注在该类上的。
Annotation[] getDeclaredAnnotations ()

//获取所有该类声明的成员类的Class对象。
Class[]<?> getDeclaredClasses ()

//获取该类声明的一个指定参数列表的构造器。
//如果该Class对象代表一个非静态内部类,那么需要将这个内部类所属的类的Class对象放在参数列表首位。
Constructor<T> getDeclaredConstructor (Class...<?> parameterTypes)

//获取所有该类声明的构造器。
Constructor[]<?> getDeclaredConstructors ()

//获取该类声明的一个指定名称的域。这个方法不会查找到数组类的length域。
Field getDeclaredField (String name)

//获取该类声明的所有域。
Field[] getDeclaredFields ()

//获取该类声明的一个指定名称与参数列表的方法。
//如果有多个对应方法,那么会返回返回值最具体的那个,若还区分不了则会随机返回一个。
//这个方法不会查找到数组类的clone()方法。
Method getDeclaredMethod (String name, 
                Class...<?> parameterTypes)

//获取该类声明的所有方法。
Method[] getDeclaredMethods ()

(5)泛型相关方法

//获取一个数组,包含一组Type,代表所有泛型接口(其实普通接口也会返回,只是能识别泛型接口)。
//注意:只会返回该类直接实现的。
Type[] getGenericInterfaces ()

//返回该类的泛型超类
Type getGenericSuperclass ()

补充:get系列与getDeclared系列在找不到结果时,若返回值是数组类型则会返回一个成员个数为0的空数组,若返回值是对象则会返回null。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值