1. Class.isAssignableFrom

偶然看见同事写的一段代码是这样的

   if( AfterRender.class.isAssignableFrom( assembly.getClass() ) ){
afterRenders.add( ( AfterRender )assembly );
}

其中用了Class类的isAssignableFrom方法,以前从来没见过这个方法,于是百度了一下, 是这样说的

A.isAssignableFrom(B) 确定一个类(B)是不是继承来自于另一个父类(A),一个接口(A)是不是实现了另外一个接口(B)

也就是说,不管是类继承还是接口实现,是来判断A是不是B的父,B是不是A的子,父.isAssignableFrom(子) == true

2. instanceof

看了Class.isAssignableFrom,想到了instanceof,这个大家应该都比较熟悉

instanceof 是 Java 中的一个双目运算符

obj instanceof Class

  1. 声明一个 class 类的对象,判断 obj 是否为 class 类的实例对象
  2. 声明一个 class 接口实现类的对象 obj,判断 obj 是否为 class 接口实现类的实例对象

乍一看,这和上面Class.isAssignableFrom不是完全一样吗?

3. 对比

3.1 参数类型和位置

  • A.isAssignableFrom(B)中的A和B都是Java中的Class对象;父在前,子在后
  • obj instanceof Class中obj表示的是实例,而Class准确的讲是一个类或接口名,并不是一个Class对象;子在前,父在后
e instanceof List.class // 这种写法是错的,所以不可能动态的把别的Class放在instanceof后面

e instanceof List // 这个写法是对的

3.2 编译与运行时

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

  • obj instanceof Class中的Class必须在编译的时候知道类型,
  • 而isAssignableFrom可以在运行时修改

3.3 基础类型

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

isAssignableFrom可以用于基础类型

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

不过因为基础类型不能继承,所以这个看起来并没有什么用处

3.4 性能

通过简单的测试,性能由好到坏依次是:

  1. instanceof
  2. isInstance
  3. isAssignableFrom

其中的isInstance后面会进行单独对比

底层字节码对比, instanceof相当于关键字,而invokevirtual表示调用了方法,所以一个是静态,另外两个是动态,静态一般是比动态的性能要好

// JAVA
b instanceof A; // Bytecode
getstatic foo/Benchmark.b:java.lang.Object
instanceof foo/A // JAVA
A.class.isInstance(b); // Bytecode
ldc Lfoo/A; (org.objectweb.asm.Type)
getstatic foo/Benchmark.b:java.lang.Object
invokevirtual java/lang/Class isInstance((Ljava/lang/Object;)Z); // JAVA
A.class.isAssignableFrom(b.getClass()); // Bytecode
ldc Lfoo/A; (org.objectweb.asm.Type)
getstatic foo/Benchmark.b:java.lang.Object
invokevirtual java/lang/Object getClass(()Ljava/lang/Class;);
invokevirtual java/lang/Class isAssignableFrom((Ljava/lang/Class;)Z);

性能测试代码:

public class InstanceBenchmark {
static B c = new C(); static boolean execute() {
return B.class.isAssignableFrom(c.getClass()); // 36ms
// return B.class.isInstance(c); // 17ms
// return c instanceof B; // 9ms
} public static void main(String[] args) {
for (int i = 0; i < 100; ++i)
execute(); int count = 1000000;
final long start = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
execute();
}
final long elapsed = System.currentTimeMillis() - start;
System.out.println(elapsed);
}
} class B {
} class C extends B {
} // Warmup the code

3.5 null对象

        boolean a = null instanceof Point; // false
boolean b = Point.class.isInstance(null); // false
boolean c = Point.class.isAssignableFrom(null); // NullPointerException

根据上述代码,可以得知instanceof和isInstance的子可以是null, isAssignableFrom的子不是null, 他们的父都不可以是null

4. Class.isInstance

上面的对比中加入了isInstance这个方法,这个方法可以看作和Class.isAssignableFrom一样,除了下述区别:

  1. isInstance的参数是对象,isAssignableFrom的参数是类
  2. isInstance的参数可以是null, isAssignableFrom参数不可为null
  3. isInstance的性能比isAssignableFrom略好

5. 总结

   if( AfterRender.class.isAssignableFrom( assembly.getClass() ) ){
afterRenders.add( ( AfterRender )assembly );
}

再回头看一下之前同事写的代码,这里必须需要用isAssignableFrom吗?

不是,因为子是assembly,是个对象,所以可以用isInstance或者instanceof

又因为父是AfterRender,一个固定的类,所以从性能角度讲,用instanceof最好

所以再使用的过程中,要结合当时的情况,现在的参数是类还是对象,要判断的父类是静态的还是动态的综合考虑

参考

[1] What is the difference between instanceof and Class.isAssignableFrom(...)?

[2] isAssignableFrom的用法详细解析

[3] Java instanceof关键字详解

