getClass、getSuperclass、getGenericSuperclass
这3个方法看起来很像,其实是有很大区别的,因为这3个方法的来源就不同,getClass是普通对象的方法,而getSuperclass,getGenericSuperclass是Class对象的方法。
getClass函数定义:
Returns the runtime class of this Object
. The returned Class
object is the object that is locked by static synchronized
methods of the represented class.The actual result type is Class<? extends |X|>
where |X|
is the erasure of the static type of the expression on which getClass
is called. For example, no cast is required in this code fragment:
Number n = 0;
Class<? extends Number> c = n.getClass();
翻译过来就是,返回此对象的运行时类对象,返回的类对象是由所表示类的静态同步方法锁定的对象(我也不懂这什么意思)。当调用 getClass方法的时候,
实际返回结果类型是 Class<? extends |X|>
,其中 |X|
是擦除调用getClass的表达式的静态类型。(我自己都不懂这说了什么,我理解的意思就是这个|X|是被擦除的那个类型,哪个类型呢,就是调用getClass方法的类的类型)例如,以下代码片段中不需要强制转换:
Number n = 0;
Class<? extends Number> c = n.getClass();
由于泛型擦除的原因,所以这个例子生成的class文件中<? extends Number>是被擦除了的。
还有一点需要注意的是getClass()是返回的运行时的Class,不是定义的时候的Class.
举例来说
//包名com.test,定义两个类ClassA,ClassB
class ClassA {
}
class ClassB extends ClassA {
}
public static void main(String[] args)
{
ClassA a = new ClassA();
ClassB b = new ClassB();
ClassA aa = new ClassB();
System.out.println(a.getClass().getName());
System.out.println(b.getClass().getName());
System.out.println(aa.getClass().getName());
}
输出结果:
com.test.ClassA
com.test.ClassB
com.test.ClassB
可以看到aa的定义类型虽然是ClassA,但是由于它的运行时类型是ClassB,所以最后aa.getClass得到的Class对象也是
com.test.ClassB
getSuperclass 函数定义
Returns the Class representing the superclass of the entity(class, interface, primitive type or void) represented by this Class. If this Class represents either the Object class, an interface, a primitive type, or void, then null is returned. If this object represents an array class then the Class object representing the Object class is returned.
翻译过来就是:返回表示这个实体(Class,接口,原始类型或者空类型)的超类Class对象.如果这个Class是Object.class,或者一个接口、或者一个原始类型,或者空类型,则会返回null。如果此对象是数组,则会返回Object Class对象.
这个方法主要返回Class对象的超类Class对象,特殊情况下,数组的Class对象的超类Class对象就是Object对象
举个例子
int[] a = new int[10];
System.out.println(a.getClass().getName());
System.out.println(a.getClass().getSuperclass().getName());
Integer[] t = new Integer[10];
System.out.println(t.getClass().getName());
System.out.println(t.getClass().getSuperclass().getName());
// 接口getSuperClass会获取为null,所以后面没有调用getName方法
System.out.println(InterfaceA.class.getSuperclass());
System.out.println(Object.class.getSuperclass());
输出结果如下:
[I
java.lang.Object
[Ljava.lang.Integer;
java.lang.Object
null
null
getGenericSuperclass函数定义:
Returns the Type
representing the direct superclass of the entity (class, interface, primitive type or void) represented by this Class
.
If the superclass is a parameterized type, the Type
object returned must accurately reflect the actual type parameters used in the source code. The parameterized type representing the superclass is created if it had not been created before. See the declaration of ParameterizedType
for the semantics of the creation process for parameterized types. If this Class
represents either the Object
class, an interface, a primitive type, or void, then null is returned. If this object represents an array class then the Class
object representing the Object
class is returned.
翻译过来就是,返回表示此 Class对象所表示的实体(类、接口、基本类型或 void)的超类的Type。如果超类是参数化类型,则返回的 Type 对象必须准确反映源代码中所使用的实际类型参数。如果以前未曾创建表示超类的参数化类型,则创建这个类型。有关参数化类型创建过程的语义,请参阅 ParameterizedType 声明。如果此 Class 表示 Object 类、接口、基本类型或 void,则返回 null。如果此对象表示一个数组类,则返回表示 Object 类的 Class 对象。
需要注意的是这个函数会返回一个Type,这个Type包含超类中的泛型。特殊情况还是数组,会返回Object的Class对象
class ClassA<T> {
}
class ClassB<T> extends ClassA<T> {
}
class ClassC extends ClassA<String> {
}
public static void main(String args[])
{
ClassB<String> b1 = new ClassB<String>();
System.out.println(b1.getClass().getName());
//这里的Type得到的泛型,并不会因为我实例化的时候用的String而变成String,而是始终与源代码对象
System.out.println(b1.getClass().getGenericSuperclass().getTypeName());
ClassB b2 = new ClassB();
System.out.println(b2.getClass().getName());
System.out.println(b2.getClass().getGenericSuperclass().getTypeName());
ClassC c1 = new ClassC();
System.out.println(c1.getClass().getName());
System.out.println(c1.getClass().getGenericSuperclass().getTypeName());
}
运行结果如下
com.test.ClassB
com.test.ClassA<T>
com.test.ClassB
com.test.ClassA<T>
com.test.ClassC
com.test.ClassA<java.lang.String>
由于源代码中ClassC就是继承的ClassA<String>,所以最后打印的就是com.test.ClassA<java.lang.String>