instanceof和Class.isAssignableFrom的区别
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
- 声明一个 class 类的对象,判断 obj 是否为 class 类的实例对象
- 声明一个 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 性能
通过简单的测试,性能由好到坏依次是:
- instanceof
- isInstance
- 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
一样,除了下述区别:
- isInstance的参数是对象,isAssignableFrom的参数是类
- isInstance的参数可以是null, isAssignableFrom参数不可为null
- 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的区别的更多相关文章
- 判断一个类是否为另一个类的实例 instanceof关键字和isAssignableFrom方法的区别
Which of the following is better? a instanceof B or B.class.isAssignableFrom(a.getClass()) The only ...
- Java中instanceof和isInstance的具体区别
Java中instanceof和isInstance的具体区别 在Think in Java泛型这一章遇到这个问题,一些博客模糊提到了isInstance是instanceof的动态实现,查阅文档参考 ...
- instanceof, isinstance,isAssignableFrom的区别
instanceof运算符 只被用于对象引用变量,检查左边的被测试对象 是不是 右边类或接口的 实例化.如果被测对象是null值,则测试结果总是false. 形象地:自身实例或子类实例 instanc ...
- instanceof、 isinstance 与 isAssignableFrom的区别
instanceof运算符 只被用于对象引用变量,检查左边的被测试对象 是不是 右边类或接口的 实例化.如果被测对象是null值,则测试结果总是false. 形象地:自身实例或子类实例 instanc ...
- instanceof、isInstance、isAssignableFrom的区别
https://stackoverflow.com/questions/3949260/java-class-isinstance-vs-class-isassignablefrom 1. MyCla ...
- instanceof 与isAssignableFrom
instanceof 针对实例 isAssignableFrom针对class对象 isAssignableFrom 是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或 ...
- Class中isAssignableFrom() 方法
看Spring源码的时候看到这个方法: protected WebApplicationContext createWebApplicationContext(ServletContext sc) { ...
- [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 ...
- isAssignableFrom
instanceof 针对实例 isAssignableFrom针对class对象 isAssignableFrom 是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类 ...
- 徒手用Java来写个Web服务器和框架吧<第三章:Service的实现和注册>
徒手用Java来写个Web服务器和框架吧<第一章:NIO篇> 徒手用Java来写个Web服务器和框架吧<第二章:Request和Response> 这一章先把Web框架的功能说 ...
随机推荐
- MySQL8配置文件
- linux软链接的创建、修改和删除
创建 ln -s [源文件或目录] [目标文件或目录] 修改 ln –snf [新的源文件或目录] [目标文件或目录] 删除 rm –rf 软链接名称 注意,上面这种形式可能会让人产生担忧,害怕删除的 ...
- NSIS自定义目录选择页面制作之安装…
在nsis制作自定义界面中,目录选择页面个人感觉最为繁琐,因为该界面不仅涉及到界面控件的创建,还要涉及到控件消息传递和状态改变时的回调函数通告. 迅雷界面为例: 其中安装目录中的8盘符,在本机中并不存 ...
- aws-s3-国际global与国内CN的一些说明
S3云存储国际版最近经常被墙,国内部分地区有时能正常上传下载,有时也会直接报错网络错误等信息, 所以建议S3使用国内AWS的.国内S3与国外S3在使用时需要注意以下几点: 1)URL不通用 国际版的S ...
- P7961 [NOIP2021] 数列 (DP 刷表法)
(n<=30,是个多维的DP) v数组就是用来计算权值的,一共有m+1个.将S看做一个二进制数,按照题目S的定义,相当于在S的每一位可以随便+1(满足限制情况下),一共可以加n次. 我们来建立D ...
- C#中Math.Round()实现中国式四舍五入问题
C#中的Math.Round()并不是使用的"四舍五入"法.实际上是四舍六入五取偶. 对于这个问题我们常见的解决方式是使用MidpointRounding.AwayFromZero ...
- Tableau Server注册安装及配置详细教程
Tableau Server注册安装及配置详细教程 本文讲解的是 Tableau Server 10.0 版本的安装及配置 这里分享的 TableauServer 安装版本为64位的10.0版本Ser ...
- Vue学习之--------脚手架的分析、Ref属性、Props配置(2022/7/28)
欢迎大家加入我的社区:http://t.csdn.cn/Q52km 社区中不定时发红包 文章目录 1.脚手架的分析 2.ref属性 2.1 基础知识 2.2 代码实现 2.3 测试效果 3.Props ...
- JSON parse error: Cannot deserialize value of type `java.lang.Integer` from Boolean value
问题原因所在:前端Vue传输的数据字段类型和后端实体类字段不一致. 我的实体类字段是int类型.前端传输的数据是布尔类型. 文章目录 1.后端方法 2.实体类字段 2.前端传输的数据 1.后端方法 @ ...
- Three.js中加载外部fbx格式的模型素材
index.html部分: index.js部分: Scene.js部分: