为什么 hamcrest 说字节 0 不等于 int 0?
Why does hamcrest say that a byte 0 is not equal to an int 0?
考虑以下使用标准 JUnit
断言和 hamcrest 的 assertThat
的测试用例:
byte b = 0;
int i = 0;
assertEquals(b, i); // success
assertThat(b, equalTo(i)); // java.lang.AssertionError: Expected: <0> but: was <0>
if (b == i) {
fail(); // test fails, so b == i is true for the JVM
}
为什么会这样?对于 JVM,这些值显然是相等的,因为 b == i
是 true
,那么为什么 hamcrest
会失败?
Assert#assertThat
是一种通用方法。原始类型不适用于泛型。在这种情况下,byte
和 int
分别装箱到 Byte
和 Integer
。
然后变成(在assertThat
内)
Byte b = 0;
Integer i = 0;
b.equals(i);
Byte#equals(Object)
的实现检查参数是否为 Byte
类型,如果不是,则立即返回 false
。
另一方面,assertEquals
是 Assert#assertEquals(long, long)
,在这种情况下,byte
和 int
参数都被提升为 long
值。在内部,这在两个相等的原始 long
值上使用 ==
。
请注意,此装箱转换有效,因为 assertThat
声明为
public static <T> void assertThat(T actual, Matcher<? super T> matcher) {
其中 byte
被装箱到 T
的 Byte
,int
被装箱到 Integer
(在对equalTo
),但推断为 Number
以匹配 Matcher<? super T>
.
这适用于 Java 8 的改进通用推理。您需要显式类型参数才能使其在 Java 7.
中工作
发生这种情况是因为 int
和 byte
被装箱到 Integer
和 Byte
,因为 hamcrest 匹配器对对象而不是基元进行操作。所以你正在比较一个 Integer
和一个 Byte
,而 Byte.equals()
的实现是:
public boolean equals(Object obj) {
if (obj instanceof Byte) {
return value == ((Byte)obj).byteValue();
}
return false;
}
和Integer.equals()
:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
换句话说,Integer
和 Byte
总是不相等的。比较基元时,只需使用 Assert.assertEquals
即可。 hamcrest 匹配器功能强大,但主要用于(复杂的)对象断言。
考虑以下使用标准 JUnit
断言和 hamcrest 的 assertThat
的测试用例:
byte b = 0;
int i = 0;
assertEquals(b, i); // success
assertThat(b, equalTo(i)); // java.lang.AssertionError: Expected: <0> but: was <0>
if (b == i) {
fail(); // test fails, so b == i is true for the JVM
}
为什么会这样?对于 JVM,这些值显然是相等的,因为 b == i
是 true
,那么为什么 hamcrest
会失败?
Assert#assertThat
是一种通用方法。原始类型不适用于泛型。在这种情况下,byte
和 int
分别装箱到 Byte
和 Integer
。
然后变成(在assertThat
内)
Byte b = 0;
Integer i = 0;
b.equals(i);
Byte#equals(Object)
的实现检查参数是否为 Byte
类型,如果不是,则立即返回 false
。
另一方面,assertEquals
是 Assert#assertEquals(long, long)
,在这种情况下,byte
和 int
参数都被提升为 long
值。在内部,这在两个相等的原始 long
值上使用 ==
。
请注意,此装箱转换有效,因为 assertThat
声明为
public static <T> void assertThat(T actual, Matcher<? super T> matcher) {
其中 byte
被装箱到 T
的 Byte
,int
被装箱到 Integer
(在对equalTo
),但推断为 Number
以匹配 Matcher<? super T>
.
这适用于 Java 8 的改进通用推理。您需要显式类型参数才能使其在 Java 7.
中工作发生这种情况是因为 int
和 byte
被装箱到 Integer
和 Byte
,因为 hamcrest 匹配器对对象而不是基元进行操作。所以你正在比较一个 Integer
和一个 Byte
,而 Byte.equals()
的实现是:
public boolean equals(Object obj) {
if (obj instanceof Byte) {
return value == ((Byte)obj).byteValue();
}
return false;
}
和Integer.equals()
:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
换句话说,Integer
和 Byte
总是不相等的。比较基元时,只需使用 Assert.assertEquals
即可。 hamcrest 匹配器功能强大,但主要用于(复杂的)对象断言。