getclass()返回运行时实际类型而非声明类型,如object obj=new arraylist()时obj.getclass()为arraylist.class;应使用==比较class实例而非字符串或equals,注意泛型擦除、空指针、类加载器隔离等问题。

Object.getClass() 返回的是运行时实际类型,不是声明类型
Java 中 getClass() 永远返回对象在堆内存中真实创建的类,和变量声明类型无关。比如 Object obj = new ArrayList(),obj.getClass() 是 ArrayList.class,不是 Object.class。
这跟 instanceof 不同:instanceof 可以向上匹配父类或接口,而 getClass() 严格到具体实现类,连子类都不认——new LinkedList().getClass() == ArrayList.class 结果是 false。
用 getClass().getName() 或 getSimpleName() 获取类名字符串
直接调用 getClass().getName() 得到带包名的全限定名(如 "java.util.ArrayList"),getClass().getSimpleName() 只返回类名(如 "ArrayList")。
注意两点:
-
getSimpleName()对匿名内部类返回空字符串,对 Lambda 表达式返回类似"MyClass$$Lambda$1/0x0000000800062c40"的不可靠字符串,不能用于逻辑判断 -
getName()在模块化(Java 9+)下仍稳定,但若需跨模块比较类,优先用==比较Class实例本身,而不是字符串
用 getClass() == Xxx.class 做精确类型判定
这是最安全、最高效的运行时类型判断方式,适用于必须区分具体实现类的场景,比如序列化策略分发、缓存 key 构建、或避免反射调用错误方法。
示例:
if (obj.getClass() == HashMap.class) {
// 处理 HashMap 特有逻辑
} else if (obj.getClass() == LinkedHashMap.class) {
// 处理 LinkedHashMap 特有逻辑(即使它也是 Map)
}
比起 obj instanceof HashMap,这种方式不会误判子类;比起字符串比较,它不依赖类名拼写,且无反射开销。
常见误用:
- 写成
obj.getClass().equals(HashMap.class)—— 虽然结果对,但多一次方法调用,==更直接 - 在泛型擦除后试图用
getClass()判断泛型参数 —— 不行,ArrayList<string>.class</string>和ArrayList<integer>.class</integer>运行时是同一个Class对象
getClass() 在数组和基本类型包装类上的表现
数组是对象,所以 int[].class 和 (new int[0]).getClass() 一致,返回 [I 这样的 JVM 内部表示;String[].class 对应 [Ljava.lang.String;。可用 Array.newInstance() 配合 getClass() 动态创建同类型数组。
基本类型包装类要注意自动装箱干扰:
-
Integer i = 100;→i.getClass()是Integer.class -
Integer i = null;→ 调用i.getClass()直接抛NullPointerException,必须先判空
没有 int.class 的实例可调 getClass(),因为基本类型不是对象;但 int.class 本身是合法的 Class 字面量,可用于反射参数匹配。
真正容易被忽略的是:当对象来自不同类加载器时,哪怕类名、字节码完全一样,getClass() == Xxx.class 也会是 false。这种场景下,类型判断必须退回到名称比对或接口契约判断,不能依赖 Class 实例相等。










