看源码必知:Class.isAssignableFrom、instanceof【isInstance】

2023-03-07 14:14:49 浏览数 (1)

结论先行: (1)Class.isAssignableFrom()从类继承的角度判断。 当前类及子类都返回true;其它false; (2)instanceof运算符 用于对象引用变量,是从实例继承的角度判断。 一个类的实例 instanceof 实现的接口定义、类定义、父类定义 都返回true; 当前对象是null,则false。 (3)instanceof和isInstance 起的效果相同; (4)数组与上面的效果相同;

测试数据:

代码语言:javascript复制
    @Data
    public static class ParentClass implements Serializable {
        private String name;
    }

    @Data
    @EqualsAndHashCode(callSuper = true)
    public static class OneLevelChildClass extends ParentClass {
        private String oneLevelChildName;
    }

    @Data
    @EqualsAndHashCode(callSuper = true)
    public static class TwoLevelChildClass extends OneLevelChildClass {
        private String twoLevelChildName;
    }
代码语言:javascript复制
    @Test
    public void testInstanceof() {
        assertThat(null instanceof Serializable).isEqualTo(false);
        /**
         * 一个类的实例 instanceof 实现的接口定义、类定义、父类定义 都返回true
         */
        ParentClass parentClass = new ParentClass();
        assertThat(parentClass instanceof Serializable).isEqualTo(true);
        assertThat(parentClass instanceof ParentClass).isEqualTo(true);
        assertThat(parentClass instanceof OneLevelChildClass).isEqualTo(false);
        assertThat(parentClass instanceof TwoLevelChildClass).isEqualTo(false);

        OneLevelChildClass oneLevelChildClass = new OneLevelChildClass();
        assertThat(oneLevelChildClass instanceof Serializable).isEqualTo(true);
        assertThat(oneLevelChildClass instanceof ParentClass).isEqualTo(true);
        assertThat(oneLevelChildClass instanceof OneLevelChildClass).isEqualTo(true);
        assertThat(oneLevelChildClass instanceof TwoLevelChildClass).isEqualTo(false);

        TwoLevelChildClass twoLevelChildClass = new TwoLevelChildClass();
        assertThat(twoLevelChildClass instanceof Serializable).isEqualTo(true);
        assertThat(twoLevelChildClass instanceof ParentClass).isEqualTo(true);
        assertThat(twoLevelChildClass instanceof OneLevelChildClass).isEqualTo(true);
        assertThat(twoLevelChildClass instanceof TwoLevelChildClass).isEqualTo(true);
    }

Class类的isInstance(Object obj)方法,obj是被测试的对象,如果obj是调用这个方法的class或子类或接口 的实例,则返回true。这个方法是instanceof运算符的动态等价

代码语言:javascript复制
    @Test
    public void testIsInstance() {
        /**
         * 作用范围与instanceof相同
         */
        ParentClass parentClass = new ParentClass();
 assertThat(Serializable.class.isInstance(parentClass)).isEqualTo(true); assertThat(ParentClass.class.isInstance(parentClass)).isEqualTo(true);
 assertThat(OneLevelChildClass.class.isInstance(parentClass)).isEqualTo(false); assertThat(TwoLevelChildClass.class.isInstance(parentClass)).isEqualTo(false);

        OneLevelChildClass oneLevelChildClass = new OneLevelChildClass();
 assertThat(Serializable.class.isInstance(oneLevelChildClass)).isEqualTo(true);
 assertThat(ParentClass.class.isInstance(oneLevelChildClass)).isEqualTo(true);
 assertThat(OneLevelChildClass.class.isInstance(oneLevelChildClass)).isEqualTo(true);
 assertThat(TwoLevelChildClass.class.isInstance(oneLevelChildClass)).isEqualTo(false);

        TwoLevelChildClass twoLevelChildClass = new TwoLevelChildClass();
 assertThat(Serializable.class.isInstance(twoLevelChildClass)).isEqualTo(true);
 assertThat(ParentClass.class.isInstance(twoLevelChildClass)).isEqualTo(true);
 assertThat(OneLevelChildClass.class.isInstance(twoLevelChildClass)).isEqualTo(true);
 assertThat(TwoLevelChildClass.class.isInstance(twoLevelChildClass)).isEqualTo(true);
    }

Class.isAssignableFrom: 当前类及子类都返回true。父类及接口返回false

例:

代码语言:javascript复制
    @Test
    public void testIsAssignableFrom() {
        ParentClass parentClass = new ParentClass();
 assertThat(parentClass.getClass().isAssignableFrom(Serializable.class)).isEqualTo(false);
        /**
         * 当前类及子类都返回true。父类及接口返回false
         */
 assertThat(parentClass.getClass().isAssignableFrom(ParentClass.class)).isEqualTo(true);
 assertThat(parentClass.getClass().isAssignableFrom(OneLevelChildClass.class)).isEqualTo(true);
 assertThat(parentClass.getClass().isAssignableFrom(TwoLevelChildClass.class)).isEqualTo(true);

        OneLevelChildClass oneLevelChildClass = new OneLevelChildClass();
 assertThat(oneLevelChildClass.getClass().isAssignableFrom(Serializable.class)).isEqualTo(false);
 assertThat(oneLevelChildClass.getClass().isAssignableFrom(ParentClass.class)).isEqualTo(false);
        /**
         * 当前类及子类都返回true。父类及接口返回false
         */
 assertThat(oneLevelChildClass.getClass().isAssignableFrom(OneLevelChildClass.class)).isEqualTo(true);
        assertThat(oneLevelChildClass.getClass().isAssignableFrom(TwoLevelChildClass.class)).isEqualTo(true);

        TwoLevelChildClass twoLevelChildClass = new TwoLevelChildClass();
        assertThat(twoLevelChildClass.getClass().isAssignableFrom(Serializable.class)).isEqualTo(false);
        assertThat(twoLevelChildClass.getClass().isAssignableFrom(ParentClass.class)).isEqualTo(false);
        assertThat(twoLevelChildClass.getClass().isAssignableFrom(OneLevelChildClass.class)).isEqualTo(false);
        /**
         * 当前类及子类都返回true。父类及接口返回false
         */
        assertThat(twoLevelChildClass.getClass().isAssignableFrom(TwoLevelChildClass.class)).isEqualTo(true);
    }
