您当前的位置: 首页 >  Java

wespten

暂无认证

  • 1浏览

    0关注

    899博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

深入学习java源码之Class.forName()与 Class.getDeclaredField()

wespten 发布时间:2019-01-27 13:46:18 ,浏览量:1

 深入学习java源码之Class.forName()与 Class.getDeclaredField()

java反射

什么是反射

反射 (Reflection) 是 Java 的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性

简而言之,通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。

反射的核心是 JVM 在运行时才动态加载类或调用方法/访问属性,它不需要事先(写代码的时候或编译期)知道运行对象是谁。

Java 反射主要提供以下功能:

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);
  • 在运行时调用任意一个对象的方法

重点:是运行时而不是编译时

 

反射在运行状态把 Java 类中的各种成分映射成相应相应的 Java 类,可以动态得获取所有的属性以及动态调用任意一个方法。 1).一段java代码在程序的运行期间会经历三个阶段:source-->class-->runtime 2).Class对象 在java中用一个Class对象来表示一个java类的class阶段 Class对象封装了一个java类定义的成员变量、成员方法、构造方法、包名、类名等。 2.反射怎么用 1).获得java类的各个组成部分,首先需要获得代表java类的Class对象 获得Class对象有以下三种方式: Class.forname(className) 用于做类加载

public static Class forName(String className)
``` 
比如在 JDBC 开发中常用此方法加载数据库驱动:
```java
 Class.forName(driver);

obj.getClass() 用于获得对象的类型

StringBuilder str = new StringBuilder("123");
Class klass = str.getClass();

类名.class 用于获得指定的类型,传参用

Class klass = int.class;
Class classInt = Integer.TYPE;

判断是否为某个类的实例

一般地,我们用 instanceof 关键字来判断是否为某个类的实例。同时我们也可以借助反射中 Class 对象的 isInstance() 方法来判断是否为某个类的实例,它是一个 native 方法:

public native boolean isInstance(Object obj);

2).反射类的构造方法,获得实例

使用Class对象的newInstance()方法来创建Class对象对应类的实例。

Class clazz = 类名.class; Constuctor con = clazz.getConstructor(new Class[]{paramClazz1,paramClazz2,.....}); con.newInstance(params....);

Class c = String.class;
Object str = c.newInstance();

先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。这种方法可以用指定的构造器构造类的实例。

//获取String所对应的Class对象
Class c = String.class;
//获取String类带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//根据构造器创建实例
Object obj = constructor.newInstance("23333");
System.out.println(obj);

3).反射类的成员方法

获取某个Class对象的方法集合,主要有以下几个方法:

getDeclaredMethods 方法返回类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

public Method[] getDeclaredMethods() throws SecurityException

 

getMethods 方法返回某个类的所有公用(public)方法,包括其继承类的公用方法。

public Method[] getMethods() throws SecurityException

 

getMethod 方法返回一个特定的方法,其中第一个参数为方法名称,后面的参数为方法的参数对应Class的对象。

public Method getMethod(String name, Class... parameterTypes)

Method m = clazz.getMethod(methodName,new Class[]{paramClazz1,paramClazz2,.....}); m.invoke();

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class test1 {
	public static void test() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
	        Class c = methodClass.class;
	        Object object = c.newInstance();
	        Method[] methods = c.getMethods();
	        Method[] declaredMethods = c.getDeclaredMethods();
	        //获取methodClass类的add方法
	        Method method = c.getMethod("add", int.class, int.class);
	        //getMethods()方法获取的所有方法
	        System.out.println("getMethods获取的方法:");
	        for(Method m:methods)
	            System.out.println(m);
	        //getDeclaredMethods()方法获取的所有方法
	        System.out.println("getDeclaredMethods获取的方法:");
	        for(Method m:declaredMethods)
	            System.out.println(m);
	    }
    }
class methodClass {
    public final int fuck = 3;
    public int add(int a,int b) {
        return a+b;
    }
    public int sub(int a,int b) {
        return a+b;
    }
}
getMethods获取的方法:
public int org.ScZyhSoft.common.methodClass.add(int,int)
public int org.ScZyhSoft.common.methodClass.sub(int,int)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
getDeclaredMethods获取的方法:
public int org.ScZyhSoft.common.methodClass.add(int,int)
public int org.ScZyhSoft.common.methodClass.sub(int,int)

可以看到,通过 getMethods() 获取的方法可以获取到父类的方法,比如 java.lang.Object 下定义的各个方法。

4).反射类的属性

获取构造器信息

获取类构造器的用法与上述获取方法的用法类似。主要是通过Class类的getConstructor方法得到Constructor类的一个实例,而Constructor类有一个newInstance方法可以创建一个对象实例:

public T newInstance(Object ... initargs)

此方法可以根据传入的参数来调用对应的Constructor创建对象实例。

