概述
Class的本质也是一个类,只不过它是将我们定义类的共同的部分进行抽象,比如我们常定义的类都含有构造方法,类变量,函数,而Class这个类就是来操作这些属性和方法的。当然我们常定义的类包含的类型都可以通过Class间接的来操作。而类的类型包含一般的类,接口,枚举类型,注解类型等等
而Class类中的getMethods()方法默认会获取父类中的公有方法,也就是public修饰的方法。所以Object中的公共方法也出现了。
注: 要想获得父类的所有方法(public、protected、default、private),可以使用apache commons包下的**FieldUtils.getAllFields()**可以获取类和父类的所有(public、protected、default、private)属性。
继承关系
public final class Class implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement
实现了 java.io.Serializable, GenericDeclaration, Type, AnnotatedElement 4个接口。
成员属性
- private transient String name;
- private final ClassLoader classLoader;
静态代码块
private static native void registerNatives();
static {
registerNatives();
}
registerNatives()方法是由其它语言实现的。通过该方法名可以猜测到registerNatives()的作用是注册本地方法。在静态代码块中调用registerNatives(),可以得出当类加载时就进行注册。
在Object、Thread等类中通过registerNatives将指定的本地方法绑定到指定函数,如将hashCode和clone本地方法绑定到JVM_IHashCode和JVM_IHashCode函数。
具体更多的内容可以参见registerNatives()深入理解
构造方法
Class类没有公共的构造方法,Class对象是在类加载的时候由Java虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。一个类被加载到内存并供我们使用需要经历如下三个阶段:
加载,这是由类加载器(ClassLoader)执行的。通过一个类的全限定名来获取其定义的二进制字节流(Class字节码),将这个字节流所代表的静态存储结构转化为方法去的运行时数据接口,根据字节码在java堆中生成一个代表这个类的java.lang.Class对象。
链接。在链接阶段将验证Class文件中的字节流包含的信息是否符合当前虚拟机的要求,为静态域分配存储空间并设置类变量的初始值(默认的零值),并且如果必需的话,将常量池中的符号引用转化为直接引用。
初始化。到了此阶段,才真正开始执行类中定义的java程序代码。用于执行该类的静态初始器和静态初始块,如果该类有父类的话,则优先对其父类进行初始化。
private Class(ClassLoader loader) {
// Initialize final field for classLoader.
// The initialization value of non-null
// prevents future JIT optimizations from assuming this final field is null.
classLoader = loader;
}
关键方法
toString()
返回Class实体的名称。例如 "abc".getClass().toString()
class java.lang.String
public String toString() {
return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
+ getName();
}
toGenericString()
返回宇哥字符串的描述信息。包括修饰符和类型信息。 例如: "abc".getClass().toGenericString():
public final class java.lang.String
public String toGenericString() {
if (isPrimitive()) {
return toString();
} else {
StringBuilder sb = new StringBuilder();
// Class modifiers are a superset of interface modifiers
int modifiers = getModifiers() & Modifier.classModifiers();
if (modifiers != 0) {
sb.append(Modifier.toString(modifiers));
sb.append(' ');
}
if (isAnnotation()) {
sb.append('@');
}
if (isInterface()) { // Note: all annotation types are interfaces
sb.append("interface");
} else {
if (isEnum())
sb.append("enum");
else
sb.append("class");
}
sb.append(' ');
sb.append(getName());
TypeVariable<?>[] typeparms = getTypeParameters();
if (typeparms.length > 0) {
boolean first = true;
sb.append('<');
for(TypeVariable<?> typeparm: typeparms) {
if (!first)
sb.append(',');
sb.append(typeparm.getTypeName());
first = false;
}
sb.append('>');
}
return sb.toString();
}
}
forName()
用指定的类加载器,根据指定的名称,返回和该类或者接口 相关的Class对象。
@CallerSensitive
public static Class<?> forName(String name, boolean initialize,
ClassLoader loader)
throws ClassNotFoundException
{
Class<?> caller = null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// Reflective call to get caller class is only needed if a security manager
// is present. Avoid the overhead of making this call otherwise.
caller = Reflection.getCallerClass();
if (sun.misc.VM.isSystemDomainLoader(loader)) {
ClassLoader ccl = ClassLoader.getClassLoader(caller);
if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
sm.checkPermission(
SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
}
return forName0(name, initialize, loader, caller);
}
根据给定的名称,返回和该类或者接口 相关的Class对象,指定的类加载器,即当前类的加载器。
@CallerSensitive
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
newInstance()
用Class 对象 创建一个类的实例。以空的参数列表实例化类。 如果没有被初始化,该类就会被初始化。
@CallerSensitive
public T newInstance()
throws InstantiationException, IllegalAccessException
{
if (System.getSecurityManager() != null) {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
}
// NOTE: the following code may not be strictly correct under
// the current Java memory model.
// Constructor lookup
if (cachedConstructor == null) {
if (this == Class.class) {
throw new IllegalAccessException(
"Can not call newInstance() on the Class for java.lang.Class"
);
}
try {
Class<?>[] empty = {};
final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
// Disable accessibility checks on the constructor
// since we have to do the security check here anyway
// (the stack depth is wrong for the Constructor's
// security check to work)
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
c.setAccessible(true);
return null;
}
});
cachedConstructor = c;
} catch (NoSuchMethodException e) {
throw (InstantiationException)
new InstantiationException(getName()).initCause(e);
}
}
Constructor<T> tmpConstructor = cachedConstructor;
// Security check (same as in java.lang.reflect.Constructor)
int modifiers = tmpConstructor.getModifiers();
if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
if (newInstanceCallerCache != caller) {
Reflection.ensureMemberAccess(caller, this, null, modifiers);
newInstanceCallerCache = caller;
}
}
// Run constructor
try {
return tmpConstructor.newInstance((Object[])null);
} catch (InvocationTargetException e) {
Unsafe.getUnsafe().throwException(e.getTargetException());
// Not reached
return null;
}
}
isInstance()
判断指定的对象是不是一个类的实例。等效于java语言的instanceof操作符。 如果指定的Object参数不为空,并且可以强制转换为由该 Class 对象表示的引用类型, 而不引发 ClassCastException,则该方法返回 true,否则返回 false。
public native boolean isInstance(Object obj);
isAssignableFrom()
判断当前类是不是参数类的父类。或者父接口。
public native boolean isAssignableFrom(Class<?> cls);
isInterface()
public native boolean isInterface();
isArray()
public native boolean isArray();
isPrimitive()
public native boolean isPrimitive();
注意这样的描述,除了8个基本类型之外,还有Void
* @return true if and only if this class represents a primitive type
*
* @see java.lang.Boolean#TYPE
* @see java.lang.Character#TYPE
* @see java.lang.Byte#TYPE
* @see java.lang.Short#TYPE
* @see java.lang.Integer#TYPE
* @see java.lang.Long#TYPE
* @see java.lang.Float#TYPE
* @see java.lang.Double#TYPE
* @see java.lang.Void#TYPE
* @since JDK1.1
isAnnotation()
public boolean isAnnotation() {
return (getModifiers() & ANNOTATION) != 0;
}
关于注解,本身是接口,因此文档写明, annotation is one kind of interface
* Note that if this method returns true, {@link #isInterface()}
* would also return true, as all annotation types are also interfaces.
isSynthetic()
public boolean isSynthetic() {
return (getModifiers() & SYNTHETIC) != 0;
}
关于synthetic关键字,可以参考synthetic关键字
getName()
public String getName() {
String name = this.name;
if (name == null)
this.name = name = getName0();
return name;
}
private native String getName0();
getClassLoader()
返回类的加载器。有一些实现里,用null代表boostrap类加载器。
@CallerSensitive
public ClassLoader getClassLoader() {
ClassLoader cl = getClassLoader0();
if (cl == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
}
return cl;
}
// Package-private to allow ClassLoader access
ClassLoader getClassLoader0() { return classLoader; }
在注释中,有这样一句:
* <p>If this object
* represents a primitive type or void, null is returned.
*
* @return the class loader that loaded the class or interface
* represented by this object.
getTypeParameters()
返回一个由 TypeVariable对象组成的数组。该数组按照声明顺序表示该GenericDeclaration对象表示的范型声明声明的变量。
public TypeVariable<Class<T>>[] getTypeParameters() {
ClassRepository info = getGenericInfo();
if (info != null)
return (TypeVariable<Class<T>>[])info.getTypeParameters();
else
return (TypeVariable<Class<T>>[])new TypeVariable<?>[0];
}
代码示例:
HashMap<String, Object> map = new HashMap<>();
TypeVariable[] t = map.getClass().getTypeParameters();
System.out.println(t.length);
System.out.println(t[0].getName());
System.out.println(t[1].getName());
>> 2
>> K
>> V
getSuperclass()
返回父类
public native Class<? super T> getSuperclass();
注意注释中这样的解释
* If this {@code Class} represents either the
* {@code Object} class, an interface, a primitive type, or void, then
* null is returned. If this object represents an array class then the
* {@code Class} object representing the {@code Object} class is
* returned.
getGenericSuperclass()
如果父类是参数化的类型。那么返回的Type对象必须真是的反映了源代码中的实际的类型参数。参数化的类型表示,如果父类没有被创建,则创建它。返回直接父类,包含范型参数
public Type getGenericSuperclass() {
ClassRepository info = getGenericInfo();
if (info == null) {
return getSuperclass();
}
// Historical irregularity:
// Generic signature marks interfaces with superclass = Object
// but this API returns null for interfaces
if (isInterface()) {
return null;
}
return info.getSuperclass();
}
getPackage()
获取包名
public Package getPackage() {
return Package.getPackage(this);
}
getInterfaces()
确定由"该对象表示的类或者接口" 实现的接口。 如果该对象是一个类。那么返回值是所有该类实现的接口。
public Class<?>[] getInterfaces() {
ReflectionData<T> rd = reflectionData();
if (rd == null) {
// no cloning required
return getInterfaces0();
} else {
Class<?>[] interfaces = rd.interfaces;
if (interfaces == null) {
interfaces = getInterfaces0();
rd.interfaces = interfaces;
}
// defensively copy before handing over to user code
return interfaces.clone();
}
}
private native Class<?>[] getInterfaces0();
getGenericInterfaces()
确定由"该对象表示的类或者接口" 实现的接口。如果一个父接口是一个参数化的类型。那么返回的Type对象必须反应了源代码中真是的类型参数。参数化的类型代表了每个父接口如果没有被创建的化,就会被创建。 如果该对象是一个类,那么返回值是一个数组。数组包含了该类实现的所有接口。 如果该对象是一个接口,数组包含了该接口直接继承的接口。 如果该对象表示一个基本类型或者void。那么返回的是一个长度为0的数组。
public Type[] getGenericInterfaces() {
ClassRepository info = getGenericInfo();
return (info == null) ? getInterfaces() : info.getSuperInterfaces();
}
与getInterfaces()的不同在于:getGenericInterface返回包括泛型的类型,getInterfaces没有
例子可以参见此
getComponentType()
返回 代表了一个数组的组件类型的类。 如果类不表示任何数组类。那么方法会返回null
public native Class<?> getComponentType();
getModifiers()
返回修饰符。编码为一个integer。
public native int getModifiers();
getSigners()
返回类的签署人。
public native Object[] getSigners()
具体细节可以参见此
setSigners()
设置人的签署人。
native void setSigners(Object[] signers);
getEnclosingMethod()
如果该类代表了在一个方法内的本地或者匿名类。 返回一个Method对象。 这个Method对象表示底层类的直接封闭方法。否则返回false。 特别的,如果基础类是有类型声明、实例初始化或者静态初始化直接封装的本地匿名类,此方法返回false。
@CallerSensitive
public Method getEnclosingMethod() throws SecurityException {
EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo();
if (enclosingInfo == null)
return null;
else {
if (!enclosingInfo.isMethod())
return null;
MethodRepository typeInfo = MethodRepository.make(enclosingInfo.getDescriptor(),
getFactory());
Class<?> returnType = toClass(typeInfo.getReturnType());
Type [] parameterTypes = typeInfo.getParameterTypes();
Class<?>[] parameterClasses = new Class<?>[parameterTypes.length];
// Convert Types to Classes; returned types *should*
// be class objects since the methodDescriptor's used
// don't have generics information
for(int i = 0; i < parameterClasses.length; i++)
parameterClasses[i] = toClass(parameterTypes[i]);
// Perform access check
Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
enclosingCandidate.checkMemberAccess(Member.DECLARED,
Reflection.getCallerClass(), true);
/*
* Loop over all declared methods; match method name,
* number of and type of parameters, *and* return
* type. Matching return type is also necessary
* because of covariant returns, etc.
*/
for(Method m: enclosingCandidate.getDeclaredMethods()) {
if (m.getName().equals(enclosingInfo.getName()) ) {
Class<?>[] candidateParamClasses = m.getParameterTypes();
if (candidateParamClasses.length == parameterClasses.length) {
boolean matches = true;
for(int i = 0; i < candidateParamClasses.length; i++) {
if (!candidateParamClasses[i].equals(parameterClasses[i])) {
matches = false;
break;
}
}
if (matches) { // finally, check return type
if (m.getReturnType().equals(returnType) )
return m;
}
}
}
}
throw new InternalError("Enclosing method not found");
}
}
private native Object[] getEnclosingMethod0();
private EnclosingMethodInfo getEnclosingMethodInfo() {
Object[] enclosingInfo = getEnclosingMethod0();
if (enclosingInfo == null)
return null;
else {
return new EnclosingMethodInfo(enclosingInfo);
}
}
private final static class EnclosingMethodInfo {
private Class<?> enclosingClass;
private String name;
private String descriptor;
private EnclosingMethodInfo(Object[] enclosingInfo) {
if (enclosingInfo.length != 3)
throw new InternalError("Malformed enclosing method information");
try {
// The array is expected to have three elements:
// the immediately enclosing class
enclosingClass = (Class<?>) enclosingInfo[0];
assert(enclosingClass != null);
// the immediately enclosing method or constructor's
// name (can be null).
name = (String) enclosingInfo[1];
// the immediately enclosing method or constructor's
// descriptor (null iff name is).
descriptor = (String) enclosingInfo[2];
assert((name != null && descriptor != null) || name == descriptor);
} catch (ClassCastException cce) {
throw new InternalError("Invalid type in enclosing method information", cce);
}
}
boolean isPartial() {
return enclosingClass == null || name == null || descriptor == null;
}
boolean isConstructor() { return !isPartial() && "<init>".equals(name); }
boolean isMethod() { return !isPartial() && !isConstructor() && !"<clinit>".equals(name); }
Class<?> getEnclosingClass() { return enclosingClass; }
String getName() { return name; }
String getDescriptor() { return descriptor; }
}
getEnclosingConstructor()
如果该类的对象表示 在一个构造器内的 本地或者匿名类。返回一个Constructor对象。该对象表示底层类的直接封装构造器。
@CallerSensitive
public Constructor<?> getEnclosingConstructor() throws SecurityException {
EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo();
if (enclosingInfo == null)
return null;
else {
if (!enclosingInfo.isConstructor())
return null;
ConstructorRepository typeInfo = ConstructorRepository.make(enclosingInfo.getDescriptor(),
getFactory());
Type [] parameterTypes = typeInfo.getParameterTypes();
Class<?>[] parameterClasses = new Class<?>[parameterTypes.length];
// Convert Types to Classes; returned types *should*
// be class objects since the methodDescriptor's used
// don't have generics information
for(int i = 0; i < parameterClasses.length; i++)
parameterClasses[i] = toClass(parameterTypes[i]);
// Perform access check
Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
enclosingCandidate.checkMemberAccess(Member.DECLARED,
Reflection.getCallerClass(), true);
/*
* Loop over all declared constructors; match number
* of and type of parameters.
*/
for(Constructor<?> c: enclosingCandidate.getDeclaredConstructors()) {
Class<?>[] candidateParamClasses = c.getParameterTypes();
if (candidateParamClasses.length == parameterClasses.length) {
boolean matches = true;
for(int i = 0; i < candidateParamClasses.length; i++) {
if (!candidateParamClasses[i].equals(parameterClasses[i])) {
matches = false;
break;
}
}
if (matches)
return c;
}
}
throw new InternalError("Enclosing constructor not found");
}
}
getDeclaringClass()
如果该对象表示的类或者接口,是一个其他类的成员变量。返回该对象所处的对象。 如果该对象或者接口不是任何其他类的成员变量。那么返回false。 如果该对象表示一个数组类,基础类型或者void,那么会返回null
@CallerSensitive
public Class<?> getDeclaringClass() throws SecurityException {
final Class<?> candidate = getDeclaringClass0();
if (candidate != null)
candidate.checkPackageAccess(
ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
return candidate;
}
private native Class<?> getDeclaringClass0();
注释中的解释如下
* If the class or interface represented by this {@code Class} object
* is a member of another class, returns the {@code Class} object
* representing the class in which it was declared.
getEnclosingClass()
返回底层类的直接封装类。如果底层类是一个顶级的类,返回null。
@CallerSensitive
public Class<?> getEnclosingClass() throws SecurityException {
// There are five kinds of classes (or interfaces):
// a) Top level classes
// b) Nested classes (static member classes)
// c) Inner classes (non-static member classes)
// d) Local classes (named classes declared within a method)
// e) Anonymous classes
// JVM Spec 4.8.6: A class must have an EnclosingMethod
// attribute if and only if it is a local class or an
// anonymous class.
EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo();
Class<?> enclosingCandidate;
if (enclosingInfo == null) {
// This is a top level or a nested class or an inner class (a, b, or c)
enclosingCandidate = getDeclaringClass();
} else {
Class<?> enclosingClass = enclosingInfo.getEnclosingClass();
// This is a local class or an anonymous class (d or e)
if (enclosingClass == this || enclosingClass == null)
throw new InternalError("Malformed enclosing method information");
else
enclosingCandidate = enclosingClass;
}
if (enclosingCandidate != null)
enclosingCandidate.checkPackageAccess(
ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
return enclosingCandidate;
}
getDeclaringClass表示这个内的声明类是哪个,常用于获取在当前中声明的内部类
getEnclosingClass表示获取当前类的外部调用类,也可以用于在内部类中获取外部类.
可以参见此
getSimpleName()
返回底层类的简单名称。这个名称在源代码里有提供。 如果底层类是匿名的,返回false。
public String getSimpleName() {
if (isArray())
return getComponentType().getSimpleName()+"[]";
String simpleName = getSimpleBinaryName();
if (simpleName == null) { // top level class
simpleName = getName();
return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name
}
// According to JLS3 "Binary Compatibility" (13.1) the binary
// name of non-package classes (not top level) is the binary
// name of the immediately enclosing class followed by a '/div> followed by:
// (for nested and inner classes): the simple name.
// (for local classes): 1 or more digits followed by the simple name.
// (for anonymous classes): 1 or more digits.
// Since getSimpleBinaryName() will strip the binary name of
// the immediatly enclosing class, we are now looking at a
// string that matches the regular expression "\$[0-9]*"
// followed by a simple name (considering the simple of an
// anonymous class to be the empty string).
// Remove leading "\$[0-9]*" from the name
int length = simpleName.length();
if (length < 1 || simpleName.charAt(0) != '/div>)
throw new InternalError("Malformed class name");
int index = 1;
while (index < length && isAsciiDigit(simpleName.charAt(index)))
index++;
// Eventually, this is the empty string iff this is an anonymous class
return simpleName.substring(index);
}
getTypeName()
以字符串形式,返回该类型对应的信息。
public String getTypeName() {
if (isArray()) {
try {
Class<?> cl = this;
int dimensions = 0;
while (cl.isArray()) {
dimensions++;
cl = cl.getComponentType();
}
StringBuilder sb = new StringBuilder();
sb.append(cl.getName());
for (int i = 0; i < dimensions; i++) {
sb.append("[]");
}
return sb.toString();
} catch (Throwable e) { /*FALLTHRU*/ }
}
return getName();
}
getCanonicalName()
返回底层类的规范名称,该名称定义在 Java Language Specification。如果底层类没有任何规范的名称,返回null
public String getCanonicalName() {
if (isArray()) {
String canonicalName = getComponentType().getCanonicalName();
if (canonicalName != null)
return canonicalName + "[]";
else
return null;
}
if (isLocalOrAnonymousClass())
return null;
Class<?> enclosingClass = getEnclosingClass();
if (enclosingClass == null) { // top level class
return getName();
} else {
String enclosingName = enclosingClass.getCanonicalName();
if (enclosingName == null)
return null;
return enclosingName + "." + getSimpleName();
}
}
getName()、getCanonicalName()、getSimpleName() 的异同, 比较可以参考此处
isAnonymousClass()
判断是否匿名类。
public boolean isAnonymousClass() {
return "".equals(getSimpleName());
}
isLocalClass()
判断是否局部类
public boolean isLocalClass() {
return isLocalOrAnonymousClass() && !isAnonymousClass();
}
isMemberClass()
判断是否成员类
public boolean isMemberClass() {
return getSimpleBinaryName() != null && !isLocalOrAnonymousClass();
}
getClasses()
返回一个数组,其中包含{@code Class}对象,这些对象表示此{@code Class}对象表示的类的所有公共类和接口。这包括从超类继承的公共类和接口成员,以及由该类声明的公共类和接口成员。如果此{@code Class}对象没有公共成员类或接口,则此方法返回长度为0的数组。如果此{@code Class}对象表示原始类型,数组类或void,则此方法还返回长度为0的数组。
@CallerSensitive
public Class<?>[] getClasses() {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
// Privileged so this implementation can look at DECLARED classes,
// something the caller might not have privilege to do. The code here
// is allowed to look at DECLARED classes because (1) it does not hand
// out anything other than public members and (2) public member access
// has already been ok'd by the SecurityManager.
return java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Class<?>[]>() {
public Class<?>[] run() {
List<Class<?>> list = new ArrayList<>();
Class<?> currentClass = Class.this;
while (currentClass != null) {
Class<?>[] members = currentClass.getDeclaredClasses();
for (int i = 0; i < members.length; i++) {
if (Modifier.isPublic(members[i].getModifiers())) {
list.add(members[i]);
}
}
currentClass = currentClass.getSuperclass();
}
return list.toArray(new Class<?>[0]);
}
});
}