代码语言:javascript复制
System.out.println(ArrayList.class.isAssignableFrom(Object.class)); //false 
System.out.println(Object.class.isAssignableFrom(ArrayList.class)); //true
System.out.println("String是Object的父类:" String.class.isAssignableFrom(Object.class)); //false
System.out.println("Object是String的父类:" Object.class.isAssignableFrom(String.class)); //true
System.out.println("Object和Object相同:" Object.class.isAssignableFrom(Object.class)); //true
代码语言:javascript复制
    @Test
    public void testArrayInClassMethod() {
        Integer[] intTypes = {1, 2};
        assertThat(intTypes.getClass().isArray()).isTrue();
        assertThat(intTypes instanceof Integer[]).isTrue();
//        assertThat(intTypes instanceof int[]); //会编译报错:不兼容的类型
        assertThat(intTypes instanceof Object[]).isTrue();

        assertThat(Integer[].class.isInstance(intTypes)).isTrue();
        assertThat(Object[].class.isInstance(intTypes)).isTrue();
//        assertThat(intTypes instanceof String[]).isTrue();//会编译报错:不兼容的类型
        assertThat(intTypes.getClass().isAssignableFrom(Object[].class)).isFalse();
        assertThat(intTypes.getClass().isAssignableFrom(Integer[].class)).isTrue();

        /**
         * 当前类及子类都返回true。父类及接口返回false
         */
 assertThat(intTypes.getClass().isAssignableFrom(Object[].class)).isFalse();
        assertThat(intTypes.getClass().isAssignableFrom(Integer[].class)).isTrue();

        Object[] objects = {1, 2};
        assertThat(objects instanceof Integer[]).isFalse();
        assertThat(objects instanceof Object[]).isTrue();

        assertThat(Integer[].class.isInstance(objects)).isFalse();//具体到抽象的为false
        assertThat(Object[].class.isInstance(objects)).isTrue();

        /**
         * 当前类及子类都返回true。父类及接口返回false
         */
        assertThat(objects.getClass().isAssignableFrom(Object[].class)).isTrue();
        assertThat(objects.getClass().isAssignableFrom(Integer[].class)).isTrue();
    }
代码语言:javascript复制
    /**
     * Determines if the specified {@code Object} is assignment-compatible
     * with the object represented by this {@code Class}.  This method is
     * the dynamic equivalent of the Java language {@code instanceof}
     * operator. The method returns {@code true} if the specified
     * {@code Object} argument is non-null and can be cast to the
     * reference type represented by this {@code Class} object without
     * raising a {@code ClassCastException.} It returns {@code false}
     * otherwise.
     *
     * <p> Specifically, if this {@code Class} object represents a
     * declared class, this method returns {@code true} if the specified
     * {@code Object} argument is an instance of the represented class (or
     * of any of its subclasses); it returns {@code false} otherwise. If
     * this {@code Class} object represents an array class, this method
     * returns {@code true} if the specified {@code Object} argument
     * can be converted to an object of the array class by an identity
     * conversion or by a widening reference conversion; it returns
     * {@code false} otherwise. If this {@code Class} object
     * represents an interface, this method returns {@code true} if the
     * class or any superclass of the specified {@code Object} argument
     * implements this interface; it returns {@code false} otherwise. If
     * this {@code Class} object represents a primitive type, this method
     * returns {@code false}.
     *
     * @param   obj the object to check
     * @return  true if {@code obj} is an instance of this class
     *
     * @since JDK1.1
     */
    public native boolean isInstance(Object obj);
代码语言:javascript复制
    /**
     * Determines if the class or interface represented by this
     * {@code Class} object is either the same as, or is a superclass or
     * superinterface of, the class or interface represented by the specified
     * {@code Class} parameter. It returns {@code true} if so;
     * otherwise it returns {@code false}. If this {@code Class}
     * object represents a primitive type, this method returns
     * {@code true} if the specified {@code Class} parameter is
     * exactly this {@code Class} object; otherwise it returns
     * {@code false}.
     *
     * <p> Specifically, this method tests whether the type represented by the
     * specified {@code Class} parameter can be converted to the type
     * represented by this {@code Class} object via an identity conversion
     * or via a widening reference conversion. See <em>The Java Language
     * Specification</em>, sections 5.1.1 and 5.1.4 , for details.
     *
     * @param cls the {@code Class} object to be checked
     * @return the {@code boolean} value indicating whether objects of the
     * type {@code cls} can be assigned to objects of this class
     * @exception NullPointerException if the specified Class parameter is
     *            null.
     * @since JDK1.1
     */
    public native boolean isAssignableFrom(Class<?> cls);

https://github.com/helloworldtang/spring-boot-cookbook/blob/master/learning-demo/src/test/java/com/tangcheng/learning/reflect/TestClassAPI.java

0 人点赞