--IntelliJ-Version ist die neueste Version 2019.2 vom 13. September 2019
$ java -version
java version "10.0.2" 2018-07-17
Wenn ich meine eigene Klasse in Java definiere, funktioniert meine eigene Klassensammlung nur dann ordnungsgemäß, wenn ich equals
und hashCode
ordnungsgemäß überschreibe.
Dieses Mal habe ich eine einfache Originalklasse definiert und mit einer IDE namens IntelliJ equals
und hashCode
generiert, aber ich war süchtig danach, also werde ich sie teilen.
--Erster Code, den ich geschrieben habe: Ich habe meine eigene Klasse namens "DistanceToNode" definiert und für diese Klasse Folgendes getan:
import java.util.*;
public class TestEqualsOld {
public static void main(String[] args) {
Set<DistanceToNode> someSet = new HashSet<>();
someSet.add(new DistanceToNode(1, 2));
System.out.println("actual = " + someSet.size() + " expected = 1");
someSet.add(new DistanceToNode(2, 3));
System.out.println("actual = " + someSet.size() + " expected = 2");
someSet.remove(new DistanceToNode(1, 2));
System.out.println("actual = " + someSet.size() + " expected = 1");
boolean flag = new DistanceToNode(3, 4).equals(new DistanceToNode(3, 4));
System.out.println("actual = " + flag + " expected = true");
}
}
class DistanceToNode {
private int dist;
private int index;
public DistanceToNode(int dist, int index) {
this.dist = dist;
this.index = index;
}
public int getDist() {
return dist;
}
public int getIndex() {
return index;
}
}
equals
und hashCode
nicht überschrieben werden, wird stattdessen die Methode der Object-Klasse verwendet, bei der es sich um eine Superklasse handelt, um festzustellen, ob die Referenzen gleich sind, und nicht, ob die Werte gleich sind. Gibt es.actual = 1 expected = 1
actual = 2 expected = 2
actual = 2 expected = 1
actual = false expected = true
import java.util.*;
public class TestEqualsOld {
public static void main(String[] args) {
Set<DistanceToNode> someSet = new HashSet<>();
someSet.add(new DistanceToNode(1, 2));
System.out.println("actual = " + someSet.size() + " expected = 1");
someSet.add(new DistanceToNode(2, 3));
System.out.println("actual = " + someSet.size() + " expected = 2");
someSet.remove(new DistanceToNode(1, 2));
System.out.println("actual = " + someSet.size() + " expected = 1");
boolean flag = new DistanceToNode(3, 4).equals(new DistanceToNode(3, 4));
System.out.println("actual = " + flag + " expected = true");
}
}
class DistanceToNode {
private int dist;
private int index;
public DistanceToNode(int dist, int index) {
this.dist = dist;
this.index = index;
}
public int getDist() {
return dist;
}
public int getIndex() {
return index;
}
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
if (!super.equals(object)) return false;
DistanceToNode that = (DistanceToNode) object;
return dist == that.dist &&
index == that.index;
}
public int hashCode() {
return Objects.hash(super.hashCode(), dist, index);
}
}
equals
und hashCode
?actual = 1 expected = 1
actual = 2 expected = 2
actual = 2 expected = 1
actual = false expected = true
――Ich hatte hier einige Tage lang Kopfschmerzen, aber wenn Sie sich den von IntelliJ generierten Code genau ansehen, verwenden sowohl equals
als auch hashCode
intern die Methoden super.equals und super.hashCode !!! Hier Ich dachte, dass es funktionieren würde, wenn ich es so umschreibe, dass es nicht super.equals oder super.hashCode verwendet, also habe ich den Code wie folgt geändert. (Ich habe auch den Klassennamen geändert.)
import java.util.*;
public class TestEquals {
public static void main(String[] args) {
Set<DistanceToNode> someSet = new HashSet<>();
someSet.add(new DistanceToNode(1, 2));
System.out.println(someSet.size());
someSet.add(new DistanceToNode(2, 3));
System.out.println(someSet.size());
someSet.remove(new DistanceToNode(1, 2));
System.out.println(someSet.size());
boolean flag = new DistanceToNode(3, 4).equals(new DistanceToNode(3, 4));
System.out.println(flag);
}
}
class DistanceToNode {
private int dist;
private int index;
public DistanceToNode(int dist, int index) {
this.dist = dist;
this.index = index;
}
public int getDist() {
return dist;
}
public int getIndex() {
return index;
}
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
// if (!super.equals(object)) return false;
DistanceToNode distanceToNode = (DistanceToNode) object;
return dist == distanceToNode.dist &&
index == distanceToNode.index;
}
@Override
public int hashCode() {
int result = 31;
result = 31 * result + dist;
result = 31 * result + index;
return result;
// return Objects.hash(super.hashCode(), dist, index);
}
}
actual = 1 expected = 1
actual = 2 expected = 2
actual = 1 expected = 1
actual = true expected = true
――IntelliJ ist praktisch, aber ich habe eine wertvolle Lektion gelernt, dass Sie nicht blind sein sollten und manchmal Ihren eigenen Kopf benutzen müssen. ――Ich habe mich gefragt, warum ein solcher Code erstellt wird, wenn IntelliJ automatisch Gleichheits- und Hashcode generiert. Gibt es einen vernünftigen Grund? ――Ich wurde in den Kommentaren darüber informiert, aber für Klassen, die eine andere konkrete Klasse als die Object-Klasse erben, möchte ich nicht gleich true setzen, wenn die Mitgliedsvariablen der übergeordneten Klasse nicht übereinstimmen. Ich denke, deshalb ist es so. In diesem Fall empfand ich dieses Anliegen von IntelliJ als störend, da es sich um eine Klasse handelt, die die Object-Klasse direkt erbt. Ich glaube nicht, dass es für die IDE schwierig ist festzustellen, ob es sich um eine Klasse handelt, die die Object-Klasse direkt erbt. Daher frage ich mich, ob ein Kommentar des IntelliJ-Entwicklers dies beheben wird. --__ 9/14 Update __: Etwas Ähnliches wie die Frage, die ich hatte, wurde bereits veröffentlicht-> https://intellij-support.jetbrains.com/hc/en-us/community/posts/206873545 -Strange-generate-hashCode-
Recommended Posts