zoukankan      html  css  js  c++  java
  • 判断一个类是否为另一个类的实例 instanceof关键字和isAssignableFrom方法的区别

    Which of the following is better?

    a instanceof B
    

    or

    B.class.isAssignableFrom(a.getClass())
    

    The only difference that I know of is, when 'a' is null, the first returns false, while the second throws an exception. Other than that, do they always give the same result?

    When using instanceof, you need to know the class of "B" at compile time. When using isAssignableFrom()it can be dynamic and change during runtime.

     

    2013年10月28日13分10秒

     

    instanceof can only be used with reference types, not primitive types. isAssignableFrom() can be used with any class objects:

    a instanceof int  // syntax error
    3 instanceof Foo  // syntax error
    int.class.isAssignableFrom(int.class)  // true
    

    See http://java.sun.com/javase/6/docs/api/java/lang/Class.html#isAssignableFrom(java.lang.Class).

     

    2013年10月28日13分10秒

     

    Talking in terms of performance :

    class A{}
    class B extends A{}
    
    A b = new B();
    
    void execute(){
       boolean test = A.class.isAssignableFrom(b.getClass());
       // boolean test = A.class.isInstance(b);
       // boolean test = b instanceof A;
    }
    
    @Test
    public void testPerf() {
        // Warmup the code
        for (int i = 0; i < 100; ++i)
            execute();
    
        // Time it
        int count = 100000;
        final long start = System.nanoTime();
        for(int i=0; i<count; i++){
           execute();
        }
        final long elapsed = System.nanoTime() - start;
        System.out.println(count+" iterations took " + TimeUnit.NANOSECONDS.toMillis(elapsed) + "ms.);
    }
    

    It gives :

    • A.class.isAssignableFrom(b.getClass()) : 100000 iterations took 15ms
    • A.class.isInstance(b) : 100000 iterations took 12ms
    • b instanceof A : 100000 iterations took 6ms

    So that we can conclude instanceof is faster !

     

    2013年10月28日13分10秒

     

    A more direct equivalent to a instanceof B is

    B.class.isInstance(a)
    

    This works (returns false) when a is null too.

     

    2013年10月27日13分10秒

     

    Apart from basic differences mentioned above, there is a core subtle difference between instanceof operator and isAssignableFrom method in Class.

    Read instanceof as “is this (the left part) the instance of this or any subclass of this (the right part)” and readx.getClass().isAssignableFrom(Y.class) as “Can I write X x = new Y()”. In other words, instanceof operator checks if the left object is same or subclass of right class, while isAssignableFrom checks if we can assign object of the parameter class (from) to the reference of the class on which the method is called. Note that both of these consider the actual instance not the reference type.

    Consider an example of 3 classes A, B and C where C extends B and B extends A.

    B b = new C();
    
    System.out.println(b instanceof A); //is b (which is actually class C object) instance of A, yes. This will return true.  
    System.out.println(b instanceof B); // is b (which is actually class C object) instance of B, yes. This will return true.  
    System.out.println(b instanceof C); // is b (which is actually class C object) instance of C, yes. This will return true. If the first statement would be B b = new B(), this would have been false.
    System.out.println(b.getClass().isAssignableFrom(A.class));//Can I write C c = new A(), no. So this is false.
    System.out.println(b.getClass().isAssignableFrom(B.class)); //Can I write C c = new B(), no. So this is false.
    System.out.println(b.getClass().isAssignableFrom(C.class)); //Can I write C c = new C(), Yes. So this is true.
    

     

    2013年10月27日13分10秒

     

    There is also another difference:

    null instanceof X is false no matter what X is

    null.getClass().isAssignableFrom(X) will throw a NullPointerException

     

    2013年10月28日13分10秒

     

    There is yet another difference. If the type (Class) to test against is dynamic, e.g. passed as a method parameter, then instanceof won't cut it for you.

    boolean test(Class clazz) {
       return (this instanceof clazz); // clazz cannot be resolved to a type.
    }
    

    but you can do:

    boolean test(Class clazz) {
       return (clazz.isAssignableFrom(this.getClass())); // okidoki
    }
    

    Oops, I see this answer is already covered. Maybe this example is helpful to someone.

     

    2013年10月28日13分10秒

     

    This thread provided me some insight into how instanceof differed from isAssignableFrom, so I thought I'd share something of my own.

    I have found that using isAssignableFrom to be the only (probably not the only, but possibly the easiest) way to ask one's self if a reference of one class can take instances of another, when one has instances of neither class to do the comparison.

    Hence, I didn't find using the instanceof operator to compare assignability to be a good idea when all I had were classes, unless I contemplated creating an instance from one of the classes; I thought this would be sloppy.

     

    2013年10月28日13分10秒

     

    Consider following situation. Suppose you want to check whether type A is a super class of the type of obj, you can go either

    ... A.class.isAssignableFrom(obj.getClass()) ...

    OR

    ... obj instanceof A ...

    But the isAssignableFrom solution requires that the type of obj be visible here. If this is not the case (e.g., the type of obj might be of a private inner class), this option is out. However, the instanceof solution would always work.

     

    2013年10月27日13分10秒

     

    some tests we did in our team show that A.class.isAssignableFrom(B.getClass()) works faster than B instanceof A. this can be very useful if you need to check this on large number of elements.

     

    2013年10月28日13分10秒

     

    instanceof cannot be used with primitive types or generic types either. As in the following code:

    //Define Class< T > type ...

    Object e = new Object();
    
    if(e instanceof T) {
      // Do something.
    }
    

    The error is: Cannot perform instanceof check against type parameter T. Use it's erasure Obect instead since further generic type information will be erased at runtime.

    Does not compile due to type erasure removing the runtime reference. However, the code below will compile:

    if( type.isAssignableFrom(e.getClass())){
      // Do something.
    }
    

     

    2013年10月27日13分10秒

  • 相关阅读:
    生手和FinallyJane一起学习ASP.NET
    使用eclipse 初学java
    关于C#中用access做数据库,使用like语句的问题(转)
    VSS (Visual Source Safe 2005) 用法详解(转)
    mysql 字符集问题之我见
    mysqli的预处理功能使用
    兼容IE和Firefox
    linux下netsnmp 已经安装,为什么没有 snmpwalk和snmpget
    ? PHP WBEM
    安装cacti时提示错误
  • 原文地址:https://www.cnblogs.com/zollty/p/3392662.html
Copyright © 2011-2022 走看看