线上有个通用解析方法,传进来的Object可能是String、Integer也可能是List,同事直接写了getClass()等于String.class,结果遇到null抛空指针,遇到子类又判不出来。Java判断类型有几个入口,适用场景完全不同。

instanceof:最常用,能处理null

if (obj instanceof String s) { System.out.println(s.length()); }

Java 16起支持模式匹配,判断通过后直接拿到强转后的变量,省掉一次强转。obj为null时instanceof返回false,不会抛异常,这是它比getClass()稳的地方。缺点是只能判引用类型,int这类基本类型编译不过。

getClass()加双等号:要求精确类型

obj.getClass()等于ArrayList.class,只有运行时类型完全一致才为true,ArrayList的子类会返回false。它不接受null,必须先判空。需要排除子类、做严格校验时用它。

isInstance与isAssignableFrom

  • isInstance:String.class.isInstance(obj),等价于instanceof,但类可以在运行时传入,适合写通用工具。
  • isAssignableFrom:Number.class.isAssignableFrom(Integer.class)为true,判断的是继承关系,跟实例无关。

基本类型和泛型判不了

int、double没有getClass,包装类型和基本类型也不相等:int.class等于Integer.class是false,int.class等于Integer.TYPE才是true。泛型更麻烦,List里的元素类型在运行时被擦除,只能拿到List本身,想判元素类型得靠反射读字段的ParameterizedType。

选型就一句:日常要判空安全的用instanceof,要严格等于运行时类型用getClass(),需要动态传类对象用isInstance。别拿toString里的类名做字符串比较,混淆和代理之后必翻车。