相同的多个向下转换;他们会被优化吗?
Same multiple downcasts in equals; will they be optimised?
我倾向于在 Java 中将我的 equals 方法写成一行...
class Test {
private String a = "";
private Integer b = Integer.MIN_VALUE;
private Long c = Long.MIN_VALUE;
public Test(final String a, final Integer b, final Long c) {
this.a = a;
this.b = b;
this.c = c;
}
@Override
public boolean equals(final Object obj) {
return obj instanceof Test && ((Test) obj).a.equals(this.a)
&& ((Test) obj).b.equals(this.b)
&& ((Test) obj).c.equals(this.c);
}
}
如您所见,在这种方法中,我多次将 Object 实例向下转换为 Test 实例。我的问题是,它是否会被编译器优化,所以只有一个向下转换而不是三个,如果我像这样编写我的 equals 方法?
public boolean equals(final Object obj) {
if (obj instanceof Test) {
final Test test = (Test) obj;
return test.a.equals(this.a) && test.b.equals(this.b)
&& test.c.equals(this.c);
} else {
return false;
}
}
它不是评论中 question 的副本,因为我在这里对 equals 方法(6 行对 3 行)实现的简洁性感兴趣,但不以性能下降为代价。在另一个问题中,区别是一行。
当我反编译 class 时,我发现 Eclipse 编译器和 javac
确实在 equals
方法中产生了三个 checkcast
指令,因此没有进行优化。
当通过 Hotspot 优化时,可能是 Hotspot 可以计算出一个 cast 就足够了。
反编译后的字节码:
public boolean equals(java.lang.Object);
Code:
0: aload_1
1: instanceof #13 // class sov/Test
4: ifeq 62
7: aload_1
8: checkcast #13 // class sov/Test
11: getfield #3 // Field a:Ljava/lang/String;
14: aload_0
15: getfield #3 // Field a:Ljava/lang/String;
18: invokevirtual #14 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
21: ifeq 62
24: aload_1
25: checkcast #13 // class sov/Test
28: getfield #7 // Field b:Ljava/lang/Integer;
31: aload_0
32: getfield #7 // Field b:Ljava/lang/Integer;
35: invokevirtual #15 // Method java/lang/Integer.equals:(Ljava/lang/Object;)Z
38: ifeq 62
41: aload_1
42: checkcast #13 // class sov/Test
45: getfield #12 // Field c:Ljava/lang/Long;
48: aload_0
49: getfield #12 // Field c:Ljava/lang/Long;
52: invokevirtual #16 // Method java/lang/Long.equals:(Ljava/lang/Object;)Z
55: ifeq 62
58: iconst_1
59: goto 63
62: iconst_0
63: ireturn
我倾向于在 Java 中将我的 equals 方法写成一行...
class Test {
private String a = "";
private Integer b = Integer.MIN_VALUE;
private Long c = Long.MIN_VALUE;
public Test(final String a, final Integer b, final Long c) {
this.a = a;
this.b = b;
this.c = c;
}
@Override
public boolean equals(final Object obj) {
return obj instanceof Test && ((Test) obj).a.equals(this.a)
&& ((Test) obj).b.equals(this.b)
&& ((Test) obj).c.equals(this.c);
}
}
如您所见,在这种方法中,我多次将 Object 实例向下转换为 Test 实例。我的问题是,它是否会被编译器优化,所以只有一个向下转换而不是三个,如果我像这样编写我的 equals 方法?
public boolean equals(final Object obj) {
if (obj instanceof Test) {
final Test test = (Test) obj;
return test.a.equals(this.a) && test.b.equals(this.b)
&& test.c.equals(this.c);
} else {
return false;
}
}
它不是评论中 question 的副本,因为我在这里对 equals 方法(6 行对 3 行)实现的简洁性感兴趣,但不以性能下降为代价。在另一个问题中,区别是一行。
当我反编译 class 时,我发现 Eclipse 编译器和 javac
确实在 equals
方法中产生了三个 checkcast
指令,因此没有进行优化。
当通过 Hotspot 优化时,可能是 Hotspot 可以计算出一个 cast 就足够了。
反编译后的字节码:
public boolean equals(java.lang.Object);
Code:
0: aload_1
1: instanceof #13 // class sov/Test
4: ifeq 62
7: aload_1
8: checkcast #13 // class sov/Test
11: getfield #3 // Field a:Ljava/lang/String;
14: aload_0
15: getfield #3 // Field a:Ljava/lang/String;
18: invokevirtual #14 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
21: ifeq 62
24: aload_1
25: checkcast #13 // class sov/Test
28: getfield #7 // Field b:Ljava/lang/Integer;
31: aload_0
32: getfield #7 // Field b:Ljava/lang/Integer;
35: invokevirtual #15 // Method java/lang/Integer.equals:(Ljava/lang/Object;)Z
38: ifeq 62
41: aload_1
42: checkcast #13 // class sov/Test
45: getfield #12 // Field c:Ljava/lang/Long;
48: aload_0
49: getfield #12 // Field c:Ljava/lang/Long;
52: invokevirtual #16 // Method java/lang/Long.equals:(Ljava/lang/Object;)Z
55: ifeq 62
58: iconst_1
59: goto 63
62: iconst_0
63: ireturn