Class类概述与使用

来源:互联网 发布:济南行知小学作文 编辑:程序博客网 时间:2024/06/07 07:23

    • Class类简介
    • 获取Class对象
    • 泛化的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(): intgetName(): intgetSimpleName(): int-------------------------------------------getCanonicalName(): int[]getName(): [IgetSimpleName(): int[]-------------------------------------------getCanonicalName(): int[][]getName(): [[IgetSimpleName(): int[][]-------------------------------------------getCanonicalName(): java.lang.StringgetName(): java.lang.StringgetSimpleName(): 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)//获取该类的ClassLoaderClassLoader 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/868URL 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。

原创粉丝点击