How to solve the problem: int cannot be dereferenced
Here I have some value which two of them are integer and I can't call a method on them since they are not reference. How can I solve this?
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 == nu开发者_JAVA百科ll) ? 0 : srcPort.hashCode());
return result;
}
Also, I have an equal method too, a part of it with the error is shown below ,which the same as above I can not compare int with a 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;
}
How can I solve this error?
Writing hashcode
and equals
can be tedious and/or error-prone, and IDEs such as Eclipse can actually automate this task for you. There are many third party libraries that can facilitate this functionality as well.
To use something from the standard library, I recommend doing the following:
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());
}
This uses varargs, autoboxing, and java.util.Arrays
utility method implementation for equality and hashcode of arrays. This will have an adequate (though perhaps not optimal) performance, but the code is succint and readable, and can always be optimized later if/when necessary.
Third party library options
From Apache Commons Lang, you can use EqualsBuilder
and HashCodeBuilder
.
The documentation has example of typical usage:
@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();
}
The resulting code is very readable, very maintainable, and less error prone.
Related questions
- Overriding equals and hashCode in Java
For the hashcode
method, you can just leave the ints as they are. Ints are their own hascodes. For the equals
method, just compare them using =
. So the code becomes:
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;
}
}
Writing correct implementations of hashCode
and equals
is tricky. Better use your IDE to generate them. That's what I did here too.
You need to use the boxed primitives, specifically Integer
. There's a similar object for each primitive, and they define the methods you're interested in (hashCode
,equals
).
Initalise the integers to something (say -1) and compare them to -1
I don't see why you want to get the Hashcode of an integer. Hashcode takes an object and returns a unique(?) integer based on the object. An integer is just a primitive object and you should need to get a hashcode from it to identify it.
I would just refer to the integers directly and have a check for -1 (if you initialise them to -1) instead of a check to null. (It is my understanding that a port is never -1, do correct me if this is false)
srcPort
and dstPort
are primitive int
s.
In your hashCode()
method, you are comparing dstPort
and srcPort
to null
. You can't do that with primitive types in Java. Just write the lines in your hashCode()
method like this:
result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
result = prime * result + dstPort;
result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
result = prime * result + srcPort;
In your equals()
method, you are trying to call the equals()
method on srcPort
. You cannot call methods on primitive types in Java. Use ==
to compare pritimive types.
Note that your equals()
method also contains the same block of code twice; this is most likely a mistake. And don't you have to check srcAddr
and dstAddr
as well in your equals()
method? What is other
in your equals()
method? Is this the complete code or only part of it?
I think Shakedown has the answer for you, just used the boxed Integer type like so:
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;
}
or alternatively use 0 as a default value (since that's what you return if the value isn't set anyway) like so:
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;
}
This way you don't need to worry about the implicit cost of auto-boxing if that is an issue
There are two problems here. First, int
s declared at the class level as instance or class variables are always initialized to a value. It doesn't matter what that value is, they are defined to be something, even if you don't explicitly do it. Second, it makes no sense to call hashCode()
on something that is a primitive type as these don't have methods you can invoke.
My implementation would look something like this:
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;
}
精彩评论