instanceof和Class.isAssignableFrom的区别的更多相关文章

  1. 判断一个类是否为另一个类的实例 instanceof关键字和isAssignableFrom方法的区别

    Which of the following is better? a instanceof B or B.class.isAssignableFrom(a.getClass()) The only ...

  2. Java中instanceof和isInstance的具体区别

    Java中instanceof和isInstance的具体区别 在Think in Java泛型这一章遇到这个问题,一些博客模糊提到了isInstance是instanceof的动态实现,查阅文档参考 ...

  3. instanceof, isinstance,isAssignableFrom的区别

    instanceof运算符 只被用于对象引用变量,检查左边的被测试对象 是不是 右边类或接口的 实例化.如果被测对象是null值,则测试结果总是false. 形象地:自身实例或子类实例 instanc ...

  4. instanceof、 isinstance 与 isAssignableFrom的区别

    instanceof运算符 只被用于对象引用变量,检查左边的被测试对象 是不是 右边类或接口的 实例化.如果被测对象是null值,则测试结果总是false. 形象地:自身实例或子类实例 instanc ...

  5. instanceof、isInstance、isAssignableFrom的区别

    https://stackoverflow.com/questions/3949260/java-class-isinstance-vs-class-isassignablefrom 1. MyCla ...

  6. instanceof 与isAssignableFrom

    instanceof 针对实例 isAssignableFrom针对class对象 isAssignableFrom   是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或 ...

  7. Class中isAssignableFrom() 方法

    看Spring源码的时候看到这个方法: protected WebApplicationContext createWebApplicationContext(ServletContext sc) { ...

  8. [JavaScript]instanceof String not behaving as expected in Google Apps Script

    Link: http://stackoverflow.com/questions/11571923/instanceof-string-not-behaving-as-expected-in-goog ...

  9. isAssignableFrom

    instanceof 针对实例  isAssignableFrom针对class对象 isAssignableFrom   是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类 ...

  10. 徒手用Java来写个Web服务器和框架吧<第三章:Service的实现和注册>

    徒手用Java来写个Web服务器和框架吧<第一章:NIO篇> 徒手用Java来写个Web服务器和框架吧<第二章:Request和Response> 这一章先把Web框架的功能说 ...

随机推荐

  1. linux系统安装Confluence

    转载网址:https://blog.yupaits.com/blog/record/linux-confluence.html#安装步骤 Confluence简介 Confluence是一个专业的企业 ...

  2. rpm,docker,k8s三种方式安装部署GitLab服务

    rpm方式 源地址:https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ wget https://mirrors.tuna.tsinghua ...

  3. NSIS皮肤插件:vcl-styles-plugins

    vcl-styles-plugins简介   NSISVCLStyles  plugin (dll)是一款应用于nsis安装程序的皮肤插件,插件大小约为1.6MB,实际应用在安装程序中压缩后约为550 ...

  4. 对循环神经网络参数的理解|LSTM RNN Input_size Batch Sequence

    在很多博客和知乎中我看到了许多对于pytorch框架中RNN接口的一些解析,但都较为浅显甚至出现一些不准确的理解,在这里我想阐述下我对于pytorch中RNN接口的参数的理解. 我们经常看到的RNN网 ...

  5. PAT甲级英语单词整理

    proper 正确 合适 vertex(vertices)顶点 respectively 个别 分别 indices 指标 索引 shipping 运输 incompatible 不相容 oxidiz ...

  6. TF-GNN踩坑记录(三)

    引言 Batch size问题 在Tensorflow-GNN中使用batch size除了需要注意上面的链接问题之外,最近我在调试的发现,使用了merge_batch_to_components() ...

  7. 前端ajax发送post 请求 json格式 springMVC报错415

    如标题所示 后端填坑日记 在使用springMVC的时候发现 后端使用@RequestBody注解会报错415 不支持的媒体类型 相信很多小伙伴都遇到过或者正在面临这个报错 提示错误:The serv ...

  8. Linux系统管理_网络管理

    常用网络指令 yum -y install net-tools #安装ifconfig工具 ifconfig #查看网络配置 ifup ens33 #启用网卡 ifdown ens33 #禁用网卡 s ...

  9. 题解 SP10500 HAYBALE - Haybale stacking

    前言 想了好久树状数组啥的,后来想想写打个差分再说,结果写完一遍AC了-- 强烈安利 题意 一个由 \(n\) 个元素组成的序列,给出 \(k\) 个操作,每次将 \(a\sim b\) 加上 \(1 ...

  10. SpringCloud(六) - RabbitMQ安装,三种消息发送模式,消息发送确认,消息消费确认(自动,手动)

    1.安装erlang语言环境 1.1 创建 erlang安装目录 mkdir erlang 1.2 上传解压压缩包 上传到: /root/ 解压缩# tar -zxvf otp_src_22.0.ta ...