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对象,否则返回null。Class<?> getEnclosingClass ()//如果该类是一个在构造器中定义的局部类或匿名类,返回这个构造器,否则返回null。Constructor<?> getEnclosingConstructor ()//如果该类是一个在方法中定义的局部类或匿名类,返回这个方法,否则返回null。Method getEnclosingMethod ()//返回该类所有枚举,若该类不是枚举类则返回null。T[] 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。
- Class类概述与使用
- java Class类概述
- Constructor类概述与使用
- Class类文件结构概述
- Servlet概述与使用
- 反射(概述,Class对象和信息,使用反射生产并操作对象,数组,反射与框架)
- SQLiteOpenHelper CLASS,与SQLiteDataBase CLASS的使用
- class.getResource与class.getClassLoader().getResource使用
- KVO的概述与使用
- KVC的概述与使用
- KVO的概述与使用
- KVO的概述与使用
- KVC的概述与使用
- KVO的概述与使用
- KVO 的概述与使用
- KVC的概述与使用
- KVO的概述与使用
- KVC的概述与使用
- HYSBZ
- Unity3D工程集成到Android工程步骤及问题解决
- Jenkins2.32.1配置与构建部署-邮件配置及构建状态(二)
- java定义二维数组的几种写法汇总
- 【servlet学习一】:servlet体系结构和工作原理
- Class类概述与使用
- fetch跨域问题
- echarts3 中,图表随着窗口的变动而变动(让图表resize有效)
- jQuery 按回车键触发函数
- sftp远程上传文件到阿里云的linux服务器
- 找x
- Java技能清单
- [日推荐] 『TheGolfGame』-小程序有游戏啦?
- js读取图片,获取并获取图片高度和宽度