听说你想搞懂Class类?别再啃那些干巴巴的文档了!作为在网络安全圈摸爬滚打多年的老兵,我来给你扒一扒这玩意儿的底裤,保证让你看完直呼“卧槽,原来是这么回事!”
public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement
Class这玩意儿,有点意思:
-
构造函数?不存在的!只有个私有的,想自己new一个?JVM第一个不答应!
JVM老大哥说了,Class类对象是它在ClassLoader加载时一手操办的,通过
defineClass
方法,就像捏泥人一样给你捏出来。
// 闲人免进!私有构造函数,禁止外部瞎搞! private Class(ClassLoader loader) { // 初始化classLoader,防止JIT优化时瞎搞,以为它是null。 classLoader = loader; }
-
Java里,每个类都藏着一个对应的Class对象,就像身份证一样。你写了个新类,编译后就会生成一个
.class
文件,这里面就装着这个Class对象。 -
一个class关键字定义的类,内存里只有一个Class对象,实例对象和它之间是多对一的关系。简单说,Class对象就是类的“元数据”,告诉你这个类是什么,能干什么。
-
Class类的实例,说白了,就是运行时给你提供或获取对象类型信息的。
Class文件:JVM的“黑话”?
JVM只认class文件,这是铁律!不管你用啥语言,最终都得变成这玩意儿,才能让JVM“临幸”。
一个class文件,对应着一个类或接口的Class对象实例。但要注意,类或接口不一定非得有对应的磁盘文件,也能直接用类加载器生成。
JVM对class文件格式那叫一个严格!哪个字节代表啥,长度多少,顺序咋排,一点都不能乱!
3.1.1 格式?其实就是一堆二进制!
别被“格式”吓唬住,class文件就是一堆8位字节的二进制流,紧凑地排列在一起,没有任何分隔符。
如果数据项需要超过8位字节,那就按高位在前的方式分割存储。
class文件格式用的是类似C语言结构体的伪结构来存数据,只有两种数据类型:无符号数和表。
-
无符号数:u1、u2、u4、u8,分别代表1个字节、2个字节、4个字节和8个字节的无符号数。用来描述数字、索引引用、数量值,或者UTF-8编码的字符串。
-
表:多个无符号数或其他表组成,以
_info
结尾。用来描述有层次关系的复合结构数据。
说白了,整个class文件就是一张大表!
Class文件格式
从类加载看Class:它就是个“模版”!
类的执行流程:加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载。(验证、准备、解析,统称“类的链接”)
Class对象就是个“类模版”,用来生成多个实例对象。反射,其实就是在获取Class对象及其内部信息,然后反过来控制实例对象。就像黑客控制肉鸡一样,只不过这里控制的是对象。
反射?常用的那些“家伙”!
Java提供了Class类和java.lang.reflect
类库来支持反射。反射包里,常用的类有:
-
java.lang.reflect.Method
:代表类的方法。 -
java.lang.reflect.Field
:代表类的成员变量。 -
java.lang.reflect.Constructor
:代表类的构造器。 -
java.lang.Class
:代表一个类。Class对象表示类加载后在堆中的对象,通过它能获取上面说的那些反射包里的东西。
创建Class类的三种“姿势”
-
运行时类.class:
Class c=Student.class;
-
对象.getClass():
Class c=new Student().getClass();
-
Class.forName():
Class<?> c = Class.forName("com.carl.test.classObject.TestClass");
Class类源码“解剖”:常用方法,一网打尽!
toString()
:我是谁?我在哪?
toString()
把对象转成字符串,格式是:"class"或"interface"+空格+类的全限定名。如果是基本数据类型,就返回类型名;如果是void,就返回"void"。
public String toString() { return (isInterface() ? "interface " : (isPrimitive() ? "" : "class ")) + getName(); }
toGenericString()
:秀出我的“血统”!
toGenericString()
返回描述类的字符串,包括修饰符和泛型参数。格式是:权限修饰符+类类型+全限定类名+泛型参数列表(没有就啥也不显示)。
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()
:召唤神龙!
forName(String className)
返回与给定字符串名称的类或接口关联的Class对象。相当于forName(String name, boolean initialize,ClassLoader loader)
,其中loader
是当前类的类加载器,className
必须是类的全限定名。Class.forName("java.lang.Thread")
会导致Thread
类被初始化。
@CallerSensitive public static Class<?> forName(String className) throws ClassNotFoundException { //获取类加载器,来加载驱动 Class<?> caller = Reflection.getCallerClass(); //forName0方法参数说明:类的全路径名、加载后是否初始化该类、使用哪个类加载器、调用forName方法的类 return forName0(className, true, ClassLoader.getClassLoader(caller), caller); } private static native Class<?> forName0(String name, boolean initialize, ClassLoader loader, Class<?> caller) throws ClassNotFoundException;
forName(String name, boolean initialize,ClassLoader loader)
用给定的类加载器返回与给定字符串名称的类或接口关联的Class对象。
参数说明:
name:类或接口的完全限定名。 initialize:是否初始化,true才初始化。 loader:指定的类加载器。
@CallerSensitive public static Class<?> forName(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException { Class<?> caller = null; SecurityManager sm = System.getSecurityManager(); if (sm != null) { //如果安全管理器不为空,则调用getCallerClass方法进行反射调用,否则避免进行此调用产生的开销 caller = Reflection.getCallerClass(); if (sun.misc.VM.isSystemDomainLoader(loader)) { ClassLoader ccl = ClassLoader.getClassLoader(caller); if (!sun.misc.VM.isSystemDomainLoader(ccl)) { //如果类加载器不为空,则进行安全检查--获取当前类加载器进行权限校验,确保可以可以访问bootstraoClassLoader类加载器 sm.checkPermission( SecurityConstants.GET_CLASSLOADER_PERMISSION); } } } return forName0(name, initialize, loader, caller); }
newInstance()
:我要“变形”!
newInstance()
创建Class对象表示的类的新实例。相当于空参构造器的new实例(String str = new String()
)。
@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. // 构造函数查找 if (cachedConstructor == null) { //如果该类是Class类,则抛出异常,因为Class类本身就没有空参构造器 if (this == Class.class) { throw new IllegalAccessException( "Can not call newInstance() on the Class for java.lang.Class" ); } try { //构造函数的参数值,如果是空,则表示空参构造 Class<?>[] empty = {}; //调用getConstructor0方法,Member.DECLARED表示当前类或接口已声明的方法集合 //这里是抛出NoSuchMethodException的位置,如果找不到空参构造则会抛出异常 final Constructor<T> c = getConstructor0(empty, Member.DECLARED); //不支持访问构造函数检查,必须在这里进行安全检查 java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<Void>() { public Void run() { //检查当前构造函数是否可访问后,设置访问标志 //true为可访问,不需要执行访问检查 //false为不可访问,需要强制执行访问检查 //这里是抛出SecurityException异常的位置 c.setAccessible(true); return null; } }); cachedConstructor = c; } catch (NoSuchMethodException e) { //捕获NoSuchMethodException并抛出InstantiationException异常 throw (InstantiationException) new InstantiationException(getName()).initCause(e); } } Constructor<T> tmpConstructor = cachedConstructor; // 安全检查 //获取权限修饰符 //public=0x00000001 private=0x00000002 protected=0x00000004 int modifiers = tmpConstructor.getModifiers(); //快速检查成员访问权限 //检查当前实例化的类和构造函数是否为public权限,如果不是public,则进入,是public则跳过 if (!Reflection.quickCheckMemberAccess(this, modifiers)) { //获取当前类的反射调用 Class<?> caller = Reflection.getCallerClass(); //如果当前创建的实例和反射调用的类不一样 if (newInstanceCallerCache != caller) { //就会去检查反射调用的类的空参构造函数的访问权限是否是public //这里是抛出IllegalAccessException的位置,确认不可访问,则会抛出异常 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; } }
isAnnotation()
:我是注解吗?
isAnnotation()
判断Class对象是不是注解类型。
public boolean isAnnotation() { return (getModifiers() & ANNOTATION) != 0; }
isSynthetic()
:我是“人造”的吗?
isSynthetic()
判断Class是不是合成类。
public boolean isSynthetic() { return (getModifiers() & SYNTHETIC) != 0; }
getName()
:我的“大名”!
getName()
返回Class对象表示的实体(类、接口、数组、基本类型或void)的名称。
-
引用类型,非数组:返回类的二进制名称(全限定名)。
java System.out.println(String.class.getName()); //输出结果为: java.lang.String
-
基本数据类型或void:返回类型名。
基本数据类型
java System.out.println(short.class.getName()); //输出结果为: short
void
java System.out.println(void.class.getName()); //输出结果为: void
-
数组类型:元素类型名称加上表示数组嵌套深度的'['字符。
元素类型名称编码:
元素类型 编码 boolean Z byte B char C class or Interface Lclassname double D float F int I long J short S class or interface的L表示元素类型名称,className表示全路径名。
例子:
-
基本数据类型的数组
java long[][] test = new long[5][5]; System.out.println(test.getClass().getName()); //输出结果为: [[J //[[表示二维数组,J表示long类型的数组
java int[][] testInt = new int[5][5]; System.out.println(testInt.getClass().getName()); //输出结果为: [[I //[[表示二维数组,I表示int类型的数组
java byte[] testByte = new byte[5]; System.out.println(testByte.getClass().getName()); //输出结果为: [B //[表示一维数组,B表示byte类型的数组
-
引用类型的数组
java String[] testString = new String[5]; System.out.println(testString.getClass().getName()); //输出结果为: [Ljava.lang.String; //[表示一维数组,L表示引用数据类型的数组
java Object[][] testObject = new Object[5][5]; System.out.println(testObject.getClass().getName()); //输出结果为: [[Ljava.lang.Object; //[[表示二维数组,L表示引用数据类型的数组
public String getName() { String name = this.name; if (name == null) this.name = name = getName0(); return name; } // 缓存该名称,减少对虚拟机的调用次数 private transient String name; private native String getName0();
getClassLoader()
:谁“罩着”我?
getClassLoader()
返回当前类的类加载器。
-
如果类由
bootstrapClassLoader
加载,返回null。 -
如果存在安全管理器,会进行权限检查。
-
如果对象表示基本数据类型或void,返回null。
@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; } // 在JVM中初始化,而不是在私有构造函数中初始化 // 该字段从反射接入中过滤,即getDeclaredField()方法,将会抛出NoSuchFieldException异常 private final ClassLoader classLoader;
getTypeParameters()
:我的“基因”!
getTypeParameters()
返回TypeVariable对象的数组,表示泛型声明的类型变量。
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]; }
TypeVariable<Class<ArrayList>>[] typeParameters = ArrayList.class.getTypeParameters(); System.out.println(typeParameters[0]); //输出结果为: E
getGenericSuperclass()
:我的“老子”是谁?
getGenericSuperclass()
返回Type对象,表示Class对象表示的实体的直接父类。
public native Class<? super T> getSuperclass(); 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(); }
Type genericSuperclass = String.class.getGenericSuperclass(); System.out.println(genericSuperclass); //输出结果为: class java.lang.Object
getInterface()
:我的“盟友”!
getInterface()
返回Class对象表示的类或接口实现的接口,不携带泛型参数。
Object[][] testObject = new Object[5][5]; Type[] genericInterfaces1 = testObject.getClass().getGenericInterfaces(); for (Type type : genericInterfaces1){ System.out.println(type); } //输出结果为: interface java.lang.Cloneable interface java.io.Serializable
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(); } } // Lazily create and cache ReflectionData private ReflectionData<T> reflectionData() { SoftReference<ReflectionData<T>> reflectionData = this.reflectionData; int classRedefinedCount = this.classRedefinedCount; ReflectionData<T> rd; if (useCaches && reflectionData != null && (rd = reflectionData.get()) != null && rd.redefinedCount == classRedefinedCount) { return rd; } // else no SoftReference or cleared SoftReference or stale ReflectionData // -> create and replace new instance return newReflectionData(reflectionData, classRedefinedCount); } private native Class<?>[] getInterfaces0();
getGenericInterfaces()
:我的“高级盟友”!
getGenericInterfaces()
返回类或接口的直接实现接口数组,携带泛型参数。
public Type[] getGenericInterfaces() { ClassRepository info = getGenericInfo(); return (info == null) ? getInterfaces() : info.getSuperInterfaces(); }
getPackage()
:我在哪个“地盘”混?
getPackage()
获取类的包名、规范和版本。
public Package getPackage() { return Package.getPackage(this); }
Package aPackage = String.class.getPackage(); System.out.println(aPackage); //输出结果为: package java.lang, Java Platform API Specification, version 1.8
getEnclosingMethod()
:谁把我“包养”了?
getEnclosingMethod()
如果Class对象表示方法中的局部类或匿名类,返回Method对象,表示底层类的直接封闭方法。
@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 static Class<?> toClass(Type o) { if (o instanceof GenericArrayType) return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()), 0) .getClass(); return (Class<?>)o; }
getEnclosingConstructor()
:谁把我“生”出来的?
getEnclosingConstructor()
如果Class对象表示构造函数中的本地类或匿名类,返回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()
:我从哪里来?
getDeclaringClass()
如果Class对象表示的类或接口是另一个类的成员,返回声明它的类的Class对象。
@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();
getEnclosingClass()
:我的“保护伞”是谁?
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; }
getSimpleName()
:我的“小名”!
getSimpleName()
返回Class对象的类名,匿名类返回空字符串,数组返回附加了'[]
'的组件类型名称。
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 // 非包类的名称是直接包含类的二进制名称,后跟'$' // (对于嵌套类或内部类): 类名. // (对于本地类): 1或多个数字后跟类名 // (对于匿名类): 1或多个数字. // 由于getSimpleBinaryName()将去掉立即包含的类的二进制名称,因此我们看到的时一个正则表达式 //"[0-9]"后跟类名的字符串,匿名类的类名为空字符串 //从类名中删除前缀"[0-9]" int length = simpleName.length(); if (length < 1 || simpleName.charAt(0) != '$') 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()
:我的“身份证号”!
getTypeName()
返回类的全限定名,基本类型或void返回对应字符串,数组返回全限定名加[]
或基本类型加[]
。
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()
:我的“官方认证名”!
getCanonicalName()
返回Java语言规范定义的类的规范名称,本地类、匿名类或组件类型没有规范名的数组返回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(); } }
isAnonymousClass()
:我是“无名氏”吗?
isAnonymousClass()
判断是否为匿名类。
public boolean isAnonymousClass() { return "".equals(getSimpleName()); }
isLocalClass()
:我是“本地户口”吗?
isLocalClass()
判断是否是本地类。
public boolean isLocalClass() { return isLocalOrAnonymousClass() && !isAnonymousClass(); }
isMemberClass()
:我是“正式员工”吗?
isMemberClass()
判断是否为成员类。
public boolean isMemberClass() { return getSimpleBinaryName() != null && !isLocalOrAnonymousClass(); }
getClasses()
:我的“朋友圈”!
getClasses()
返回Class对象的类的所有公共类和成员接口。
@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]); } }); }
getFields()
:我的“公开属性”!
getFields()
返回类的所有可访问(public)公共字段Field对象的数组。
@CallerSensitive public Field[] getFields() throws SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return copyFields(privateGetPublicFields(null)); }
getMethods()
:我的“公开技能”!
getMethods()
返回类对象对应类或接口中的所有public方法,包括声明的和继承的。
@CallerSensitive public Method[] getMethods() throws SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return copyMethods(privateGetPublicMethods()); }
//测试类的父类 public class SuperClass { public static void play(){ System.out.println("static play()"); } }
```java //测试类 public class MemberClass { private String name;
private String sex; public String description; public int age; public static void sl
黑客/
原文始发于微信公众号(龙哥网络安全):撕开Class类的神秘面纱:一场来自“网络安全老炮”的深度解剖!
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论