5).反射类的属性

getFiled:访问公有的成员变量

getDeclaredField:所有已声明的成员变量,但不能得到其父类的成员变量

Field field = clazz.getField(fieldName); field.setAccessible(true);//设置为可访问 filed.setObject(value); //设置值 Object value = field.get(clazz); //获得值 Object staticValue = filed.get(Class); //获得静态值

相对而言,反射比内省更容易理解一点。用一句比较白的话来概括,反射就是让你可以通过名称来得到对象(类,属性,方法)的技术。例如我们可以通过类名来生成一个类的实例;知道了方法名,就可以调用这个方法;知道了属性名就可以访问这个属性的值,还是写两个例子让大家更直观的了解反射的使用方法:

通过类名来构造一个类的实例  

Class cls_str=Class.forName("java.lang.String");  
Object str=cls_str.newInstance();  //相当于String str=new String();  
通过方法名来调用一个方法  
String methodName="length";  
Method m=cls_str.getMethod(methodName,null);  
System.out.println("lengthis"+m.invoke(str,null));  
//相当于System.out.println(str.length());  

上面的两个例子是比较常用方法。看到上面的例子就有人要发问了:为什么要这么麻烦呢?本来一条语句就完成的事情干吗要整这么复杂?没错,在上面的例 子中确实没有必要这么麻烦。不过你想像这样一个应用程序,它支持动态的功能扩展,也就是说程序不重新启动但是可以自动加载新的功能,这个功能使用一个具体 类来表示。首先我们必须为这些功能定义一个接口类,然后我们要求所有扩展的功能类必须实现我指定的接口,这个规定了应用程序和可扩展功能之间的接口规则, 但是怎么动态加载呢?我们必须让应用程序知道要扩展的功能类的类名,比如是test.Func1,当我们把这个类名(字符串)告诉应用程序后,它就可以使 用我们第一个例子的方法来加载并启用新的功能。 6).调用方法

当我们从类中获取了一个方法后,我们就可以用 invoke() 方法来调用这个方法。invoke 方法的原型为:

public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
public class test1 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class klass = methodClass.class;
        //创建methodClass的实例
        Object obj = klass.newInstance();
        //获取methodClass类的add方法
        Method method = klass.getMethod("add",int.class,int.class);
        //调用method对应的方法 => add(1,4)
        Object result = method.invoke(obj,1,4);
        System.out.println(result);
    }
}
class methodClass {
    public final int fuck = 3;
    public int add(int a,int b) {
        return a+b;
    }
    public int sub(int a,int b) {
        return a+b;
    }
}

7).利用反射创建数组

数组在Java里是比较特殊的一种类型,它可以赋值给一个Object Reference。下面我们看一看利用反射创建数组的例子:

public static void testArray() throws ClassNotFoundException {
        Class cls = Class.forName("java.lang.String");
        Object array = Array.newInstance(cls,25);
        //往数组里添加内容
        Array.set(array,0,"hello");
        Array.set(array,1,"Java");
        Array.set(array,2,"fuck");
        Array.set(array,3,"Scala");
        Array.set(array,4,"Clojure");
        //获取某一项的内容
        System.out.println(Array.get(array,3));
    }

其中的Array类为java.lang.reflect.Array类。我们通过Array.newInstance()创建数组对象,它的原型是:

public static Object newInstance(Class componentType, int length)
        throws NegativeArraySizeException {
        return newArray(componentType, length);
    }

而 newArray 方法是一个 native 方法,它在 HotSpot JVM 里的具体实现我们后边再研究,这里先把源码贴出来:

private static native Object newArray(Class componentType, int length)
        throws NegativeArraySizeException;

 

反射的一些注意事项

由于反射会额外消耗一定的系统资源,因此如果不需要动态地创建一个对象,那么就不需要用反射。

另外,反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

 

java源码

Modifier and TypeMethod and DescriptionforName(String className)

返回与给定字符串名称的类或接口相关联的 对象。

static 类forName(String name, boolean initialize, ClassLoader loader)

使用给定的类加载器返回与给定字符串名称的类或接口相关联的 对象。

AnnotatedType[]getAnnotatedInterfaces()

返回一个 AnnotatedType对象的数组, AnnotatedType使用类型指定由此 AnnotatedType对象表示的实体的超级

AnnotatedTypegetAnnotatedSuperclass()

返回一个 AnnotatedType对象,该对象表示使用类型来指定由此 对象表示的实体的 类。

AgetAnnotation(类 annotationClass)

返回该元素的,如果这样的注释 ,否则返回null指定类型的注释。

Annotation[]getAnnotations()

返回此元素上 存在的注释。

A[]getAnnotationsByType(类 annotationClass)

返回与此元素相关 联的注释 。

StringgetCanonicalName()

返回由Java语言规范定义的基础类的规范名称。

类[]getClasses()

