java中instanceOf和Class.isInstance(obj)的对比

辨析一个类和一个实例是不是具有实现关系,通常使用 instanceOF和Class<?>.isInstanceOf(obj),为了能够更好的使用这两种检测方式,我们需要知道两者的差别。

//通常我们会用到下面的关系,instanceOf说明了类和对象的直接实现关系
if(obj instanceOf ObjClass)
{
//..  
}

这种关系是如何实现的呢

首先obj 是ObjClass的实例的话,那么obj必须是非空,所以 obj!=null,其次,obj.getClass()==ObjClass.class

//所以如上等价于
if(obj!=null && obj.getClass()==ObjClass.class)
{
//
}

上面使用了 == 而不是equal,因为这更加合理,在java中,类是静态的,唯一的,共享的单例,所以这里用 == 在恰当不过了,使用 == 更能说明 实现关系.

那么 Class<?>.isInstanceOf(obj)是如何实现的呢

ObjClass.getClass().isInstance(obj)其实是由 类型->对象的查询,说明了类和对象的间接实现关系。

当一个类继承了某个接口,类,或者而是抽象类,那么,isInstanceOf旨在查找出,这个对象到底实现了哪些类,说着比较绕口。

interface I{

} 
class A implements I{

}

class B extends A
{

}

B b = new B();

I.class.isInstance(b); //查询 b是不是实现了接口I true
A.class.isInstance(b);//查询b是不实现了A类  true
B.class.isInstance(b);//查询b是不实现了B类  true

在java jdk中  isInstance是用C语言 native代码实现的,如果换成java,就要一下面的原理实现

其实现是一层一层的查询(java源码使用native code 缩写,这里也不写代码解释了,就是调用下面的方法逐步查询的)

查询的停止位置是 Object.class == I.class

public boolean isInstance(Object a)
{
    if(a==null)
    {
      return false;
    }
    //检查当前类的实现
    if(a.getClass()==I.class)
    {
      return true;
    }
    //检查接口的实现
    if(Arrays.asList(a.getClass().getInterfaces()).contains(I.class))
    {
      return true;
    }

//如果查询得到的话返回 true;
//否则在java.lang.Object.class处终止,这里需要注意,a.getClass().getInterfaces()是获取到了所有的接口,所以接下来不给 接口做检查
        Class superClass = a.getClass().getSuperClass();
        while(superClass != Object.class)
        {
          if(superClass==I.class)
          {
            return true;
          }
          superClass =  superClass.getClass();
        }

       return false;
}


看到区别,自然也需要了解这两种检测方法的使用范围。

instanceOf 用于检测 类与对象的直接实现关系,检测方式是 对象->类。

Class<?>.isInstance(obj) 用于检测非直接实现关系,检测方式是 类->对象。


通常来说  ,对于一个对象和一个类来说,(obj instanceOf ObjClass) 关系如果为真,那么 Class<?>.isInstance(obj)关系也为真。但反过来就不一样了,Class<?>.isInstance(obj)更加适合 泛类型 的检测(如代理,接口,抽象类等规则),而 instanceOf符合直接类型的检测。




你可能感兴趣的:(instanceof)