Class对象的getXXXClass和getXXXName

xiaoxiao2025-05-02  11

getXXXClass方法获取class对象

在讲解具体的方法之前,我们先介绍一下java类(接口)的划分方法。 java的class对象分为5种,这一点在getEnclosingClass方法的注释中有写明,分别是: a. Top类 b. Nested类:嵌套类,即静态成员类 c. Inner类:内部类,即普通成员类 d. Local类:局部类,在方法中定义的类 e. Anonymous:匿名类

Class对象有3个和name相关的方法,分别是getClass, getDeclaringClass和getEnclosingClass,下面我们仔细看一下这3个方法有什么区别。

getClass方法 getClass方法是从Object类继承而来的方法,返回的是该对象所对应的运行时类。 class.getClass()返回的自然是java.lang.Class.

getDeclaringClass方法 从注释可以看出,class.getDeclaringClass()方法返回了声明class对象的类,只有当class对象的类A是另一个类B的成员类,该方法才能返回值,返回该成员类所在的类(即类B),否则返回null值。 如果class对象是local class,是在类B的方法里定义的,同样返回null值,而不会返回类B。

/** * If the class or interface represented by this {@code Class} object * is a member of another class, returns the {@code Class} object * representing the class in which it was declared. This method returns * null if this class or interface is not a member of any other class. If * this {@code Class} object represents an array class, a primitive * type, or void,then this method returns null. * * @return the declaring class for 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 declaring class and invocation of {@link * SecurityManager#checkPackageAccess s.checkPackageAccess()} * denies access to the package of the declaring class * @since JDK1.1 */ @CallerSensitive public Class<?> getDeclaringClass() throws SecurityException { final Class<?> candidate = getDeclaringClass0(); if (candidate != null) candidate.checkPackageAccess( ClassLoader.getClassLoader(Reflection.getCallerClass()), true); return candidate; } getEnclosingClass方法

返回该class对象的立即封闭类,即该类实在哪个类里定义的,与getDeclaringClass不同,getEnclosingClass并不要求一定是成员类。

@CallerSensitive public Class<?> getEnclosingClass() throws SecurityException { 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; }

总结一下:

getXXXName方法返回名称

在讲具体的区别之前,先明确对象的描述符概念。 在class文件里,字段表集合里存储了类的属性和方法,并且通过描述符来区分不同的对象类型。对于基本数据结构,描述符用一个大写字母表示;对于对象,描述符用L+类的全限定名表示,并以分号结束。 描述符在class类中getName方法的注释中也有描述。

Class对象有3个和name相关的方法,分别是getSimpleName, getName和getCanonicalName,下面我们仔细看一下这3个方法有什么区别。

getName 在class类里,getName方法通过调用native方法getName0获得,返回class对象在虚拟机里面的表示。 1 .对于top class,getName为:类的全限定名,如:test.Test。 2 .对于nested class和inner class,getName为:getEnclosingClass的getName + $ + 类名,如test.Test$Inner。 3 . 对于anonymous class,getName为:getEnclosingClass的getName + $ + 虚拟机分配的类名(虚拟机对于每一个类中的匿名类会按顺序分配给1,2之类的类名,如test.Test$1。 对于local class,getName为:getEnclosingClass的getName + $ + 虚拟机分配的前缀+类名(由于local class是属于方法的,一个类中的不同方法下的local class类名是有可能相同的,所以虚拟机会在类名前面自动加上按方法加上1,2之类的排序),如test.Test$2LocalClass。 4 .对于基本数据结构的class对象,getName为:基本数据结构的名称,如boolean。 5 .对于数组的class对象,getName为:[ + 元素类型的描述符,如[Ljava.lang.String;(带分号),[Z。如果是多维数组,则带有多个[。

getSimpleName方法

从代码可以看出 1 .对于数组的class对象,返回元素类型的getSimpleName+[]。 2 .对于非top class的对象,获取getEnclosingClass,从getName中截去getEnclosingClass的getName,截去$符号,然后截去字符串前面的所有数字。 3 .对于top class的对象,返回类名。

public String getSimpleName() { if (isArray()) return getComponentType().getSimpleName()+"[]"; String simpleName = getSimpleBinaryName(); if (simpleName == null) { // top level class simpleName = getName(); return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name } 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); } private String getSimpleBinaryName() { Class<?> enclosingClass = getEnclosingClass(); if (enclosingClass == null) // top level class return null; // Otherwise, strip the enclosing class' name try { return getName().substring(enclosingClass.getName().length()); } catch (IndexOutOfBoundsException ex) { throw new InternalError("Malformed class name", ex); } } getCanonicalName方法 1 .对于数组的class对象,检查元素类型的getCanonicalName,如果是null,则返回null;否则元素类型的getCanonicalName + []。 2 .对于local class和anonymous class,返回null。 3.对于top class,返回getName。 4.获取getEnclosingClass的getCanonicalName作为canonicalName,为null则返回null;否则getCanonicalName + . + getSimpleName。 public String getCanonicalName() { if (isArray()) { String canonicalName = getComponentType().getCanonicalName(); if (canonicalName != null) return canonicalName + "[]"; else return null; } if (isLocalOrAnonymousClass()) return null; Class<?> enclosingClass = getEnclosingClass(); if (enclosingClass == null) { // top level class return getName(); } else { String enclosingName = enclosingClass.getCanonicalName(); if (enclosingName == null) return null; return enclosingName + "." + getSimpleName(); } }

总结一下:

spring包里的classMetadata 在spring的org.springframework.core.type包下的classMetadata接口里有一些与我们上述内容相关的方法,这些方法在spring的源码中经常会遇到,我们通过其实现类StandardClassMetadata一并解释一下: isIndependent 从方法名称上可以看出,判断对应的类是否是独立的,不需要依赖其它类。 如果是top class或nested class,视为Independent,返回true;否则返回false。 @Override public boolean isIndependent() { return (!hasEnclosingClass() || (this.introspectedClass.getDeclaringClass() != null && Modifier.isStatic(this.introspectedClass.getModifiers()))); } hasEnclosingClass 从方法名称上可以看出,判断getEnclosingClass是否存在。 如果是top class返回false,否则返回true。 @Override public boolean hasEnclosingClass() { return (this.introspectedClass.getEnclosingClass() != null); } getEnclosingClassName 从方法名称上可以看出,获取getEnclosingClass的getName。 如果是top class返回null,否则返回getEnclosingClass的getName。 @Override @Nullable public String getEnclosingClassName() { Class<?> enclosingClass = this.introspectedClass.getEnclosingClass(); return (enclosingClass != null ? enclosingClass.getName() : null); } getClassName 从方法名称上可以看出对于class对象的getName。 @Override public String getClassName() { return this.introspectedClass.getName(); }
转载请注明原文地址: https://www.6miu.com/read-5029649.html

最新回复(0)