返回包含一个数组 表示所有的公共类和由此表示的类的成员接口的对象 对象。

ClassLoadergetClassLoader()

返回类的类加载器。

getComponentType()

返回 数组的组件类型的Class。

ConstructorgetConstructor(类... parameterTypes)

返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 函数。

Constructor[]getConstructors()

返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造 对象。

AgetDeclaredAnnotation(类 annotationClass)

如果这样的注释 直接存在 ,则返回指定类型的元素注释,否则返回null。

Annotation[]getDeclaredAnnotations()

返回 直接存在于此元素上的注释。

A[]getDeclaredAnnotationsByType(类 annotationClass)

如果此类注释 直接存在或 间接存在,则返回该元素的注释(指定类型)。

类[]getDeclaredClasses()

返回一个反映所有被这个 对象表示的类的成员声明的类和 对象的数组。

ConstructorgetDeclaredConstructor(类... parameterTypes)

返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 函数。

Constructor[]getDeclaredConstructors()

返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组

FieldgetDeclaredField(String name)

返回一个 Field对象,它反映此表示的类或接口的指定已声明字段 对象。

Field[]getDeclaredFields()

返回的数组 Field对象反映此表示的类或接口声明的所有字段 对象。

方法getDeclaredMethod(String name, 类... parameterTypes)

返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 对象。

方法[]getDeclaredMethods()

返回包含一个数组 方法对象反射的类或接口的所有声明的方法,通过此表示 对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。

getDeclaringClass()

如果由此 对象表示的类或接口是另一个类的成员,则返回表示其声明的类的 对象。

getEnclosingClass()

返回底层类的即时封闭类。

ConstructorgetEnclosingConstructor()

如果此对象表示构造函数中的本地或匿名类,则返回表示底层类的立即封闭构造函数的Constructor对象。

方法getEnclosingMethod()

如果此对象表示方法中的本地或匿名类,则返回表示基础类的即时封闭方法的方法对象。

T[]getEnumConstants()

返回此枚举类的元素,如果此Class对象不表示枚举类型,则返回null。

FieldgetField(String name)

返回一个 Field对象,它反映此表示的类或接口的指定公共成员字段 对象。

Field[]getFields()

返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段 对象。

Type[]getGenericInterfaces()

返回 Type表示通过由该对象所表示的类或接口直接实现的接口秒。

TypegetGenericSuperclass()

返回 Type表示此所表示的实体(类,接口,基本类型或void)的直接超类

类[]getInterfaces()

确定由该对象表示的类或接口实现的接口。

方法getMethod(String name, 类... parameterTypes)

返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法 对象。

方法[]getMethods()

返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 对象,包括那些由类或接口和那些从超类和超接口继承的声明。

intgetModifiers()

返回此类或接口的Java语言修饰符,以整数编码。

StringgetName()

返回由 对象表示的实体(类,接口,数组类,原始类型或空白)的名称,作为 String

软件包getPackage()

获取此类的包。

ProtectionDomaingetProtectionDomain()

返回 ProtectionDomain

URLgetResource(String name)

查找具有给定名称的资源。

InputStreamgetResourceAsStream(String name)

查找具有给定名称的资源。

Object[]getSigners()

获得这个类的签名者。

StringgetSimpleName()

返回源代码中给出的基础类的简单名称。

