Meg*_*mug 441 java reflection instanceof
以下哪项更好?
a instanceof B
Run Code Online (Sandbox Code Playgroud)
要么
B.class.isAssignableFrom(a.getClass())
Run Code Online (Sandbox Code Playgroud)
我所知道的唯一区别是,当'a'为null时,第一个返回false,而第二个抛出异常.除此之外,他们总是给出相同的结果吗?
Mar*_*ski 483
使用时instanceof
,您需要知道B
编译时的类.使用isAssignableFrom()
它时可以是动态的,并在运行时更改.
Ada*_*eld 202
instanceof
只能用于引用类型,而不能用于基本类型. isAssignableFrom()
可以与任何类对象一起使用:
a instanceof int // syntax error
3 instanceof Foo // syntax error
int.class.isAssignableFrom(int.class) // true
Run Code Online (Sandbox Code Playgroud)
看到 http://java.sun.com/javase/6/docs/api/java/lang/Class.html#isAssignableFrom(java.lang.Class).
JBE*_*JBE 110
谈论绩效:
TL; DR
使用具有类似性能的isInstance或instanceof.isAssignableFrom略慢.
按性能排序:
基于JAVA 8 Windows x64上2000次迭代的基准测试,有20次预热迭代.
理论上
使用类似软的字节码查看器,我们可以将每个运算符转换为字节码.
在以下情况下:
package foo;
public class Benchmark
{
public static final Object a = new A();
public static final Object b = new B();
...
}
Run Code Online (Sandbox Code Playgroud)
JAVA:
b instanceof A;
Run Code Online (Sandbox Code Playgroud)
字节码:
getstatic foo/Benchmark.b:java.lang.Object
instanceof foo/A
Run Code Online (Sandbox Code Playgroud)
JAVA:
A.class.isInstance(b);
Run Code Online (Sandbox Code Playgroud)
字节码:
ldc Lfoo/A; (org.objectweb.asm.Type)
getstatic foo/Benchmark.b:java.lang.Object
invokevirtual java/lang/Class isInstance((Ljava/lang/Object;)Z);
Run Code Online (Sandbox Code Playgroud)
JAVA:
A.class.isAssignableFrom(b.getClass());
Run Code Online (Sandbox Code Playgroud)
字节码:
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);
Run Code Online (Sandbox Code Playgroud)
测量每个运算符使用的字节码指令的数量,我们可以预期instanceof和isInstance比isAssignableFrom更快.但是,实际性能不是由字节码决定的,而是由机器代码决定的(取决于平台).让我们为每个运营商做一个微基准测试.
基准
信用:正如@ aleksandr-dubinsky所建议的,并且感谢@yura提供基本代码,这里有一个JMH基准测试(参见本调优指南):
class A {}
class B extends A {}
public class Benchmark {
public static final Object a = new A();
public static final Object b = new B();
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public boolean testInstanceOf()
{
return b instanceof A;
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public boolean testIsInstance()
{
return A.class.isInstance(b);
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public boolean testIsAssignableFrom()
{
return A.class.isAssignableFrom(b.getClass());
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(TestPerf2.class.getSimpleName())
.warmupIterations(20)
.measurementIterations(2000)
.forks(1)
.build();
new Runner(opt).run();
}
}
Run Code Online (Sandbox Code Playgroud)
给出以下结果(得分是一个时间单位的操作数,所以得分越高越好):
Benchmark Mode Cnt Score Error Units
Benchmark.testIsInstance thrpt 2000 373,061 ± 0,115 ops/us
Benchmark.testInstanceOf thrpt 2000 371,047 ± 0,131 ops/us
Benchmark.testIsAssignableFrom thrpt 2000 363,648 ± 0,289 ops/us
Run Code Online (Sandbox Code Playgroud)
警告
instanceof
在代码的上下文中,可能比例isInstance
如... 更容易优化...举个例子,采取以下循环:
class A{}
class B extends A{}
A b = new B();
boolean execute(){
return A.class.isAssignableFrom(b.getClass());
// return A.class.isInstance(b);
// return b instanceof A;
}
// Warmup the code
for (int i = 0; i < 100; ++i)
execute();
// Time it
int count = 100000;
final long start = System.nanoTime();
for(int i=0; i<count; i++){
execute();
}
final long elapsed = System.nanoTime() - start;
Run Code Online (Sandbox Code Playgroud)
感谢JIT,代码在某些时候进行了优化,我们得到:
注意
最初这篇文章是在原始JAVA中使用for循环进行自己的基准测试,由于像Just In Time这样的优化可以消除循环,因此产生了不可靠的结果.因此,它主要测量JIT编译器优化循环所需的时间:请参阅性能测试,与迭代次数无关,以获取更多详细信息
相关问题
use*_*008 33
更直接的相当于a instanceof B
是
B.class.isInstance(a)
Run Code Online (Sandbox Code Playgroud)
当此作品(返回false)a
是null
也.
小智 22
除了上面提到的基本差异之外,instanceof运算符和Class中的isAssignableFrom方法之间存在核心细微差别.
读instanceof
为"这是(左侧部分)这个或其任何子类(右侧部分)的实例"并读x.getClass().isAssignableFrom(Y.class)
作"我可以写X x = new Y()
".换句话说,instanceof运算符检查左对象是否是右类的相同或子类,同时isAssignableFrom
检查我们是否可以将参数类(from)的对象分配给调用该方法的类的引用.
请注意,这两个都认为实际的实例不是引用类型.
考虑3个类A,B和C的示例,其中C扩展B,B扩展A.
B b = new C();
System.out.println(b instanceof A); //is b (which is actually class C object) instance of A, yes. This will return true.
System.out.println(b instanceof B); // is b (which is actually class C object) instance of B, yes. This will return true.
System.out.println(b instanceof C); // is b (which is actually class C object) instance of C, yes. This will return true. If the first statement would be B b = new B(), this would have been false.
System.out.println(b.getClass().isAssignableFrom(A.class));//Can I write C c = new A(), no. So this is false.
System.out.println(b.getClass().isAssignableFrom(B.class)); //Can I write C c = new B(), no. So this is false.
System.out.println(b.getClass().isAssignableFrom(C.class)); //Can I write C c = new C(), Yes. So this is true.
Run Code Online (Sandbox Code Playgroud)
小智 15
还有另一个区别:
null instanceof X false
无论X是什么
null.getClass().isAssignableFrom(X)将抛出NullPointerException
小智 11
还有另一个不同之处.如果要测试的类型(Class)是动态的,例如作为方法参数传递,那么instanceof将不会为您剪切它.
boolean test(Class clazz) {
return (this instanceof clazz); // clazz cannot be resolved to a type.
}
Run Code Online (Sandbox Code Playgroud)
但你可以这样做:
boolean test(Class clazz) {
return (clazz.isAssignableFrom(this.getClass())); // okidoki
}
Run Code Online (Sandbox Code Playgroud)
哎呀,我看到这个答案已经涵盖了.也许这个例子对某人有帮助.
小智 7
这个主题为我提供了一些instanceof
有所不同的见解isAssignableFrom
,所以我想我会分享一些自己的东西.
我发现isAssignableFrom
如果一个类的引用可以接受另一个类的实例,当一个类没有类的实例进行比较时,使用它是唯一的(可能不是唯一的,但可能是最简单的)方式来询问自己.
因此,我没有发现使用instanceof
运算符来比较赋值是一个好主意,当我所有的都是类时,除非我考虑从其中一个类创建一个实例; 我以为这会马虎.
instanceof不能与基本类型或泛型类型一起使用。如以下代码所示:
//Define Class< T > type ...
Object e = new Object();
if(e instanceof T) {
// Do something.
}
Run Code Online (Sandbox Code Playgroud)
错误是:无法对类型参数T执行instanceof检查。请改用它的擦除对象,因为在运行时将删除更多的通用类型信息。
由于类型删除导致无法编译,因此删除了运行时引用。但是,下面的代码将编译:
if( type.isAssignableFrom(e.getClass())){
// Do something.
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
251139 次 |
最近记录: |