最近在项目里调用的一个类库,返回值是一个Class类型,我想判断一下这个Class对象是否为某个Class的子类或者父类,经过一番搜索,发现了一篇被转了很多次的文章,但是据我自己测试感觉存在一些问题,所以就直接拿别人文章的名字做了我写这篇文章的题目,文章的具体地址在文末的参考文章里。
首先写几个类说明一下它们的关系。
class A {
}
class B extends A {
}
class C extends A {
}
class D extends B {
}
instanceof
如果不用反射,平时判断一个类是否为某个类的子类,通常都用instanceof来判断。
public class TestInstanceOf {
public static void main(String[] args) {
A a = new A();
B b = new B();
C c = new C();
D d = new D();
System.out.println(a instanceof A);
System.out.println(b instanceof A);
System.out.println(c instanceof A);
System.out.println(d instanceof B);
System.out.println(d instanceof A);
}
}
结果当然输出的都是true,不过这篇文章主要是想讨论使用Class类的isAssignableFrom方法。
isAssignableFrom
public class TestClass {
public static void main(String[] args) {
System.out.println(A.class.isAssignableFrom(A.class)); //true
System.out.println(A.class.isAssignableFrom(B.class)); //true
System.out.println(B.class.isAssignableFrom(A.class)); //false
System.out.println(A.class.isAssignableFrom(C.class)); //true
System.out.println(A.class.isAssignableFrom(D.class)); //true
}
}
刚开始我想知道isAssignableFrom用法的时候产生了一些疑惑,从方法名上看带有From,就先入为主的认为参数传递的应该是子类的Class,但写了程序测试发现似乎不太对,然后就进入到源码(jdk14)里去看,如下:
/**
* 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
* @throws NullPointerException if the specified Class parameter is
* null.
* @since 1.1
*/
@HotSpotIntrinsicCandidate
public native boolean isAssignableFrom(Class<?> cls);
一看已经到native方法,那就先看看注释吧,注释的描述也是看的我云里雾里的。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. 有些复杂,那就简化一下,大致可以简化成这样Determines if the class represented by this Class object is a superclass of the class represented by the specified Class parameter. 这样就清晰多了,也就是说参数传入的应该是子类。
然后再说到我看到的这篇被很多人转发的参考文章,其中它里面的类是这么写的
class T{
List<A> a;
List<B> b;
Map<Integer, String> map ;
int c;
}
class A {}
class B{}
测试的main函数里面有一段是这么写的
//fc是遍历Class T对象里所有的成员变量
//fc会是a,b,map,c的类型
if(fc.isAssignableFrom(List.class)) {
}
这篇文章里的执行程序之所以是正确的是因为fc本身就是List类型,但是如果将T里的List类型改为ArrayList,那就判断不出来了,而ArrayList是实现了List的接口的。我觉得原作者这么写,很有可能就是像我刚开始一样,看到了这个函数名中有From这个单词。
当然我写这篇文章,并不是为了批评参考文章中的作者,只是作为一种技术探讨,共同进步。
参考
- https://blog.csdn.net/is_zhoufeng/article/details/7629931