这里我有一些值,其中两个是整数,我不能调用它们的方法,因为它们不是引用。我该如何解决这个问题?
String srcAddr, dstAddr, protocol;
int srcPort, dstPort;
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
result = prime * result + ((dstPort == null) ? 0 : dstPort.hashCode());
result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
result = prime * result + ((srcPort == null) ? 0 : srcPort.hashCode());
return result;
}
另外,我也有一个相同的方法,下面显示了错误的一部分,与上面相同我无法将int与null进行比较。
@Override
public boolean equals(Object obj) {
if (srcPort == null) {
if (other.srcPort != null)
return false;
} else if (!srcPort.equals(other.srcPort))
return false;
if (srcPort == null) {
if (other.srcPort != null)
return false;
} else if (!srcPort.equals(other.srcPort))
return false;
}
如何解决此错误?
答案 0 :(得分:4)
编写hashcode
和equals
可能会很乏味和/或容易出错,而像Eclipse这样的IDE实际上可以为您自动执行此任务。有许多第三方库也可以促进此功能。
要使用标准库中的内容,我建议您执行以下操作:
import java.util.Arrays;
// conveniently packs varargs to array
private static Object[] pack(Object... objs) {
return objs;
}
private Object[] fieldsAsArray() {
return pack(srcAddr, dstAddr, protocol, srcPort, dstPort);
}
@Override public int hashCode() {
return Arrays.hashCode(this.fieldsAsArray());
}
@Override public boolean equals(Object o) {
// TODO: instanceof check, cast and assign o to other
return Arrays.equals(this.fieldsAsArray(), other.fieldsAsArray());
}
这使用varargs,autoboxing和java.util.Arrays
实用程序方法实现数组的相等性和哈希码。这将具有足够的(尽管可能不是最佳的)性能,但代码是简洁和可读的,并且如果/在必要时可以随后进行优化。
从Apache Commons Lang,您可以使用EqualsBuilder
和HashCodeBuilder
。
文档中有典型用法示例:
@Override public boolean equals(Object obj) {
if (obj == null) { return false; }
if (obj == this) { return true; }
if (obj.getClass() != this.getClass()) {
return false;
}
MyClass other = (MyClass) obj;
return new EqualsBuilder()
.appendSuper(super.equals(obj))
.append(field1, other.field1)
.append(field2, other.field2)
.append(field3, other.field3)
.isEquals();
}
@Override public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(field1)
.append(field2)
.append(field3)
.toHashCode();
}
生成的代码非常易读,易于维护,并且不易出错。
答案 1 :(得分:2)
对于hashcode
方法,您可以按原样保留整数。 Ints是他们自己的hascodes。对于equals
方法,只需使用=
进行比较即可。所以代码变成了:
public class Connection {
String srcAddr, dstAddr, protocol; int srcPort, dstPort;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
result = prime * result + dstPort;
result = prime * result
+ ((protocol == null) ? 0 : protocol.hashCode());
result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
result = prime * result + srcPort;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Connection other = (Connection) obj;
if (dstAddr == null) {
if (other.dstAddr != null)
return false;
} else if (!dstAddr.equals(other.dstAddr))
return false;
if (dstPort != other.dstPort)
return false;
if (protocol == null) {
if (other.protocol != null)
return false;
} else if (!protocol.equals(other.protocol))
return false;
if (srcAddr == null) {
if (other.srcAddr != null)
return false;
} else if (!srcAddr.equals(other.srcAddr))
return false;
if (srcPort != other.srcPort)
return false;
return true;
}
}
编写hashCode
和equals
的正确实现非常棘手。更好地使用IDE来生成它们。这就是我在这里所做的。
答案 2 :(得分:1)
答案 3 :(得分:0)
将整数初始化为某事(比如-1)并将它们与-1进行比较
我不明白你为什么要得到一个整数的Hashcode。 Hashcode接受一个对象并返回一个基于该对象的唯一(?)整数。整数只是一个原始对象,您应该从中获取一个哈希码来识别它。
我只是直接引用整数并检查-1(如果将它们初始化为-1)而不是检查为null。 (据我所知,端口永远不会为-1,如果这是假的话,请纠正我)
答案 4 :(得分:0)
srcPort
和dstPort
是原始int
s。
在hashCode()
方法中,您要将dstPort
和srcPort
与null
进行比较。你不能用Java中的原始类型做到这一点。只需在hashCode()
方法中写下这样的行:
result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
result = prime * result + dstPort;
result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
result = prime * result + srcPort;
在equals()
方法中,您尝试在equals()
上调用srcPort
方法。您无法在Java中调用基本类型的方法。使用==
来比较确切类型。
请注意,您的equals()
方法也包含两次相同的代码块;这很可能是一个错误。您不必在srcAddr
方法中检查dstAddr
和equals()
吗? other
方法中的equals()
是什么?这是完整的代码还是仅仅是其中的一部分?
答案 5 :(得分:0)
这里有两个问题。首先,在类级别声明的int
作为实例或类变量始终初始化为一个值。无论该值是什么,它们都被定义为某种东西,即使您没有明确地这样做。其次,将hashCode()
调用为基本类型的东西是没有意义的,因为它们没有可以调用的方法。
我的实现看起来像这样:
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
result = prime * result + dstPort;
result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
result = prime * result + srcPort.hashCode;
return result;
}
public boolean equals(Object obj) {
if (!(obj instanceof MyClass)) {
return false;
}
//Cast obj to a MyClass
if (other.srcPort != scrPort) {
return false;
}
if (other.dstPort != dstPort) {
return false;
}
//Check the other variables too.
//We didn't fall into any if-statements.
return true;
}
答案 6 :(得分:0)
我认为Shakedown有你的答案,只是使用盒装的Integer类型:
String srcAddr, dstAddr, protocol; Integer srcPort, dstPort;
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
result = prime * result + ((dstPort == null) ? 0 : dstPort);
result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
result = prime * result + ((srcPort == null) ? 0 : srcPort);
return result;
}
或者使用0作为默认值(因为如果没有设置值,那就是你返回的内容),如下所示:
String srcAddr="", dstAddr=""; int srcPort=0,dstPort=0; //empty string has hashCode 0
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + dstAddr.hashCode();
result = prime * result + dstPort;
result = prime * result + srcAddr.hashCode();
result = prime * result + srcPort;
return result;
}
这样,如果出现问题,您无需担心自动装箱的隐性成本