类[] typeparms = getTypeParameters(); if (typeparms.length > 0) { boolean first = true; sb.append(' caller) throws ClassNotFoundException; @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 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() { public Void run() { c.setAccessible(true); return null; } }); cachedConstructor = c; } catch (NoSuchMethodException e) { throw (InstantiationException) new InstantiationException(getName()).initCause(e); } } Constructor 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; } } private volatile transient Constructor cachedConstructor; private volatile transient Class newInstanceCallerCache; public native boolean isInstance(Object obj); public native boolean isAssignableFrom(Class cls); public native boolean isInterface(); public native boolean isArray(); public native boolean isPrimitive(); public boolean isAnnotation() { return (getModifiers() & ANNOTATION) != 0; } public boolean isSynthetic() { return (getModifiers() & SYNTHETIC) != 0; } public String getName() { String name = this.name; if (name == null) this.name = name = getName0(); return name; } // cache the name to reduce the number of calls into the VM private transient String name; private native String getName0(); @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; } private final ClassLoader classLoader; @SuppressWarnings("unchecked") public TypeVariable[] getTypeParameters() { ClassRepository info = getGenericInfo(); if (info != null) return (TypeVariable[])info.getTypeParameters(); else return (TypeVariable[])new TypeVariable[0]; } public native Class[] getInterfaces() { ReflectionData 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(); public Type[] getGenericInterfaces() { ClassRepository info = getGenericInfo(); return (info == null) ? getInterfaces() : info.getSuperInterfaces(); } public native Class getComponentType(); public native int getModifiers(); public native Object[] getSigners(); native void setSigners(Object[] signers); @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() && "".equals(name); } boolean isMethod() { return !isPartial() && !isConstructor() && !"".equals(name); } Class getEnclosingClass() { return enclosingClass; } String getName() { return name; } String getDescriptor() { return descriptor; } } private static Class toClass(Type o) { if (o instanceof GenericArrayType) return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()), 0) .getClass(); return (Class)o; } @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"); } } @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(); @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; } 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 } 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); } 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(); } private static boolean isAsciiDigit(char c) { return '0' [] getClasses() { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); return java.security.AccessController.doPrivileged( new java.security.PrivilegedAction[] run() { List 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]); } }); } @CallerSensitive public Field[] getFields() throws SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return copyFields(privateGetPublicFields(null)); } @CallerSensitive public Method[] getMethods() throws SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return copyMethods(privateGetPublicMethods()); } @CallerSensitive public Constructor[] getConstructors() throws SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return copyConstructors(privateGetDeclaredConstructors(true)); } @CallerSensitive public Field getField(String name) throws NoSuchFieldException, SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); Field field = getField0(name); if (field == null) { throw new NoSuchFieldException(name); } return field; } @CallerSensitive public Method getMethod(String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); Method method = getMethod0(name, parameterTypes, true); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } return method; } @CallerSensitive public Constructor getConstructor(Class... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return getConstructor0(parameterTypes, Member.PUBLIC); } @CallerSensitive public Class[] getDeclaredClasses() throws SecurityException { checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), false); return getDeclaredClasses0(); } @CallerSensitive public Field[] getDeclaredFields() throws SecurityException { checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); return copyFields(privateGetDeclaredFields(false)); } @CallerSensitive public Method[] getDeclaredMethods() throws SecurityException { checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); return copyMethods(privateGetDeclaredMethods(false)); } @CallerSensitive public Constructor[] getDeclaredConstructors() throws SecurityException { checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); return copyConstructors(privateGetDeclaredConstructors(false)); } @CallerSensitive public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException { checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Field field = searchFields(privateGetDeclaredFields(false), name); if (field == null) { throw new NoSuchFieldException(name); } return field; } @CallerSensitive public Method getDeclaredMethod(String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } return method; } @CallerSensitive public Constructor getDeclaredConstructor(Class... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); return getConstructor0(parameterTypes, Member.DECLARED); } public InputStream getResourceAsStream(String name) { name = resolveName(name); ClassLoader cl = getClassLoader0(); if (cl==null) { // A system class. return ClassLoader.getSystemResourceAsStream(name); } return cl.getResourceAsStream(name); } public java.net.URL getResource(String name) { name = resolveName(name); ClassLoader cl = getClassLoader0(); if (cl==null) { // A system class. return ClassLoader.getSystemResource(name); } return cl.getResource(name); } /** protection domain returned when the internal domain is null */ private static java.security.ProtectionDomain allPermDomain; public java.security.ProtectionDomain getProtectionDomain() { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(SecurityConstants.GET_PD_PERMISSION); } java.security.ProtectionDomain pd = getProtectionDomain0(); if (pd == null) { if (allPermDomain == null) { java.security.Permissions perms = new java.security.Permissions(); perms.add(SecurityConstants.ALL_PERMISSION); allPermDomain = new java.security.ProtectionDomain(null, perms); } pd = allPermDomain; } return pd; } private native java.security.ProtectionDomain getProtectionDomain0(); static native Class getPrimitiveClass(String name); private void checkMemberAccess(int which, Class caller, boolean checkProxyInterfaces) { final SecurityManager s = System.getSecurityManager(); if (s != null) { /* Default policy allows access to all {@link Member#PUBLIC} members, * as well as access to classes that have the same class loader as the caller. * In all other cases, it requires RuntimePermission("accessDeclaredMembers") * permission. */ final ClassLoader ccl = ClassLoader.getClassLoader(caller); final ClassLoader cl = getClassLoader0(); if (which != Member.PUBLIC) { if (ccl != cl) { s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); } } this.checkPackageAccess(ccl, checkProxyInterfaces); } } private void checkPackageAccess(final ClassLoader ccl, boolean checkProxyInterfaces) { final SecurityManager s = System.getSecurityManager(); if (s != null) { final ClassLoader cl = getClassLoader0(); if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { String name = this.getName(); int i = name.lastIndexOf('.'); if (i != -1) { // skip the package access check on a proxy class in default proxy package String pkg = name.substring(0, i); if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) { s.checkPackageAccess(pkg); } } } // check package access on the proxy interfaces if (checkProxyInterfaces && Proxy.isProxyClass(this)) { ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces()); } } } private String resolveName(String name) { if (name == null) { return name; } if (!name.startsWith("/")) { Class c = this; while (c.isArray()) { c = c.getComponentType(); } String baseName = c.getName(); int index = baseName.lastIndexOf('.'); if (index != -1) { name = baseName.substring(0, index).replace('.', '/') +"/"+name; } } else { name = name.substring(1); } return name; } /** * Atomic operations support. */ private static class Atomic { // initialize Unsafe machinery here, since we need to call Class.class instance method // and have to avoid calling it in the static initializer of the Class class... private static final Unsafe unsafe = Unsafe.getUnsafe(); // offset of Class.reflectionData instance field private static final long reflectionDataOffset; // offset of Class.annotationType instance field private static final long annotationTypeOffset; // offset of Class.annotationData instance field private static final long annotationDataOffset; static { Field[] fields = Class.class.getDeclaredFields0(false); // bypass caches reflectionDataOffset = objectFieldOffset(fields, "reflectionData"); annotationTypeOffset = objectFieldOffset(fields, "annotationType"); annotationDataOffset = objectFieldOffset(fields, "annotationData"); } private static long objectFieldOffset(Field[] fields, String fieldName) { Field field = searchFields(fields, fieldName); if (field == null) { throw new Error("No " + fieldName + " field found in java.lang.Class"); } return unsafe.objectFieldOffset(field); } static boolean casReflectionData(Class clazz, SoftReference oldData, SoftReference newData) { return unsafe.compareAndSwapObject(clazz, reflectionDataOffset, oldData, newData); } static boolean casAnnotationType(Class clazz, AnnotationType oldType, AnnotationType newType) { return unsafe.compareAndSwapObject(clazz, annotationTypeOffset, oldType, newType); } static boolean casAnnotationData(Class clazz, AnnotationData oldData, AnnotationData newData) { return unsafe.compareAndSwapObject(clazz, annotationDataOffset, oldData, newData); } } // Caches for certain reflective results private static boolean useCaches = true; // reflection data that might get invalidated when JVM TI RedefineClasses() is called private static class ReflectionData { volatile Field[] declaredFields; volatile Field[] publicFields; volatile Method[] declaredMethods; volatile Method[] publicMethods; volatile Constructor[] declaredConstructors; volatile Constructor[] publicConstructors; // Intermediate results for getFields and getMethods volatile Field[] declaredPublicFields; volatile Method[] declaredPublicMethods; volatile Class[] interfaces; // Value of classRedefinedCount when we created this ReflectionData instance final int redefinedCount; ReflectionData(int redefinedCount) { this.redefinedCount = redefinedCount; } } private volatile transient SoftReference reflectionData; // Incremented by the VM on each call to JVM TI RedefineClasses() // that redefines this class or a superclass. private volatile transient int classRedefinedCount = 0; // Lazily create and cache ReflectionData private ReflectionData reflectionData() { SoftReference reflectionData = this.reflectionData; int classRedefinedCount = this.classRedefinedCount; ReflectionData 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 ReflectionData newReflectionData(SoftReference oldReflectionData, int classRedefinedCount) { if (!useCaches) return null; while (true) { ReflectionData rd = new ReflectionData(classRedefinedCount); // try to CAS it... if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference(rd))) { return rd; } // else retry oldReflectionData = this.reflectionData; classRedefinedCount = this.classRedefinedCount; if (oldReflectionData != null && (rd = oldReflectionData.get()) != null && rd.redefinedCount == classRedefinedCount) { return rd; } } } // Generic signature handling private native String getGenericSignature0(); // Generic info repository; lazily initialized private volatile transient ClassRepository genericInfo; // accessor for factory private GenericsFactory getFactory() { // create scope and factory return CoreReflectionFactory.make(this, ClassScope.make(this)); } // accessor for generic info repository; // generic info is lazily initialized private ClassRepository getGenericInfo() { ClassRepository genericInfo = this.genericInfo; if (genericInfo == null) { String signature = getGenericSignature0(); if (signature == null) { genericInfo = ClassRepository.NONE; } else { genericInfo = ClassRepository.make(signature, getFactory()); } this.genericInfo = genericInfo; } return (genericInfo != ClassRepository.NONE) ? genericInfo : null; } // Annotations handling native byte[] getRawAnnotations(); // Since 1.8 native byte[] getRawTypeAnnotations(); static byte[] getExecutableTypeAnnotationBytes(Executable ex) { return getReflectionFactory().getExecutableTypeAnnotationBytes(ex); } native ConstantPool getConstantPool(); private Field[] privateGetDeclaredFields(boolean publicOnly) { checkInitted(); Field[] res; ReflectionData rd = reflectionData(); if (rd != null) { res = publicOnly ? rd.declaredPublicFields : rd.declaredFields; if (res != null) return res; } // No cached value available; request value from VM res = Reflection.filterFields(this, getDeclaredFields0(publicOnly)); if (rd != null) { if (publicOnly) { rd.declaredPublicFields = res; } else { rd.declaredFields = res; } } return res; } private Field[] privateGetPublicFields(Set c : getInterfaces()) { if (!traversedInterfaces.contains(c)) { traversedInterfaces.add(c); addAll(fields, c.privateGetPublicFields(traversedInterfaces)); } } // Direct superclass, recursively if (!isInterface()) { Class c = getSuperclass(); if (c != null) { addAll(fields, c.privateGetPublicFields(traversedInterfaces)); } } res = new Field[fields.size()]; fields.toArray(res); if (rd != null) { rd.publicFields = res; } return res; } private static void addAll(Collection c, Field[] o) { for (int i = 0; i < o.length; i++) { c.add(o[i]); } } private Constructor[] privateGetDeclaredConstructors(boolean publicOnly) { checkInitted(); Constructor[] res; ReflectionData rd = reflectionData(); if (rd != null) { res = publicOnly ? rd.publicConstructors : rd.declaredConstructors; if (res != null) return res; } // No cached value available; request value from VM if (isInterface()) { @SuppressWarnings("unchecked") Constructor[] temporaryRes = (Constructor[]) new Constructor[0]; res = temporaryRes; } else { res = getDeclaredConstructors0(publicOnly); } if (rd != null) { if (publicOnly) { rd.publicConstructors = res; } else { rd.declaredConstructors = res; } } return res; } private Method[] privateGetDeclaredMethods(boolean publicOnly) { checkInitted(); Method[] res; ReflectionData rd = reflectionData(); if (rd != null) { res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods; if (res != null) return res; } // No cached value available; request value from VM res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly)); if (rd != null) { if (publicOnly) { rd.declaredPublicMethods = res; } else { rd.declaredMethods = res; } } return res; } static class MethodArray { // Don't add or remove methods except by add() or remove() calls. private Method[] methods; private int length; private int defaults; MethodArray() { this(20); } MethodArray(int initialSize) { if (initialSize < 2) throw new IllegalArgumentException("Size should be 2 or more"); methods = new Method[initialSize]; length = 0; defaults = 0; } boolean hasDefaults() { return defaults != 0; } void add(Method m) { if (length == methods.length) { methods = Arrays.copyOf(methods, 2 * methods.length); } methods[length++] = m; if (m != null && m.isDefault()) defaults++; } void addAll(Method[] ma) { for (int i = 0; i < ma.length; i++) { add(ma[i]); } } void addAll(MethodArray ma) { for (int i = 0; i < ma.length(); i++) { add(ma.get(i)); } } void addIfNotPresent(Method newMethod) { for (int i = 0; i < length; i++) { Method m = methods[i]; if (m == newMethod || (m != null && m.equals(newMethod))) { return; } } add(newMethod); } void addAllIfNotPresent(MethodArray newMethods) { for (int i = 0; i < newMethods.length(); i++) { Method m = newMethods.get(i); if (m != null) { addIfNotPresent(m); } } } /* Add Methods declared in an interface to this MethodArray. * Static methods declared in interfaces are not inherited. */ void addInterfaceMethods(Method[] methods) { for (Method candidate : methods) { if (!Modifier.isStatic(candidate.getModifiers())) { add(candidate); } } } int length() { return length; } Method get(int i) { return methods[i]; } Method getFirst() { for (Method m : methods) if (m != null) return m; return null; } void removeByNameAndDescriptor(Method toRemove) { for (int i = 0; i < length; i++) { Method m = methods[i]; if (m != null && matchesNameAndDescriptor(m, toRemove)) { remove(i); } } } private void remove(int i) { if (methods[i] != null && methods[i].isDefault()) defaults--; methods[i] = null; } private boolean matchesNameAndDescriptor(Method m1, Method m2) { return m1.getReturnType() == m2.getReturnType() && m1.getName() == m2.getName() && // name is guaranteed to be interned arrayContentsEq(m1.getParameterTypes(), m2.getParameterTypes()); } void compactAndTrim() { int newPos = 0; // Get rid of null slots for (int pos = 0; pos < length; pos++) { Method m = methods[pos]; if (m != null) { if (pos != newPos) { methods[newPos] = m; } newPos++; } } if (newPos != methods.length) { methods = Arrays.copyOf(methods, newPos); } } void removeLessSpecifics() { if (!hasDefaults()) return; for (int i = 0; i < length; i++) { Method m = get(i); if (m == null || !m.isDefault()) continue; for (int j = 0; j < length; j++) { if (i == j) continue; Method candidate = get(j); if (candidate == null) continue; if (!matchesNameAndDescriptor(m, candidate)) continue; if (hasMoreSpecificClass(m, candidate)) remove(j); } } } Method[] getArray() { return methods; } // Returns true if m1 is more specific than m2 static boolean hasMoreSpecificClass(Method m1, Method m2) { Class m1Class = m1.getDeclaringClass(); Class m2Class = m2.getDeclaringClass(); return m1Class != m2Class && m2Class.isAssignableFrom(m1Class); } } private Method[] privateGetPublicMethods() { checkInitted(); Method[] res; ReflectionData rd = reflectionData(); if (rd != null) { res = rd.publicMethods; if (res != null) return res; } // No cached value available; compute value recursively. // Start by fetching public declared methods MethodArray methods = new MethodArray(); { Method[] tmp = privateGetDeclaredMethods(true); methods.addAll(tmp); } // Now recur over superclass and direct superinterfaces. // Go over superinterfaces first so we can more easily filter // out concrete implementations inherited from superclasses at // the end. MethodArray inheritedMethods = new MethodArray(); for (Class i : getInterfaces()) { inheritedMethods.addInterfaceMethods(i.privateGetPublicMethods()); } if (!isInterface()) { Class c = getSuperclass(); if (c != null) { MethodArray supers = new MethodArray(); supers.addAll(c.privateGetPublicMethods()); // Filter out concrete implementations of any // interface methods for (int i = 0; i < supers.length(); i++) { Method m = supers.get(i); if (m != null && !Modifier.isAbstract(m.getModifiers()) && !m.isDefault()) { inheritedMethods.removeByNameAndDescriptor(m); } } // Insert superclass's inherited methods before // superinterfaces' to satisfy getMethod's search // order supers.addAll(inheritedMethods); inheritedMethods = supers; } } // Filter out all local methods from inherited ones for (int i = 0; i < methods.length(); i++) { Method m = methods.get(i); inheritedMethods.removeByNameAndDescriptor(m); } methods.addAllIfNotPresent(inheritedMethods); methods.removeLessSpecifics(); methods.compactAndTrim(); res = methods.getArray(); if (rd != null) { rd.publicMethods = res; } return res; } private static Field searchFields(Field[] fields, String name) { String internedName = name.intern(); for (int i = 0; i < fields.length; i++) { if (fields[i].getName() == internedName) { return getReflectionFactory().copyField(fields[i]); } } return null; } private Field getField0(String name) throws NoSuchFieldException { // Note: the intent is that the search algorithm this routine // uses be equivalent to the ordering imposed by // privateGetPublicFields(). It fetches only the declared // public fields for each class, however, to reduce the number // of Field objects which have to be created for the common // case where the field being requested is declared in the // class which is being queried. Field res; // Search declared public fields if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { return res; } // Direct superinterfaces, recursively Class[] interfaces = getInterfaces(); for (int i = 0; i < interfaces.length; i++) { Class c = interfaces[i]; if ((res = c.getField0(name)) != null) { return res; } } // Direct superclass, recursively if (!isInterface()) { Class c = getSuperclass(); if (c != null) { if ((res = c.getField0(name)) != null) { return res; } } } return null; } private static Method searchMethods(Method[] methods, String name, Class[] parameterTypes) { Method res = null; String internedName = name.intern(); for (int i = 0; i < methods.length; i++) { Method m = methods[i]; if (m.getName() == internedName && arrayContentsEq(parameterTypes, m.getParameterTypes()) && (res == null || res.getReturnType().isAssignableFrom(m.getReturnType()))) res = m; } return (res == null ? res : getReflectionFactory().copyMethod(res)); } private Method getMethod0(String name, Class[] parameterTypes, boolean includeStaticMethods) { MethodArray interfaceCandidates = new MethodArray(2); Method res = privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates); if (res != null) return res; // Not found on class or superclass directly interfaceCandidates.removeLessSpecifics(); return interfaceCandidates.getFirst(); // may be null } private Method privateGetMethodRecursive(String name, Class[] parameterTypes, boolean includeStaticMethods, MethodArray allInterfaceCandidates) { Method res; // Search declared public methods if ((res = searchMethods(privateGetDeclaredMethods(true), name, parameterTypes)) != null) { if (includeStaticMethods || !Modifier.isStatic(res.getModifiers())) return res; } // Search superclass's methods if (!isInterface()) { Class[] interfaces = getInterfaces(); for (Class c : interfaces) if ((res = c.getMethod0(name, parameterTypes, false)) != null) allInterfaceCandidates.add(res); // Not found return null; } private Constructor getConstructor0(Class[] parameterTypes, int which) throws NoSuchMethodException { Constructor[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC)); for (Constructor constructor : constructors) { if (arrayContentsEq(parameterTypes, constructor.getParameterTypes())) { return getReflectionFactory().copyConstructor(constructor); } } throw new NoSuchMethodException(getName() + "." + argumentTypesToString(parameterTypes)); } private static boolean arrayContentsEq(Object[] a1, Object[] a2) { if (a1 == null) { return a2 == null || a2.length == 0; } if (a2 == null) { return a1.length == 0; } if (a1.length != a2.length) { return false; } for (int i = 0; i < a1.length; i++) { if (a1[i] != a2[i]) { return false; } } return true; } private static Field[] copyFields(Field[] arg) { Field[] out = new Field[arg.length]; ReflectionFactory fact = getReflectionFactory(); for (int i = 0; i < arg.length; i++) { out[i] = fact.copyField(arg[i]); } return out; } private static Method[] copyMethods(Method[] arg) { Method[] out = new Method[arg.length]; ReflectionFactory fact = getReflectionFactory(); for (int i = 0; i < arg.length; i++) { out[i] = fact.copyMethod(arg[i]); } return out; } private static Constructor[] copyConstructors(Constructor[] arg) { Constructor[] out = arg.clone(); ReflectionFactory fact = getReflectionFactory(); for (int i = 0; i < out.length; i++) { out[i] = fact.copyConstructor(out[i]); } return out; } private native Field[] getDeclaredFields0(boolean publicOnly); private native Method[] getDeclaredMethods0(boolean publicOnly); private native Constructor[] getDeclaredConstructors0(boolean publicOnly); private native Class[] getDeclaredClasses0(); private static String argumentTypesToString(Class[] argTypes) { StringBuilder buf = new StringBuilder(); buf.append("("); if (argTypes != null) { for (int i = 0; i < argTypes.length; i++) { if (i > 0) { buf.append(", "); } Class c = argTypes[i]; buf.append((c == null) ? "null" : c.getName()); } } buf.append(")"); return buf.toString(); } /** use serialVersionUID from JDK 1.1 for interoperability */ private static final long serialVersionUID = 3206093459760846163L; private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]; public boolean desiredAssertionStatus() { ClassLoader loader = getClassLoader(); // If the loader is null this is a system class, so ask the VM if (loader == null) return desiredAssertionStatus0(this); // If the classloader has been initialized with the assertion // directives, ask it. Otherwise, ask the VM. synchronized(loader.assertionLock) { if (loader.classAssertionStatus != null) { return loader.desiredAssertionStatus(getName()); } } return desiredAssertionStatus0(this); } // Retrieves the desired assertion status of this class from the VM private static native boolean desiredAssertionStatus0(Class clazz); public boolean isEnum() { // An enum must both directly extend java.lang.Enum and have // the ENUM bit set; classes for specialized enum constants // don't do the former. return (this.getModifiers() & ENUM) != 0 && this.getSuperclass() == java.lang.Enum.class; } // Fetches the factory for reflective objects private static ReflectionFactory getReflectionFactory() { if (reflectionFactory == null) { reflectionFactory = java.security.AccessController.doPrivileged (new sun.reflect.ReflectionFactory.GetReflectionFactoryAction()); } return reflectionFactory; } private static ReflectionFactory reflectionFactory; // To be able to query system properties as soon as they're available private static boolean initted = false; private static void checkInitted() { if (initted) return; AccessController.doPrivileged(new PrivilegedAction() { public Void run() { if (System.out == null) { // java.lang.System not yet fully initialized return null; } // Doesn't use Boolean.getBoolean to avoid class init. String val = System.getProperty("sun.reflect.noCaches"); if (val != null && val.equals("true")) { useCaches = false; } initted = true; return null; } }); } public T[] getEnumConstants() { T[] values = getEnumConstantsShared(); return (values != null) ? values.clone() : null; } T[] getEnumConstantsShared() { if (enumConstants == null) { if (!isEnum()) return null; try { final Method values = getMethod("values"); java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Void run() { values.setAccessible(true); return null; } }); @SuppressWarnings("unchecked") T[] temporaryConstants = (T[])values.invoke(null); enumConstants = temporaryConstants; } // These can happen when users concoct enum-like classes // that don't comply with the enum spec. catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException ex) { return null; } } return enumConstants; } private volatile transient T[] enumConstants = null; Map enumConstantDirectory() { if (enumConstantDirectory == null) { T[] universe = getEnumConstantsShared(); if (universe == null) throw new IllegalArgumentException( getName() + " is not an enum type"); Map m = new HashMap(2 * universe.length); for (T constant : universe) m.put(((Enum)constant).name(), constant); enumConstantDirectory = m; } return enumConstantDirectory; } private volatile transient Map enumConstantDirectory = null; @SuppressWarnings("unchecked") public T cast(Object obj) { if (obj != null && !isInstance(obj)) throw new ClassCastException(cannotCastMsg(obj)); return (T) obj; } private String cannotCastMsg(Object obj) { return "Cannot cast " + obj.getClass().getName() + " to " + getName(); } @SuppressWarnings("unchecked") public Class superClass = getSuperclass(); Map
关注
打赏
1665965058
查看更多评论
0.0529s