isAssignable方法位于spring的org.springframework.util工具包的ClassUtils类中下
源码:
/**
* Check if the right-hand side type may be assigned to the left-hand side
* type, assuming setting by reflection. Considers primitive wrapper
* classes as assignable to the corresponding primitive types.
* @param lhsType the target type
* @param rhsType the value type that should be assigned to the target type
* @return if the target type is assignable from the value type
* @see TypeUtils#isAssignable
*/
public static boolean isAssignable(Class> lhsType, Class> rhsType) {
Assert.notNull(lhsType, "Left-hand side type must not be null");
Assert.notNull(rhsType, "Right-hand side type must not be null");
// 若左边类型 是右边类型的父类、父接口,或者左边类型等于右边类型
if (lhsType.isAssignableFrom(rhsType)) {
return true;
}
// 左边入参是否是基本类型
if (lhsType.isPrimitive()) {
//primitiveWrapperTypeMap是从包装类型到基本类型的map,将右边入参转化为基本类型
Class> resolvedPrimitive = primitiveWrapperTypeMap.get(rhsType);
if (lhsType == resolvedPrimitive) {
return true;
}
}
else {
// 将右边入参转化为包装类型
Class> resolvedWrapper = primitiveTypeToWrapperMap.get(rhsType);
if (resolvedWrapper != null && lhsType.isAssignableFrom(resolvedWrapper))
{
return true;
}
}
return false;
}
ClassUtils.isAssignable()
方法扩展了Class的isAssignableFrom()
方法,即将Java
的基本类型和包装类型做了兼容。
/**
* 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}.
*
* 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 The Java Language
* Specification, 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);
实现:
/**
* Instances of the class {@code Class} represent classes and
* interfaces in a running Java application. An enum is a kind of
* class and an annotation is a kind of interface. Every array also
* belongs to a class that is reflected as a {@code Class} object
* that is shared by all arrays with the same element type and number
* of dimensions. The primitive Java types ({@code boolean},
* {@code byte}, {@code char}, {@code short},
* {@code int}, {@code long}, {@code float}, and
* {@code double}), and the keyword {@code void} are also
* represented as {@code Class} objects.
*
* {@code Class} has no public constructor. Instead {@code Class}
* objects are constructed automatically by the Java Virtual Machine as classes
* are loaded and by calls to the {@code defineClass} method in the class
* loader.
*
*
The following example uses a {@code Class} object to print the
* class name of an object:
*
*
* void printClassName(Object obj) {
* System.out.println("The class of " + obj +
* " is " + obj.getClass().getName());
* }
*
*
* It is also possible to get the {@code Class} object for a named
* type (or for void) using a class literal. See Section 15.8.2 of
* The Java™ Language Specification.
* For example:
*
*
* {@code System.out.println("The name of class Foo is: "+Foo.class.getName());}
*
*
* @param the type of the class modeled by this {@code Class}
* object. For example, the type of {@code String.class} is {@code
* Class}. Use {@code Class>} if the class being modeled is
* unknown.
*
* @author unascribed
* @see java.lang.ClassLoader#defineClass(byte[], int, int)
* @since JDK1.0
*/
public final class Class implements java.io.Serializable,
GenericDeclaration,
Type,
AnnotatedElement {
private static final int ANNOTATION= 0x00002000;
private static final int ENUM = 0x00004000;
private static final int SYNTHETIC = 0x00001000;
private static native void registerNatives();
static {
registerNatives();
}
实现调用的是java Native方法,这里不继续展开。
与instanceof()方法对比:
A instanceof B :判断A对象是否为B类或接口的实例或者子类或子接口的对象
A.isAssignableFrom(B) :判断A Class对象所代表的类或者接口 是否为B Class对象所代表的类或者接口
PS:简单说就是 instanceof是判断A是否继承B,isAssignableFrom是判断B是否继承A
测试:
package com.auuzee.test1;
class A {
}
class B extends A {
}
public class Test1 {
public static void main(String[] args) {
A a = new A();
B b = new B();
A ba = new B();
System.out.println("1-------------");
System.out.println(A.class.isAssignableFrom(a.getClass()));
System.out.println(B.class.isAssignableFrom(b.getClass()));
System.out.println(A.class.isAssignableFrom(b.getClass()));
System.out.println(B.class.isAssignableFrom(a.getClass()));
System.out.println(A.class.isAssignableFrom(ba.getClass()));
System.out.println(B.class.isAssignableFrom(ba.getClass()));
System.out.println("2-------------");
System.out.println(a.getClass().isAssignableFrom(A.class));
System.out.println(b.getClass().isAssignableFrom(B.class));
System.out.println(a.getClass().isAssignableFrom(B.class));
System.out.println(b.getClass().isAssignableFrom(A.class));
System.out.println(ba.getClass().isAssignableFrom(A.class));
System.out.println(ba.getClass().isAssignableFrom(B.class));
System.out.println("3-------------");
System.out.println(Object.class.isAssignableFrom(b.getClass()));
System.out.println(Object.class.isAssignableFrom("abc".getClass()));
System.out.println("4-------------");
System.out.println("a".getClass().isAssignableFrom(Object.class));
System.out.println("abc".getClass().isAssignableFrom(Object.class));
}
}
结果:
PS:
1.class2是不是class1的子类或者子接口
2.Object是所有类的父类
参考文章:https://www.cnblogs.com/greatfish/p/6097507.html 测试用