instanceof是Java中的二元运算符,左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回true;否则,返回false。
explanation

  • 类的实例包含本身的实例,以及所有直接或间接子类的实例
  • instanceof左边显式声明的类型与右边操作元必须是同种类或存在继承关系,也就是说需要位于同一个继承树,否则会编译错误。

pay attention

  • 左边的对象实例不能是基础数据类型
  • 左边的对象实例和右边的类不在同一个继承树上
  • null用instanceof跟任何类型比较时都是false

    instanceof 和classLoader

    判断两个类是否“相等”,是由2个因素来决定的:

  • 一是class信息是否“相等”,这里的“相等”指的是描述类的class信息是一致的,包括包名一致、类名一致、类里的信息一致等;

  • 另一个就是加载该class的ClassLoader是否是同一个。

    ClassLoader的双亲委派模型

    image.png
    双亲委派模型要求所有的类加载器都有一个父加载器,除了最顶层的启动类加载器之外。它的执行逻辑是:当一个类加载器收到加载类的请求时,它不会自己去尝试加载类,而是委托给其父类来加载,每一个层级都是如此,直至到达启动类加载器为止,如果父类加载器反馈自己无法加载时,子类才会自己尝试去加载类。

Class.forName()加载类

  1. public static Class<?> forName(String name, boolean initialize, ClassLoader loader)

这三个参数的含义如下:
name: 类或接口的全限定名
initialize:前面介绍类加载机制时有讲过,共有加载、验证、准备、解析、初始化、使用、卸载等步骤,该参数为true表示加载该类时会进行类的初始化,false表示不会进行类的初始化。
loader:表示采用哪个ClassLoader来加载该类

  1. public static Class<?> forName(String className)

其实相当于Class.forName(className, true, appClassLoader),也即采用默认的ClassLoader来加载类,并且在加载时会进行类初始化。

为什么要自定义类加载器

大部分情况下,我们都不需要自定义类加载器。但是默认的类加载器有一个局限性,就是它只能加载特定目录下的class文件,但是如果我们想要加载远程服务器上的class文件,或者就是一个符合class规范的二进制字节流,那么就需要自定义类加载器来实现了。
现在流行的热修复、热部署技术,其实都是利用了自定义类加载器来实现的。