1. 概述
在Java中,如果我们不恰当地比较两个byte
数组,可能会得到意想不到的结果。在这篇简短教程中,我们将学习如何正确地按值比较两个数组。
2. 问题介绍
一个例子可以快速解释这个问题。假设我们有一个字符串:
final static String INPUT = "I am a magic string.";
然后,我们使用String.getBytes()
方法从上述字符串获取两个字节数组:
final static byte[] ARRAY1 = INPUT.getBytes();
final static byte[] ARRAY2 = INPUT.getBytes();
显然,如果我们比较ARRAY1
和ARRAY2
,我们期望这两个数组在值上是相等的,因为它们是由相同的输入字符串创建的。
接下来,让我们看看可能犯的常见错误,并找出正确的比较方法。
为了简化,我们将使用单元测试断言来验证每种比较方法是否返回预期结果。
3. ==
运算符和equals()
方法并非理想选择
在Java中,==
称为“等于”运算符。首先,让我们尝试使用*==*
运算符比较两个数组:
assertFalse(ARRAY1 == ARRAY2);
上面的简单测试运行时通过了。也就是说,ARRAY1 == ARRAY2
返回false
,即使两个数组中的元素在值上相同——这并不是我们期望的结果。这是因为==
运算符比较的是两个数组的内存地址,而不是它们的内容。这意味着两个数组可以有相同的内容,但它们是不同的对象。因此,即使两个数组等价,==
运算符也会返回false
。
我们可能已经了解了Java中==
运算符与equals()
方法的区别:==
执行引用平等检查,而equals()
方法执行值平等检查。
由于我们的目标是比较两个数组的值,让我们创建另一个简单的测试,使用equals()
方法比较ARRAY1
和ARRAY2
:
assertFalse(ARRAY1.equals(ARRAY2));
如果运行这个测试,它也会通过。这意味着equals()
方法也没有给出我们期望的结果。接下来,让我们弄清楚为什么equals()
没有正确工作。
当我们调用ARRAY1.equals(ARRAY2)
时,实际上是调用了Object
类的equals()
方法。让我们看看Object
类的equals()
方法的实现:
public boolean equals(Object obj) {
return (this == obj);
}
如我们所见,Object
的equals()
方法内部使用==
运算符比较两个对象。对于数组,==
和equals()
是一样的,因此它们都执行引用平等检查。
4. 使用Arrays.equals()
方法
现在我们知道==
运算符和equals()
方法都不是检查两个数组值等同的正确方式。然而,在Java编程中,两个数组的值比较是一个相当常见的操作。因此,Java标准库提供了Arrays.equals()
方法来完成这项任务:
assertTrue(Arrays.equals(ARRAY1, ARRAY2));
如果运行这个方法,测试会通过。所以,Arrays.equals()
返回了我们两个byte
数组值比较的预期结果。
此外,Arrays.equals()
方法适用于其他类型的数组。我们应该使用Arrays.equals()
方法来检查所有类型数组的值等同性。
最后,让我们看看两个String
数组的值比较示例:
String[] strArray1 = new String[] { "Java", "is", "great" };
String[] strArray2 = new String[] { "Java", "is", "great" };
assertFalse(strArray1 == strArray2);
assertFalse(strArray1.equals(strArray2));
assertTrue(Arrays.equals(strArray1, strArray2));
在上面的代码中,strArray1
和strArray2
的内容相同。测试结果显示,*==*
和equals()
报告为false
,但使用Arrays.equals()
方法给出了预期结果。
5. 总结
在这篇文章中,我们讨论了比较两个数组内容时的常见陷阱。还探讨了如何正确比较两个byte
数组的值。
==
运算符和equals()
方法都对数组执行引用平等检查。如果需要比较两个数组的值,应该使用Arrays.equals(array1, array2)
方法。
像往常一样,这里展示的所有代码片段都可以在GitHub上找到。