属性
构造方法
/*
* Private constructor. Only the Java Virtual Machine creates Class objects.
* This constructor is not used and prevents the default constructor being
* generated.
*/
private Class(ClassLoader loader, Class<?> arrayComponentType) {
// Initialize final field for classLoader. The initialization value of non-null
// prevents future JIT optimizations from assuming this final field is null.
classLoader = loader;
componentType = arrayComponentType;
}
通用方法
toGenericString
public String toGenericString() {
// isPrimitive 基本数据类型判断 byte short int long float double boolean char
if (isPrimitive()) {
return toString();
} else {
// StringBuffer 线程不安全 StringBuilders 线程安全
StringBuilder sb = new StringBuilder();
Class<?> component = this;
int arrayDepth = 0;
// isArray() 数组判断 do while 必定先执行一次
if (isArray()) {
do {
arrayDepth++;
component = component.getComponentType();
} while (component.isArray());
sb.append(component.getName());
} else {
// Class modifiers are a superset of interface modifiers
int modifiers = getModifiers() & Modifier.classModifiers();
if (modifiers != 0) {
sb.append(Modifier.toString(modifiers));
sb.append(' ');
}
// isAnnotation 是否是注释
if (isAnnotation()) {
sb.append('@');
}
if (isInterface()) { // Note: all annotation interfaces are interfaces
sb.append("interface");
} else {
// isEnum 枚举类型判断
if (isEnum())
sb.append("enum");
else if (isRecord())
sb.append("record");
else
sb.append("class");
}
sb.append(' ');
sb.append(getName());
}
TypeVariable<?>[] typeparms = component.getTypeParameters();
if (typeparms.length > 0) {
sb.append(Arrays.stream(typeparms)
.map(Class::typeVarBounds)
.collect(Collectors.joining(",", "<", ">")));
}
if (arrayDepth > 0) sb.append("[]".repeat(arrayDepth));
return sb.toString();
}
}
typeVarBounds
/**
* 01- TypeVariable ??
*/
static String typeVarBounds(TypeVariable<?> typeVar) {
Type[] bounds = typeVar.getBounds();
if (bounds.length == 1 && bounds[0].equals(Object.class)) {
return typeVar.getName();
} else {
return typeVar.getName() + " extends " +
Arrays.stream(bounds)
.map(Type::getTypeName)
.collect(Collectors.joining(" & "));
}
}
forName
/**
* 静态方法,Class.forName(类名【全类名】)
**/
@CallerSensitive
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
// forName0 本地方法
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
forName(String name, boolean initialize, ClassLoader loader)
/**
* 参数 :
* 01-name 全类名 【java.lang.Class】
* 02-initialize 是否初始化,传值wei true时 对应的Class 将会被初始化
* 03-loader 类加载对象
*/
@CallerSensitive
public static Class<?> forName(String name, boolean initialize,
ClassLoader loader)
throws ClassNotFoundException
{
Class<?> caller = null;
@SuppressWarnings("removal")
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 (loader == null) {
ClassLoader ccl = ClassLoader.getClassLoader(caller);
if (ccl != null) {
sm.checkPermission(
SecurityConstants.GET_CLASSLOADER_PERMISSION); // 获取类加载权限
}
}
}
return forName0(name, initialize, loader, caller);
}
forName(Module module, String name)
/**
* 参数 :
* 01-module 模块化??
*/
@CallerSensitive
public static Class<?> forName(Module module, String name) {
Objects.requireNonNull(module);
Objects.requireNonNull(name);
ClassLoader cl;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
Class<?> caller = Reflection.getCallerClass();
if (caller != null && caller.getModule() != module) {
// if caller is null, Class.forName is the last java frame on the stack.
// java.base has all permissions
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
// module::getClassLoader 这是java8 引入的新特性,表达的意思为 获取 module中的 getClassLoader 方法
PrivilegedAction<ClassLoader> pa = module::getClassLoader;
cl = AccessController.doPrivileged(pa);
} else {
cl = module.getClassLoader();
}
if (cl != null) {
return cl.loadClass(module, name);
} else {
return BootLoader.loadClass(module, name);
}
}
newInstance()
/**
** 此方法被废弃了
*
*/
@CallerSensitive
@Deprecated(since="9")
public T newInstance()
throws InstantiationException, IllegalAccessException
{
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false);
}
// Constructor lookup
Constructor<T> tmpConstructor = cachedConstructor;
if (tmpConstructor == 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 = getReflectionFactory().copyConstructor(
getConstructor0(empty, Member.DECLARED));
// Disable accessibility checks on the constructor
// access check is done with the true caller
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<>() {
public Void run() {
c.setAccessible(true);
return null;
}
});
cachedConstructor = tmpConstructor = c;
} catch (NoSuchMethodException e) {
throw (InstantiationException)
new InstantiationException(getName()).initCause(e);
}
}
try {
Class<?> caller = Reflection.getCallerClass();
return getReflectionFactory().newInstance(tmpConstructor, null, caller);
} catch (InvocationTargetException e) {
Unsafe.getUnsafe().throwException(e.getTargetException());
// Not reached
return null;
}
}
getPackage()
public Package getPackage() {
if (isPrimitive() || isArray()) {
return null;
}
ClassLoader cl = getClassLoader0();
return cl != null ? cl.definePackage(this)
: BootLoader.definePackage(this);
}
getPackageName()
public String getPackageName() {
String pn = this.packageName;
if (pn == null) {
Class<?> c = isArray() ? elementType() : this;
if (c.isPrimitive()) {
pn = "java.lang";
} else {
String cn = c.getName();
int dot = cn.lastIndexOf('.');
pn = (dot != -1) ? cn.substring(0, dot).intern() : "";
}
this.packageName = pn;
}
return pn;
}
getInterfaces()
public Class<?>[] getInterfaces() {
// defensively copy before handing over to user code
return getInterfaces(true);
}
getInterfaces(boolean cloneArray)
private Class<?>[] getInterfaces(boolean cloneArray) {
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 if requested
return cloneArray ? interfaces.clone() : interfaces;
}
}
getGenericInterfaces()
public Type[] getGenericInterfaces() {
ClassRepository info = getGenericInfo();
return (info == null) ? getInterfaces() : info.getSuperInterfaces();
}
getComponentType()
/**
* 当且仅当是数组类型的时候返回对应的Class
**/
public Class<?> getComponentType() {
// Only return for array types. Storage may be reused for Class for instance types.
if (isArray()) {
return componentType;
} else {
return null;
}
}
getEnclosingMethod()
@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
final Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
enclosingCandidate.checkMemberAccess(sm, Member.DECLARED,
Reflection.getCallerClass(), true);
}
Method[] candidates = enclosingCandidate.privateGetDeclaredMethods(false);
/*
* 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.
*/
ReflectionFactory fact = getReflectionFactory();
for (Method m : candidates) {
if (m.getName().equals(enclosingInfo.getName()) &&
arrayContentsEq(parameterClasses,
fact.getExecutableSharedParameterTypes(m))) {
// finally, check return type
if (m.getReturnType().equals(returnType)) {
return fact.copyMethod(m);
}
}
}
throw new InternalError("Enclosing method not found");
}
}
getEnclosingConstructor()
@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
final Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
enclosingCandidate.checkMemberAccess(sm, Member.DECLARED,
Reflection.getCallerClass(), true);
}
Constructor<?>[] candidates = enclosingCandidate
.privateGetDeclaredConstructors(false);
/*
* Loop over all declared constructors; match number
* of and type of parameters.
*/
ReflectionFactory fact = getReflectionFactory();
for (Constructor<?> c : candidates) {
if (arrayContentsEq(parameterClasses,
fact.getExecutableSharedParameterTypes(c))) {
return fact.copyConstructor(c);
}
}
throw new InternalError("Enclosing constructor not found");
}
}
getDeclaringClass()
@CallerSensitive
public Class<?> getDeclaringClass() throws SecurityException {
final Class<?> candidate = getDeclaringClass0();
if (candidate != null) {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
candidate.checkPackageAccess(sm,
ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
}
}
return candidate;
}
getEnclosingClass()
/**
* Returns the immediately enclosing class of the underlying
* class. If the underlying class is a top level class this
* method returns {@code null}.
* @return the immediately enclosing class of the underlying class
* @throws SecurityException
* If a security manager, <i>s</i>, is present and the caller's
* class loader is not the same as or an ancestor of the class
* loader for the enclosing class and invocation of {@link
* SecurityManager#checkPackageAccess s.checkPackageAccess()}
* denies access to the package of the enclosing class
* @since 1.5
*/
@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.7.7: 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 = getDeclaringClass0();
} 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) {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
enclosingCandidate.checkPackageAccess(sm,
ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
}
}
return enclosingCandidate;
}
getSimpleName()
/**
* Returns the simple name of the underlying class as given in the
* source code. An empty string is returned if the underlying class is
* {@linkplain #isAnonymousClass() anonymous}.
* A {@linkplain #isSynthetic() synthetic class}, one not present
* in source code, can have a non-empty name including special
* characters, such as "{@code $}".
*
* <p>The simple name of an {@linkplain #isArray() array class} is the simple name of the
* component type with "[]" appended. In particular the simple
* name of an array class whose component type is anonymous is "[]".
*
* @return the simple name of the underlying class
* @since 1.5
*/
public String getSimpleName() {
ReflectionData<T> rd = reflectionData();
String simpleName = rd.simpleName;
if (simpleName == null) {
rd.simpleName = simpleName = getSimpleName0();
}
return simpleName;
}
getTypeName()
/**
* Return an informative string for the name of this class or interface.
*
* @return an informative string for the name of this class or interface
* @since 1.8
*/
public String getTypeName() {
if (isArray()) {
try {
Class<?> cl = this;
int dimensions = 0;
do {
dimensions++;
cl = cl.getComponentType();
} while (cl.isArray());
return cl.getName() + "[]".repeat(dimensions);
} catch (Throwable e) { /*FALLTHRU*/ }
}
return getName();
}
getCanonicalName()
/**
* Returns the canonical name of the underlying class as
* defined by <cite>The Java Language Specification</cite>.
* Returns {@code null} if the underlying class does not have a canonical
* name. Classes without canonical names include:
* <ul>
* <li>a {@linkplain #isLocalClass() local class}
* <li>a {@linkplain #isAnonymousClass() anonymous class}
* <li>a {@linkplain #isHidden() hidden class}
* <li>an array whose component type does not have a canonical name</li>
* </ul>
*
* @return the canonical name of the underlying class if it exists, and
* {@code null} otherwise.
* @since 1.5
*/
public String getCanonicalName() {
ReflectionData<T> rd = reflectionData();
String canonicalName = rd.canonicalName;
if (canonicalName == null) {
rd.canonicalName = canonicalName = getCanonicalName0();
}
return canonicalName == ReflectionData.NULL_SENTINEL? null : canonicalName;
}
isAnonymousClass()
/**
* Returns {@code true} if and only if the underlying class
* is an anonymous class.
*
* @apiNote
* An anonymous class is not a {@linkplain #isHidden() hidden class}.
*
* @return {@code true} if and only if this class is an anonymous class.
* @since 1.5
* @jls 15.9.5 Anonymous Class Declarations
*/
public boolean isAnonymousClass() {
return !isArray() && isLocalOrAnonymousClass() &&
getSimpleBinaryName0() == null;
}
isLocalClass()
/**
* Returns {@code true} if and only if the underlying class
* is a local class.
*
* @return {@code true} if and only if this class is a local class.
* @since 1.5
* @jls 14.3 Local Class Declarations
*/
public boolean isLocalClass() {
return isLocalOrAnonymousClass() &&
(isArray() || getSimpleBinaryName0() != null);
}
isMemberClass()
/**
* Returns {@code true} if and only if the underlying class
* is a member class.
*
* @return {@code true} if and only if this class is a member class.
* @since 1.5
* @jls 8.5 Member Type Declarations
*/
public boolean isMemberClass() {
return !isLocalOrAnonymousClass() && getDeclaringClass0() != null;
}
getSimpleBinaryName()
/**
* Returns the "simple binary name" of the underlying class, i.e.,
* the binary name without the leading enclosing class name.
* Returns {@code null} if the underlying class is a top level
* class.
*/
private String getSimpleBinaryName() {
if (isTopLevelClass())
return null;
String name = getSimpleBinaryName0();
if (name == null) // anonymous class
return "";
return name;
}
isTopLevelClass()
/**
* Returns {@code true} if this is a top level class. Returns {@code false}
* otherwise.
*/
private boolean isTopLevelClass() {
return !isLocalOrAnonymousClass() && getDeclaringClass0() == null;
}
isLocalOrAnonymousClass()
/**
* Returns {@code true} if this is a local class or an anonymous
* class. Returns {@code false} otherwise.
*/
private boolean isLocalOrAnonymousClass() {
// JVM Spec 4.7.7: A class must have an EnclosingMethod
// attribute if and only if it is a local class or an
// anonymous class.
return hasEnclosingMethodInfo();
}
getClasses()
/**
* Returns an array containing {@code Class} objects representing all
* the public classes and interfaces that are members of the class
* represented by this {@code Class} object. This includes public
* class and interface members inherited from superclasses and public class
* and interface members declared by the class. This method returns an
* array of length 0 if this {@code Class} object has no public member
* classes or interfaces. This method also returns an array of length 0 if
* this {@code Class} object represents a primitive type, an array
* class, or void.
*
* @return the array of {@code Class} objects representing the public
* members of this class
* @throws SecurityException
* If a security manager, <i>s</i>, is present and
* the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class.
*
* @since 1.1
*/
@SuppressWarnings("removal")
@CallerSensitive
public Class<?>[] getClasses() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, 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<>() {
public Class<?>[] run() {
List<Class<?>> list = new ArrayList<>();
Class<?> currentClass = Class.this;
while (currentClass != null) {
for (Class<?> m : currentClass.getDeclaredClasses()) {
if (Modifier.isPublic(m.getModifiers())) {
list.add(m);
}
}
currentClass = currentClass.getSuperclass();
}
return list.toArray(new Class<?>[0]);
}
});
}
getFields()
/**
* Returns an array containing {@code Field} objects reflecting all
* the accessible public fields of the class or interface represented by
* this {@code Class} object.
*
* <p> If this {@code Class} object represents a class or interface with
* no accessible public fields, then this method returns an array of length
* 0.
*
* <p> If this {@code Class} object represents a class, then this method
* returns the public fields of the class and of all its superclasses and
* superinterfaces.
*
* <p> If this {@code Class} object represents an interface, then this
* method returns the fields of the interface and of all its
* superinterfaces.
*
* <p> If this {@code Class} object represents an array type, a primitive
* type, or void, then this method returns an array of length 0.
*
* <p> The elements in the returned array are not sorted and are not in any
* particular order.
*
* @return the array of {@code Field} objects representing the
* public fields
* @throws SecurityException
* If a security manager, <i>s</i>, is present and
* the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class.
*
* @since 1.1
* @jls 8.2 Class Members
* @jls 8.3 Field Declarations
*/
@CallerSensitive
public Field[] getFields() throws SecurityException {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
}
return copyFields(privateGetPublicFields());
}
getMethods()
/**
* Returns an array containing {@code Method} objects reflecting all the
* public methods of the class or interface represented by this {@code
* Class} object, including those declared by the class or interface and
* those inherited from superclasses and superinterfaces.
*
* <p> If this {@code Class} object represents an array type, then the
* returned array has a {@code Method} object for each of the public
* methods inherited by the array type from {@code Object}. It does not
* contain a {@code Method} object for {@code clone()}.
*
* <p> If this {@code Class} object represents an interface then the
* returned array does not contain any implicitly declared methods from
* {@code Object}. Therefore, if no methods are explicitly declared in
* this interface or any of its superinterfaces then the returned array
* has length 0. (Note that a {@code Class} object which represents a class
* always has public methods, inherited from {@code Object}.)
*
* <p> The returned array never contains methods with names "{@code <init>}"
* or "{@code <clinit>}".
*
* <p> The elements in the returned array are not sorted and are not in any
* particular order.
*
* <p> Generally, the result is computed as with the following 4 step algorithm.
* Let C be the class or interface represented by this {@code Class} object:
* <ol>
* <li> A union of methods is composed of:
* <ol type="a">
* <li> C's declared public instance and static methods as returned by
* {@link #getDeclaredMethods()} and filtered to include only public
* methods.</li>
* <li> If C is a class other than {@code Object}, then include the result
* of invoking this algorithm recursively on the superclass of C.</li>
* <li> Include the results of invoking this algorithm recursively on all
* direct superinterfaces of C, but include only instance methods.</li>
* </ol></li>
* <li> Union from step 1 is partitioned into subsets of methods with same
* signature (name, parameter types) and return type.</li>
* <li> Within each such subset only the most specific methods are selected.
* Let method M be a method from a set of methods with same signature
* and return type. M is most specific if there is no such method
* N != M from the same set, such that N is more specific than M.
* N is more specific than M if:
* <ol type="a">
* <li> N is declared by a class and M is declared by an interface; or</li>
* <li> N and M are both declared by classes or both by interfaces and
* N's declaring type is the same as or a subtype of M's declaring type
* (clearly, if M's and N's declaring types are the same type, then
* M and N are the same method).</li>
* </ol></li>
* <li> The result of this algorithm is the union of all selected methods from
* step 3.</li>
* </ol>
*
* @apiNote There may be more than one method with a particular name
* and parameter types in a class because while the Java language forbids a
* class to declare multiple methods with the same signature but different
* return types, the Java virtual machine does not. This
* increased flexibility in the virtual machine can be used to
* implement various language features. For example, covariant
* returns can be implemented with {@linkplain
* java.lang.reflect.Method#isBridge bridge methods}; the bridge
* method and the overriding method would have the same
* signature but different return types.
*
* @return the array of {@code Method} objects representing the
* public methods of this class
* @throws SecurityException
* If a security manager, <i>s</i>, is present and
* the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class.
*
* @jls 8.2 Class Members
* @jls 8.4 Method Declarations
* @since 1.1
*/
@CallerSensitive
public Method[] getMethods() throws SecurityException {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
}
return copyMethods(privateGetPublicMethods());
}
getConstructors()
/**
* Returns an array containing {@code Constructor} objects reflecting
* all the public constructors of the class represented by this
* {@code Class} object. An array of length 0 is returned if the
* class has no public constructors, or if the class is an array class, or
* if the class reflects a primitive type or void.
*
* @apiNote
* While this method returns an array of {@code
* Constructor<T>} objects (that is an array of constructors from
* this class), the return type of this method is {@code
* Constructor<?>[]} and <em>not</em> {@code Constructor<T>[]} as
* might be expected. This less informative return type is
* necessary since after being returned from this method, the
* array could be modified to hold {@code Constructor} objects for
* different classes, which would violate the type guarantees of
* {@code Constructor<T>[]}.
*
* @return the array of {@code Constructor} objects representing the
* public constructors of this class
* @throws SecurityException
* If a security manager, <i>s</i>, is present and
* the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class.
*
* @since 1.1
*/
@CallerSensitive
public Constructor<?>[] getConstructors() throws SecurityException {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
}
return copyConstructors(privateGetDeclaredConstructors(true));
}
getField(String name)
/**
* Returns a {@code Field} object that reflects the specified public member
* field of the class or interface represented by this {@code Class}
* object. The {@code name} parameter is a {@code String} specifying the
* simple name of the desired field.
*
* <p> The field to be reflected is determined by the algorithm that
* follows. Let C be the class or interface represented by this {@code Class} object:
*
* <OL>
* <LI> If C declares a public field with the name specified, that is the
* field to be reflected.</LI>
* <LI> If no field was found in step 1 above, this algorithm is applied
* recursively to each direct superinterface of C. The direct
* superinterfaces are searched in the order they were declared.</LI>
* <LI> If no field was found in steps 1 and 2 above, and C has a
* superclass S, then this algorithm is invoked recursively upon S.
* If C has no superclass, then a {@code NoSuchFieldException}
* is thrown.</LI>
* </OL>
*
* <p> If this {@code Class} object represents an array type, then this
* method does not find the {@code length} field of the array type.
*
* @param name the field name
* @return the {@code Field} object of this class specified by
* {@code name}
* @throws NoSuchFieldException if a field with the specified name is
* not found.
* @throws NullPointerException if {@code name} is {@code null}
* @throws SecurityException
* If a security manager, <i>s</i>, is present and
* the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class.
*
* @since 1.1
* @jls 8.2 Class Members
* @jls 8.3 Field Declarations
*/
@CallerSensitive
public Field getField(String name)
throws NoSuchFieldException, SecurityException {
Objects.requireNonNull(name);
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
}
Field field = getField0(name);
if (field == null) {
throw new NoSuchFieldException(name);
}
return getReflectionFactory().copyField(field);
}
getMethod(String name, Class<?>… parameterTypes)
/**
* Returns a {@code Method} object that reflects the specified public
* member method of the class or interface represented by this
* {@code Class} object. The {@code name} parameter is a
* {@code String} specifying the simple name of the desired method. The
* {@code parameterTypes} parameter is an array of {@code Class}
* objects that identify the method's formal parameter types, in declared
* order. If {@code parameterTypes} is {@code null}, it is
* treated as if it were an empty array.
*
* <p> If this {@code Class} object represents an array type, then this
* method finds any public method inherited by the array type from
* {@code Object} except method {@code clone()}.
*
* <p> If this {@code Class} object represents an interface then this
* method does not find any implicitly declared method from
* {@code Object}. Therefore, if no methods are explicitly declared in
* this interface or any of its superinterfaces, then this method does not
* find any method.
*
* <p> This method does not find any method with name "{@code <init>}" or
* "{@code <clinit>}".
*
* <p> Generally, the method to be reflected is determined by the 4 step
* algorithm that follows.
* Let C be the class or interface represented by this {@code Class} object:
* <ol>
* <li> A union of methods is composed of:
* <ol type="a">
* <li> C's declared public instance and static methods as returned by
* {@link #getDeclaredMethods()} and filtered to include only public
* methods that match given {@code name} and {@code parameterTypes}</li>
* <li> If C is a class other than {@code Object}, then include the result
* of invoking this algorithm recursively on the superclass of C.</li>
* <li> Include the results of invoking this algorithm recursively on all
* direct superinterfaces of C, but include only instance methods.</li>
* </ol></li>
* <li> This union is partitioned into subsets of methods with same
* return type (the selection of methods from step 1 also guarantees that
* they have the same method name and parameter types).</li>
* <li> Within each such subset only the most specific methods are selected.
* Let method M be a method from a set of methods with same VM
* signature (return type, name, parameter types).
* M is most specific if there is no such method N != M from the same
* set, such that N is more specific than M. N is more specific than M
* if:
* <ol type="a">
* <li> N is declared by a class and M is declared by an interface; or</li>
* <li> N and M are both declared by classes or both by interfaces and
* N's declaring type is the same as or a subtype of M's declaring type
* (clearly, if M's and N's declaring types are the same type, then
* M and N are the same method).</li>
* </ol></li>
* <li> The result of this algorithm is chosen arbitrarily from the methods
* with most specific return type among all selected methods from step 3.
* Let R be a return type of a method M from the set of all selected methods
* from step 3. M is a method with most specific return type if there is
* no such method N != M from the same set, having return type S != R,
* such that S is a subtype of R as determined by
* R.class.{@link #isAssignableFrom}(S.class).
* </ol>
*
* @apiNote There may be more than one method with matching name and
* parameter types in a class because while the Java language forbids a
* class to declare multiple methods with the same signature but different
* return types, the Java virtual machine does not. This
* increased flexibility in the virtual machine can be used to
* implement various language features. For example, covariant
* returns can be implemented with {@linkplain
* java.lang.reflect.Method#isBridge bridge methods}; the bridge
* method and the overriding method would have the same
* signature but different return types. This method would return the
* overriding method as it would have a more specific return type.
*
* @param name the name of the method
* @param parameterTypes the list of parameters
* @return the {@code Method} object that matches the specified
* {@code name} and {@code parameterTypes}
* @throws NoSuchMethodException if a matching method is not found
* or if the name is "<init>"or "<clinit>".
* @throws NullPointerException if {@code name} is {@code null}
* @throws SecurityException
* If a security manager, <i>s</i>, is present and
* the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class.
*
* @jls 8.2 Class Members
* @jls 8.4 Method Declarations
* @since 1.1
*/
@CallerSensitive
public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
Objects.requireNonNull(name);
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
}
Method method = getMethod0(name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(methodToString(name, parameterTypes));
}
return getReflectionFactory().copyMethod(method);
}
getConstructor(Class<?>… parameterTypes)
/**
* Returns a {@code Constructor} object that reflects the specified
* public constructor of the class represented by this {@code Class}
* object. The {@code parameterTypes} parameter is an array of
* {@code Class} objects that identify the constructor's formal
* parameter types, in declared order.
*
* If this {@code Class} object represents an inner class
* declared in a non-static context, the formal parameter types
* include the explicit enclosing instance as the first parameter.
*
* <p> The constructor to reflect is the public constructor of the class
* represented by this {@code Class} object whose formal parameter
* types match those specified by {@code parameterTypes}.
*
* @param parameterTypes the parameter array
* @return the {@code Constructor} object of the public constructor that
* matches the specified {@code parameterTypes}
* @throws NoSuchMethodException if a matching method is not found.
* @throws SecurityException
* If a security manager, <i>s</i>, is present and
* the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class.
*
* @since 1.1
*/
@CallerSensitive
public Constructor<T> getConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException
{
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
}
return getReflectionFactory().copyConstructor(
getConstructor0(parameterTypes, Member.PUBLIC));
}
getDeclaredClasses()
/**
* Returns an array of {@code Class} objects reflecting all the
* classes and interfaces declared as members of the class represented by
* this {@code Class} object. This includes public, protected, default
* (package) access, and private classes and interfaces declared by the
* class, but excludes inherited classes and interfaces. This method
* returns an array of length 0 if the class declares no classes or
* interfaces as members, or if this {@code Class} object represents a
* primitive type, an array class, or void.
*
* @return the array of {@code Class} objects representing all the
* declared members of this class
* @throws SecurityException
* If a security manager, <i>s</i>, is present and any of the
* following conditions is met:
*
* <ul>
*
* <li> the caller's class loader is not the same as the
* class loader of this class and invocation of
* {@link SecurityManager#checkPermission
* s.checkPermission} method with
* {@code RuntimePermission("accessDeclaredMembers")}
* denies access to the declared classes within this class
*
* <li> the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class
*
* </ul>
*
* @since 1.1
* @jls 8.5 Member Type Declarations
*/
@CallerSensitive
public Class<?>[] getDeclaredClasses() throws SecurityException {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), false);
}
return getDeclaredClasses0();
}
getDeclaredFields()
/**
* Returns an array of {@code Field} objects reflecting all the fields
* declared by the class or interface represented by this
* {@code Class} object. This includes public, protected, default
* (package) access, and private fields, but excludes inherited fields.
*
* <p> If this {@code Class} object represents a class or interface with no
* declared fields, then this method returns an array of length 0.
*
* <p> If this {@code Class} object represents an array type, a primitive
* type, or void, then this method returns an array of length 0.
*
* <p> The elements in the returned array are not sorted and are not in any
* particular order.
*
* @return the array of {@code Field} objects representing all the
* declared fields of this class
* @throws SecurityException
* If a security manager, <i>s</i>, is present and any of the
* following conditions is met:
*
* <ul>
*
* <li> the caller's class loader is not the same as the
* class loader of this class and invocation of
* {@link SecurityManager#checkPermission
* s.checkPermission} method with
* {@code RuntimePermission("accessDeclaredMembers")}
* denies access to the declared fields within this class
*
* <li> the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class
*
* </ul>
*
* @since 1.1
* @jls 8.2 Class Members
* @jls 8.3 Field Declarations
*/
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
}
return copyFields(privateGetDeclaredFields(false));
}
getRecordComponents()
/**
* Returns an array of {@code RecordComponent} objects representing all the
* record components of this record class, or {@code null} if this class is
* not a record class.
*
* <p> The components are returned in the same order that they are declared
* in the record header. The array is empty if this record class has no
* components. If the class is not a record class, that is {@link
* #isRecord()} returns {@code false}, then this method returns {@code null}.
* Conversely, if {@link #isRecord()} returns {@code true}, then this method
* returns a non-null value.
*
* @apiNote
* <p> The following method can be used to find the record canonical constructor:
*
* <pre>{@code
* static <T extends Record> Constructor<T> getCanonicalConstructor(Class<T> cls)
* throws NoSuchMethodException {
* Class<?>[] paramTypes =
* Arrays.stream(cls.getRecordComponents())
* .map(RecordComponent::getType)
* .toArray(Class<?>[]::new);
* return cls.getDeclaredConstructor(paramTypes);
* }}</pre>
*
* @return An array of {@code RecordComponent} objects representing all the
* record components of this record class, or {@code null} if this
* class is not a record class
* @throws SecurityException
* If a security manager, <i>s</i>, is present and any of the
* following conditions is met:
*
* <ul>
*
* <li> the caller's class loader is not the same as the
* class loader of this class and invocation of
* {@link SecurityManager#checkPermission
* s.checkPermission} method with
* {@code RuntimePermission("accessDeclaredMembers")}
* denies access to the declared methods within this class
*
* <li> the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class
*
* </ul>
*
* @jls 8.10 Record Classes
* @since 16
*/
@CallerSensitive
public RecordComponent[] getRecordComponents() {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
}
if (!isRecord()) {
return null;
}
return getRecordComponents0();
}
getDeclaredMethods()
/**
* Returns an array containing {@code Method} objects reflecting all the
* declared methods of the class or interface represented by this {@code
* Class} object, including public, protected, default (package)
* access, and private methods, but excluding inherited methods.
* The declared methods may include methods <em>not</em> in the
* source of the class or interface, including {@linkplain
* Method#isBridge bridge methods} and other {@linkplain
* Executable#isSynthetic synthetic} methods added by compilers.
*
* <p> If this {@code Class} object represents a class or interface that
* has multiple declared methods with the same name and parameter types,
* but different return types, then the returned array has a {@code Method}
* object for each such method.
*
* <p> If this {@code Class} object represents a class or interface that
* has a class initialization method {@code <clinit>}, then the returned
* array does <em>not</em> have a corresponding {@code Method} object.
*
* <p> If this {@code Class} object represents a class or interface with no
* declared methods, then the returned array has length 0.
*
* <p> If this {@code Class} object represents an array type, a primitive
* type, or void, then the returned array has length 0.
*
* <p> The elements in the returned array are not sorted and are not in any
* particular order.
*
* @return the array of {@code Method} objects representing all the
* declared methods of this class
* @throws SecurityException
* If a security manager, <i>s</i>, is present and any of the
* following conditions is met:
*
* <ul>
*
* <li> the caller's class loader is not the same as the
* class loader of this class and invocation of
* {@link SecurityManager#checkPermission
* s.checkPermission} method with
* {@code RuntimePermission("accessDeclaredMembers")}
* denies access to the declared methods within this class
*
* <li> the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class
*
* </ul>
*
* @jls 8.2 Class Members
* @jls 8.4 Method Declarations
* @see <a
* href="{@docRoot}/java.base/java/lang/reflect/package-summary.html#LanguageJvmModel">Java
* programming language and JVM modeling in core reflection</a>
* @since 1.1
*/
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
}
return copyMethods(privateGetDeclaredMethods(false));
}
getDeclaredConstructors()
/**
* Returns an array of {@code Constructor} objects reflecting all the
* constructors declared by the class represented by this
* {@code Class} object. These are public, protected, default
* (package) access, and private constructors. The elements in the array
* returned are not sorted and are not in any particular order. If the
* class has a default constructor, it is included in the returned array.
* This method returns an array of length 0 if this {@code Class}
* object represents an interface, a primitive type, an array class, or
* void.
*
* <p> See <cite>The Java Language Specification</cite>,
* section {@jls 8.2}.
*
* @return the array of {@code Constructor} objects representing all the
* declared constructors of this class
* @throws SecurityException
* If a security manager, <i>s</i>, is present and any of the
* following conditions is met:
*
* <ul>
*
* <li> the caller's class loader is not the same as the
* class loader of this class and invocation of
* {@link SecurityManager#checkPermission
* s.checkPermission} method with
* {@code RuntimePermission("accessDeclaredMembers")}
* denies access to the declared constructors within this class
*
* <li> the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class
*
* </ul>
*
* @since 1.1
* @jls 8.8 Constructor Declarations
*/
@CallerSensitive
public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
}
return copyConstructors(privateGetDeclaredConstructors(false));
}
getDeclaredField(String name)
/**
* Returns a {@code Field} object that reflects the specified declared
* field of the class or interface represented by this {@code Class}
* object. The {@code name} parameter is a {@code String} that specifies
* the simple name of the desired field.
*
* <p> If this {@code Class} object represents an array type, then this
* method does not find the {@code length} field of the array type.
*
* @param name the name of the field
* @return the {@code Field} object for the specified field in this
* class
* @throws NoSuchFieldException if a field with the specified name is
* not found.
* @throws NullPointerException if {@code name} is {@code null}
* @throws SecurityException
* If a security manager, <i>s</i>, is present and any of the
* following conditions is met:
*
* <ul>
*
* <li> the caller's class loader is not the same as the
* class loader of this class and invocation of
* {@link SecurityManager#checkPermission
* s.checkPermission} method with
* {@code RuntimePermission("accessDeclaredMembers")}
* denies access to the declared field
*
* <li> the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class
*
* </ul>
*
* @since 1.1
* @jls 8.2 Class Members
* @jls 8.3 Field Declarations
*/
@CallerSensitive
public Field getDeclaredField(String name)
throws NoSuchFieldException, SecurityException {
Objects.requireNonNull(name);
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
}
Field field = searchFields(privateGetDeclaredFields(false), name);
if (field == null) {
throw new NoSuchFieldException(name);
}
return getReflectionFactory().copyField(field);
}
getDeclaredMethod(String name, Class<?>… parameterTypes)
/**
* Returns a {@code Method} object that reflects the specified
* declared method of the class or interface represented by this
* {@code Class} object. The {@code name} parameter is a
* {@code String} that specifies the simple name of the desired
* method, and the {@code parameterTypes} parameter is an array of
* {@code Class} objects that identify the method's formal parameter
* types, in declared order. If more than one method with the same
* parameter types is declared in a class, and one of these methods has a
* return type that is more specific than any of the others, that method is
* returned; otherwise one of the methods is chosen arbitrarily. If the
* name is "<init>"or "<clinit>" a {@code NoSuchMethodException}
* is raised.
*
* <p> If this {@code Class} object represents an array type, then this
* method does not find the {@code clone()} method.
*
* @param name the name of the method
* @param parameterTypes the parameter array
* @return the {@code Method} object for the method of this class
* matching the specified name and parameters
* @throws NoSuchMethodException if a matching method is not found.
* @throws NullPointerException if {@code name} is {@code null}
* @throws SecurityException
* If a security manager, <i>s</i>, is present and any of the
* following conditions is met:
*
* <ul>
*
* <li> the caller's class loader is not the same as the
* class loader of this class and invocation of
* {@link SecurityManager#checkPermission
* s.checkPermission} method with
* {@code RuntimePermission("accessDeclaredMembers")}
* denies access to the declared method
*
* <li> the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class
*
* </ul>
*
* @jls 8.2 Class Members
* @jls 8.4 Method Declarations
* @since 1.1
*/
@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
Objects.requireNonNull(name);
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
}
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(methodToString(name, parameterTypes));
}
return getReflectionFactory().copyMethod(method);
}
getDeclaredPublicMethods(String name, Class<?>… parameterTypes)
/**
* Returns the list of {@code Method} objects for the declared public
* methods of this class or interface that have the specified method name
* and parameter types.
*
* @param name the name of the method
* @param parameterTypes the parameter array
* @return the list of {@code Method} objects for the public methods of
* this class matching the specified name and parameters
*/
List<Method> getDeclaredPublicMethods(String name, Class<?>... parameterTypes) {
Method[] methods = privateGetDeclaredMethods(/* publicOnly */ true);
ReflectionFactory factory = getReflectionFactory();
List<Method> result = new ArrayList<>();
for (Method method : methods) {
if (method.getName().equals(name)
&& Arrays.equals(
factory.getExecutableSharedParameterTypes(method),
parameterTypes)) {
result.add(factory.copyMethod(method));
}
}
return result;
}
getDeclaredConstructor(Class<?>… parameterTypes)
/**
* Returns a {@code Constructor} object that reflects the specified
* constructor of the class or interface represented by this
* {@code Class} object. The {@code parameterTypes} parameter is
* an array of {@code Class} objects that identify the constructor's
* formal parameter types, in declared order.
*
* If this {@code Class} object represents an inner class
* declared in a non-static context, the formal parameter types
* include the explicit enclosing instance as the first parameter.
*
* @param parameterTypes the parameter array
* @return The {@code Constructor} object for the constructor with the
* specified parameter list
* @throws NoSuchMethodException if a matching method is not found.
* @throws SecurityException
* If a security manager, <i>s</i>, is present and any of the
* following conditions is met:
*
* <ul>
*
* <li> the caller's class loader is not the same as the
* class loader of this class and invocation of
* {@link SecurityManager#checkPermission
* s.checkPermission} method with
* {@code RuntimePermission("accessDeclaredMembers")}
* denies access to the declared constructor
*
* <li> the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class
*
* </ul>
*
* @since 1.1
*/
@CallerSensitive
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException
{
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
}
return getReflectionFactory().copyConstructor(
getConstructor0(parameterTypes, Member.DECLARED));
}
getResourceAsStream(String name)
/**
* Finds a resource with a given name.
*
* <p> If this class is in a named {@link Module Module} then this method
* will attempt to find the resource in the module. This is done by
* delegating to the module's class loader {@link
* ClassLoader#findResource(String,String) findResource(String,String)}
* method, invoking it with the module name and the absolute name of the
* resource. Resources in named modules are subject to the rules for
* encapsulation specified in the {@code Module} {@link
* Module#getResourceAsStream getResourceAsStream} method and so this
* method returns {@code null} when the resource is a
* non-"{@code .class}" resource in a package that is not open to the
* caller's module.
*
* <p> Otherwise, if this class is not in a named module then the rules for
* searching resources associated with a given class are implemented by the
* defining {@linkplain ClassLoader class loader} of the class. This method
* delegates to this {@code Class} object's class loader.
* If this {@code Class} object was loaded by the bootstrap class loader,
* the method delegates to {@link ClassLoader#getSystemResourceAsStream}.
*
* <p> Before delegation, an absolute resource name is constructed from the
* given resource name using this algorithm:
*
* <ul>
*
* <li> If the {@code name} begins with a {@code '/'}
* (<code>'\u002f'</code>), then the absolute name of the resource is the
* portion of the {@code name} following the {@code '/'}.
*
* <li> Otherwise, the absolute name is of the following form:
*
* <blockquote>
* {@code modified_package_name/name}
* </blockquote>
*
* <p> Where the {@code modified_package_name} is the package name of this
* object with {@code '/'} substituted for {@code '.'}
* (<code>'\u002e'</code>).
*
* </ul>
*
* @param name name of the desired resource
* @return A {@link java.io.InputStream} object; {@code null} if no
* resource with this name is found, the resource is in a package
* that is not {@linkplain Module#isOpen(String, Module) open} to at
* least the caller module, or access to the resource is denied
* by the security manager.
* @throws NullPointerException If {@code name} is {@code null}
*
* @see Module#getResourceAsStream(String)
* @since 1.1
* @revised 9
*/
@CallerSensitive
public InputStream getResourceAsStream(String name) {
name = resolveName(name);
Module thisModule = getModule();
if (thisModule.isNamed()) {
// check if resource can be located by caller
if (Resources.canEncapsulate(name)
&& !isOpenToCaller(name, Reflection.getCallerClass())) {
return null;
}
// resource not encapsulated or in package open to caller
String mn = thisModule.getName();
ClassLoader cl = getClassLoader0();
try {
// special-case built-in class loaders to avoid the
// need for a URL connection
if (cl == null) {
return BootLoader.findResourceAsStream(mn, name);
} else if (cl instanceof BuiltinClassLoader) {
return ((BuiltinClassLoader) cl).findResourceAsStream(mn, name);
} else {
URL url = cl.findResource(mn, name);
return (url != null) ? url.openStream() : null;
}
} catch (IOException | SecurityException e) {
return null;
}
}
// unnamed module
ClassLoader cl = getClassLoader0();
if (cl == null) {
return ClassLoader.getSystemResourceAsStream(name);
} else {
return cl.getResourceAsStream(name);
}
}
getResource(String name)
/**
* Finds a resource with a given name.
*
* <p> If this class is in a named {@link Module Module} then this method
* will attempt to find the resource in the module. This is done by
* delegating to the module's class loader {@link
* ClassLoader#findResource(String,String) findResource(String,String)}
* method, invoking it with the module name and the absolute name of the
* resource. Resources in named modules are subject to the rules for
* encapsulation specified in the {@code Module} {@link
* Module#getResourceAsStream getResourceAsStream} method and so this
* method returns {@code null} when the resource is a
* non-"{@code .class}" resource in a package that is not open to the
* caller's module.
*
* <p> Otherwise, if this class is not in a named module then the rules for
* searching resources associated with a given class are implemented by the
* defining {@linkplain ClassLoader class loader} of the class. This method
* delegates to this {@code Class} object's class loader.
* If this {@code Class} object was loaded by the bootstrap class loader,
* the method delegates to {@link ClassLoader#getSystemResource}.
*
* <p> Before delegation, an absolute resource name is constructed from the
* given resource name using this algorithm:
*
* <ul>
*
* <li> If the {@code name} begins with a {@code '/'}
* (<code>'\u002f'</code>), then the absolute name of the resource is the
* portion of the {@code name} following the {@code '/'}.
*
* <li> Otherwise, the absolute name is of the following form:
*
* <blockquote>
* {@code modified_package_name/name}
* </blockquote>
*
* <p> Where the {@code modified_package_name} is the package name of this
* object with {@code '/'} substituted for {@code '.'}
* (<code>'\u002e'</code>).
*
* </ul>
*
* @param name name of the desired resource
* @return A {@link java.net.URL} object; {@code null} if no resource with
* this name is found, the resource cannot be located by a URL, the
* resource is in a package that is not
* {@linkplain Module#isOpen(String, Module) open} to at least the caller
* module, or access to the resource is denied by the security
* manager.
* @throws NullPointerException If {@code name} is {@code null}
* @since 1.1
* @revised 9
*/
@CallerSensitive
public URL getResource(String name) {
name = resolveName(name);
Module thisModule = getModule();
if (thisModule.isNamed()) {
// check if resource can be located by caller
if (Resources.canEncapsulate(name)
&& !isOpenToCaller(name, Reflection.getCallerClass())) {
return null;
}
// resource not encapsulated or in package open to caller
String mn = thisModule.getName();
ClassLoader cl = getClassLoader0();
try {
if (cl == null) {
return BootLoader.findResource(mn, name);
} else {
return cl.findResource(mn, name);
}
} catch (IOException ioe) {
return null;
}
}
// unnamed module
ClassLoader cl = getClassLoader0();
if (cl == null) {
return ClassLoader.getSystemResource(name);
} else {
return cl.getResource(name);
}
}
isEnum() {
/**
* Returns true if and only if this class was declared as an enum in the
* source code.
*
* Note that {@link java.lang.Enum} is not itself an enum class.
*
* Also note that if an enum constant is declared with a class body,
* the class of that enum constant object is an anonymous class
* and <em>not</em> the class of the declaring enum class. The
* {@link Enum#getDeclaringClass} method of an enum constant can
* be used to get the class of the enum class declaring the
* constant.
*
* @return true if and only if this class was declared as an enum in the
* source code
* @since 1.5
* @jls 8.9.1 Enum Constants
*/
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;
}
isRecord()
/**
* Returns {@code true} if and only if this class is a record class.
*
* <p> The {@linkplain #getSuperclass() direct superclass} of a record
* class is {@code java.lang.Record}. A record class is {@linkplain
* Modifier#FINAL final}. A record class has (possibly zero) record
* components; {@link #getRecordComponents()} returns a non-null but
* possibly empty value for a record.
*
* <p> Note that class {@link Record} is not a record class and thus
* invoking this method on class {@code Record} returns {@code false}.
*
* @return true if and only if this class is a record class, otherwise false
* @jls 8.10 Record Classes
* @since 16
*/
public boolean isRecord() {
// this superclass and final modifier check is not strictly necessary
// they are intrinsified and serve as a fast-path check
return getSuperclass() == java.lang.Record.class &&
(this.getModifiers() & Modifier.FINAL) != 0 &&
isRecord0();
}
getEnumConstants()
/**
* Returns the elements of this enum class or null if this
* Class object does not represent an enum class.
*
* @return an array containing the values comprising the enum class
* represented by this {@code Class} object in the order they're
* declared, or null if this {@code Class} object does not
* represent an enum class
* @since 1.5
* @jls 8.9.1 Enum Constants
*/
public T[] getEnumConstants() {
T[] values = getEnumConstantsShared();
return (values != null) ? values.clone() : null;
}
enumConstantDirectory()
/**
* Returns a map from simple name to enum constant. This package-private
* method is used internally by Enum to implement
* {@code public static <T extends Enum<T>> T valueOf(Class<T>, String)}
* efficiently. Note that the map is returned by this method is
* created lazily on first use. Typically it won't ever get created.
*/
Map<String, T> enumConstantDirectory() {
Map<String, T> directory = enumConstantDirectory;
if (directory == null) {
T[] universe = getEnumConstantsShared();
if (universe == null)
throw new IllegalArgumentException(
getName() + " is not an enum class");
directory = new HashMap<>((int)(universe.length / 0.75f) + 1);
for (T constant : universe) {
directory.put(((Enum<?>)constant).name(), constant);
}
enumConstantDirectory = directory;
}
return directory;
}
cast(Object obj)
/**
* Casts an object to the class or interface represented
* by this {@code Class} object.
*
* @param obj the object to be cast
* @return the object after casting, or null if obj is null
*
* @throws ClassCastException if the object is not
* null and is not assignable to the type T.
*
* @since 1.5
*/
@SuppressWarnings("unchecked")
@IntrinsicCandidate
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException(cannotCastMsg(obj));
return (T) obj;
}
asSubclass(Class clazz)
/**
* Casts this {@code Class} object to represent a subclass of the class
* represented by the specified class object. Checks that the cast
* is valid, and throws a {@code ClassCastException} if it is not. If
* this method succeeds, it always returns a reference to this {@code Class} object.
*
* <p>This method is useful when a client needs to "narrow" the type of
* a {@code Class} object to pass it to an API that restricts the
* {@code Class} objects that it is willing to accept. A cast would
* generate a compile-time warning, as the correctness of the cast
* could not be checked at runtime (because generic types are implemented
* by erasure).
*
* @param <U> the type to cast this {@code Class} object to
* @param clazz the class of the type to cast this {@code Class} object to
* @return this {@code Class} object, cast to represent a subclass of
* the specified class object.
* @throws ClassCastException if this {@code Class} object does not
* represent a subclass of the specified class (here "subclass" includes
* the class itself).
* @since 1.5
*/
@SuppressWarnings("unchecked")
public <U> Class<? extends U> asSubclass(Class<U> clazz) {
if (clazz.isAssignableFrom(this))
return (Class<? extends U>) this;
else
throw new ClassCastException(this.toString());
}
getAnnotation(Class annotationClass)
/**
* {@inheritDoc}
* <p>Note that any annotation returned by this method is a
* declaration annotation.
*
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
@Override
@SuppressWarnings("unchecked")
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
return (A) annotationData().annotations.get(annotationClass);
}
isAnnotationPresent(Class<? extends Annotation> annotationClass)
/**
* {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return GenericDeclaration.super.isAnnotationPresent(annotationClass);
}
getAnnotationsByType(Class annotationClass)
/**
* {@inheritDoc}
* <p>Note that any annotations returned by this method are
* declaration annotations.
*
* @throws NullPointerException {@inheritDoc}
* @since 1.8
*/
@Override
public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
AnnotationData annotationData = annotationData();
return AnnotationSupport.getAssociatedAnnotations(annotationData.declaredAnnotations,
this,
annotationClass);
}
getAnnotations()
/**
* {@inheritDoc}
* <p>Note that any annotations returned by this method are
* declaration annotations.
*
* @since 1.5
*/
@Override
public Annotation[] getAnnotations() {
return AnnotationParser.toArray(annotationData().annotations);
}
getDeclaredAnnotation(Class annotationClass)
/**
* {@inheritDoc}
* <p>Note that any annotation returned by this method is a
* declaration annotation.
*
* @throws NullPointerException {@inheritDoc}
* @since 1.8
*/
@Override
@SuppressWarnings("unchecked")
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
return (A) annotationData().declaredAnnotations.get(annotationClass);
}
getNestHost()
/**
* Returns the nest host of the <a href=#nest>nest</a> to which the class
* or interface represented by this {@code Class} object belongs.
* Every class and interface belongs to exactly one nest.
*
* If the nest host of this class or interface has previously
* been determined, then this method returns the nest host.
* If the nest host of this class or interface has
* not previously been determined, then this method determines the nest
* host using the algorithm of JVMS 5.4.4, and returns it.
*
* Often, a class or interface belongs to a nest consisting only of itself,
* in which case this method returns {@code this} to indicate that the class
* or interface is the nest host.
*
* <p>If this {@code Class} object represents a primitive type, an array type,
* or {@code void}, then this method returns {@code this},
* indicating that the represented entity belongs to the nest consisting only of
* itself, and is the nest host.
*
* @return the nest host of this class or interface
*
* @throws SecurityException
* If the returned class is not the current class, and
* if a security manager, <i>s</i>, is present and the caller's
* class loader is not the same as or an ancestor of the class
* loader for the returned class and invocation of {@link
* SecurityManager#checkPackageAccess s.checkPackageAccess()}
* denies access to the package of the returned class
* @since 11
* @jvms 4.7.28 The {@code NestHost} Attribute
* @jvms 4.7.29 The {@code NestMembers} Attribute
* @jvms 5.4.4 Access Control
*/
@CallerSensitive
public Class<?> getNestHost() {
if (isPrimitive() || isArray()) {
return this;
}
Class<?> host = getNestHost0();
if (host == this) {
return this;
}
// returning a different class requires a security check
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkPackageAccess(sm,
ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
}
return host;
}