java反射中经常用到Class类, 本文对它以及它的方法进行简单说明
Class类位于java.lang
包中, Class类的实例表示正在运行的Java应用程序中的类和接口.
枚举算类, 注解算接口; 数组算类,它映射的Class对象被有着相同元素和大小的数组共享;
Java的原生(primitive types)类型(boolean、byte、char、short、int、long、float、double
)和关键字void
也代表Class对象.
Class类实现了Serializable、GenericDeclaration、Type、AnnotatedElement
接口
Class类无public构造函数, Class类对象是由JVM在类加载的时候调用类加载器的defineClass
方法创建的.
如下方法能够获取类名:
obj.getClass().getName()
Foo.class.getName()
这些方法可以判断某个类是否是接口、是否是枚举、是否是注解、是否有某个注解、是否是匿名类、是否是某个类的超类(是否可强制转换为该类)等
boolean isArray()
: 是否是数组; int[].class.isArray()
为true
boolean isAnnotation()
: 是否是注解, 若返回true
,则isInterface
也为ture
; Target.class.isAnnotation()
为true
boolean isEnum()
: 是否是枚举类boolean isPrimitive()
: 是否是原生类型(共9个, 包装类返回false
), void.class.isArray()
为true
boolean isInterface()
: 是否是接口boolean isMemberClass()
: 是否是成员类, 类的定义在另一个类里面的那种boolean isAnonymousClass()
: 是否是匿名类boolean isLocalClass()
: 是否是本地类boolean isSynthetic()
: 是否是复合类 (接口Member
也有这个方法)boolean isInstance(Object obj)
: obj是否是该类的一个实例boolean isAssignableFrom(Class<?> cls)
: cls是否可以被转换成该类boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
: 该类上是否存在这个注解(继承自接口AnnotatedElement
)下面是几个方法的实例说明:
public class Main {
class Test{} // 这是传说中的成员类
public static void main(String[] args) {
class LocalClass{} // 这是传说中的本地类
Object obj = new Hello(){ // Hello是其他地方定义的一个接口, 有一个sayHello()方法, 这就是匿名类(无类名)
public void sayHello() {
}
};
System.out.println(Test.class.isMemberClass()); // true
System.out.println(obj.getClass().isAnonymousClass()); // true
System.out.println(LocalClass.class.isLocalClass()); // true
System.out.println(Hello.class.isInstance(obj)); // true
System.out.println(Bean.class.isAnnotationPresent(Target.class)); // true
}
}
instanceof
、 isInstance
、 isAssignableFrom
的区别instanceof
运算符只被用于对象引用变量, 比如: 自身类或子类的实例 instanceof 自身类
返回true
isInstance(Object obj)
是instanceof
运算符的动态等价, 比如: 自身类.class.isInstance(自身类或子类的实例)
返回true
isAssignableFrom(Class<?> cls)
是两个类之间的关系, 比如: 自身类.class.isAssignableFrom(自身类或子类.class)
返回true
通过Class类可以获取这个类的一些内容性质的信息, 比如属性、方法、构造方法、注解
Field[] getFields()
: 获取本类或父类中所有public属性Field getField(String name)
: 获取本类或父类中特定名字的public属性Field[] getDeclaredFields()
: 获取本类中声明的所有属性Field getDeclaredField(String name)
: 获取本类中声明的特定名字的属性Method[] getMethods()
: 获取本类或父类中所有public方法(包括构造器方法)Method getMethod(String name, Class<?>... parameterTypes)
: 获取本类或父类中特定名字和参数的public方法Method[] getDeclaredMethods()
: 获取本类中声明的所有方法(包括非public但不包括继承来的)Method getDeclaredMethod(String name, Class<?>... parameterTypes)
: 获取本类中声明的特定名字和参数的方法(最常用)Constructor<?>[] getConstructors()
: 获取本类中所有public构造器Constructor<T> getConstructor(Class<?>... parameterTypes)
: 获取本类中特定参数的public构造器Constructor<?>[] getDeclaredConstructors()
: 获取本类中所有构造器Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
: 获取本类中指定参数的构造器这几个方法均继承自接口AnnotatedElement
Annotation[] getAnnotations()
: 获取这个元素上的所有注解(包括父类上被@Inherited
标记的注解)<A extends Annotation> A getAnnotation(Class<A> annotationClass)
: 获取这个元素上指定类型的注解, 没有返回nullAnnotation[] getDeclaredAnnotations()
: 获取直接标注在这个元素上的注解Class<? super T> getSuperclass()
: 返回本类的父类(直接超类);int[].class
为Object
, int.class
为null
, Object.class
为null
Type getGenericSuperclass()
: 以Type的形式返回本类的父类, 带有范型信息(没有范型信息时把Class以Type形式返回)Class<?>[] getInterfaces()
: 返回本类直接实现的接口Type[] getGenericInterfaces()
: 以Type的形式返回本类直接实现的接口, 带有范型信息<U> Class<? extends U> asSubclass(Class<U> clazz)
: 把当前类转为clazz表示的子类(或自己), 不能转抛ClassCastException
异常asSubclass
的作用
ArrayList.class.asSubclass(List.class)
得到的还是ArrayList.class
, 看起来没什么作用
但是它的作用体现在窄化未知的Class类型的范围, 比如通常我们用到Class.forName("XXX")
, 它的返回是Class<?>
比较宽泛, 我们可以窄化一下: Class.forName("XXX").asSubclass(List.class).newInstance()
. 当XXX
不是List
的子类时,抛出ClassCastException
异常
Class<?> getEnclosingClass()
: 获取底层类的直接封闭类, 如上面LocalClass
的封闭类为Main
, 那个匿名类的封闭类也是Main
Constructor<?> getEnclosingConstructor()
: 若该Class对象是在一个构造方法中的本地类或匿名类时, 返回这个构造器对象, 表示底层类直接封闭构造方法, 否则返回null
; 上面的LocalClass
不在构造方法中,因此返回null
Method getEnclosingMethod()
: 若该Class对象是在一个方法中的本地类或匿名类时, 返回这个Method
对象, 表示底层类的直接封闭方法, 否则返回null
Class<?> getDeclaringClass()
: 该类是另一个类的成员(isMemberClass
),则返回该类的声明类(外部类); 接口Member
中也有该方法Class<?>[] getDeclaredClasses()
: 返回该类中直接声明的所有类Class<?>[] getClasses()
: 返回该类中直接声明的所有public类static Class<?> forName(String className)
: 返回与给定的字符串名称相关联的Class对象String getSimpleName()
: 返回源码中定义的简单类名, 匿名类返回空串, 数组返回”组件类型[]”String getCanonicalName
: 返回底层类的Java语言规范中定义的标准名称public String getName()
: 返回此Class对象所表示的实体(类,接口,数组类,基本类型或void)的名字, 略复杂,规则如下:
元素类型 | 类型代码 |
---|---|
boolean | Z |
byte | B |
char | C |
double | D |
float | F |
int | I |
long | J |
short | S |
class or interface | Lclassname; |
来个例子:
public class ClassTest {
public static void main(String[] args) throws Exception {
Class clazz = String.class;
System.out.println(clazz.getSimpleName()); // String
System.out.println(clazz.getCanonicalName()); // java.lang.String
System.out.println(clazz.getName()); // java.lang.String
clazz = int.class;
System.out.println(clazz.getSimpleName()); // int
System.out.println(clazz.getCanonicalName()); // int
System.out.println(clazz.getName()); // int
String[] strings = {"a", "b"};
clazz = strings.getClass();
System.out.println(clazz.getSimpleName()); // String[]
System.out.println(clazz.getCanonicalName()); // java.lang.String[]
System.out.println(clazz.getName()); // [Ljava.lang.String;
int[][] array = {new int[]{1, 2}, new int[]{10, 20}};
clazz = array.getClass();
System.out.println(clazz.getSimpleName()); // int[][]
System.out.println(clazz.getCanonicalName()); // int[][]
System.out.println(clazz.getName()); // [[I
}
}
TypeVariable<Class<T>>[] getTypeParameters()
: 继承自接口GenericDeclaration
,按照声明顺序返回声明的类型变量Class<?> getComponentType()
: 若该类是个数组,则返回组件的类型还有一些方法暂不介绍了.