具有相同地址的两个对象不相等(==)
Two objects with same address not equal (==)
我有一个 属性 和一个 Team
类型的方法:
this.team
和 flag.getTeam()
(这只是 属性 的单行 getter)。
以下是相应的 toString()
输出:
org.bukkit.craftbukkit.v1_12_R1.scoreboard.CraftTeam@674e0730
和 org.bukkit.craftbukkit.v1_12_R1.scoreboard.CraftTeam@674e0730
team == flag.getTeam()
returns false
, 而
team.hashCode() == flag.getTeam().hashCode()
returns true
和
team.toString().equals(flag.getTeam().toString())
returns true
public class PlayerTimer extends BukkitRunnable {
Domination plugin;
Player player;
Team team;
public PlayerTimer(Domination plugin, Player player) {
this.plugin = plugin;
this.player = player;
for (Team team : plugin.getWorldGameScoreboards().get(plugin.getCurrentWorld()).getTeams()) {
for (OfflinePlayer offlinePlayer : team.getPlayers()) {
if (offlinePlayer.getPlayer() == player) {
this.team = team;
break;
}
}
if (this.team != null) break;
}
}
@Override
public void run() {
for (Flag flag : plugin.getWorldFlags().get(plugin.getCurrentWorld())) {
for (OfflinePlayer offlinePlayer : team.getPlayers()) {
if (offlinePlayer.isOnline()) {
Player player = offlinePlayer.getPlayer();
double scaledDistance = player.getLocation().distance(flag.getLocation()) / 5; // max 5 blocks away
if (scaledDistance < 1) {
plugin.log(team + " : " + flag.getTeam() + ", " + (team == flag.getTeam()) + "; " + team.equals(flag.getTeam()) + (team.hashCode() == flag.getTeam().hashCode()) + "^ " + team.toString().equals(flag.getTeam().toString());
...
}
}
}
}
}
}
为什么 ==
没有返回 true
?
答案是您正在尝试比较对象。两个对象可以有相同的值,但它们在内存中的位置不同。当您使用 == 时,您比较的是指针(它们在内存中具有不同的地址)而不是对象值。为此,您应该像在第三行中那样使用 .equals() 。
如果对象是在相同的 "way" 中创建的,那么 hashCode 将是相同的(使用相同的 class 和字段,因此 hashCode 方程给出相同的值 - 这是正确的)。总而言之,当你在两个具有相同属性值的对象上使用 == 时,它们实际上是两个具有不同内存地址的不同对象。
我认为误解来自 toString()
方法的实现方式。在一个对象上调用 toString
将产生一个字符串 equivalent to the following value
getClass().getName() + '@' + Integer.toHexString(hashCode())
要实现的关键点是 Object
的哈希码是 based on memory location, hashcode for a String
is based on the String
's value。因此可以产生相同的 toString()
输出,不同的 String
对象具有相同的内容。
我有一个 属性 和一个 Team
类型的方法:
this.team
和 flag.getTeam()
(这只是 属性 的单行 getter)。
以下是相应的 toString()
输出:
org.bukkit.craftbukkit.v1_12_R1.scoreboard.CraftTeam@674e0730
和 org.bukkit.craftbukkit.v1_12_R1.scoreboard.CraftTeam@674e0730
team == flag.getTeam()
returns false
, 而
team.hashCode() == flag.getTeam().hashCode()
returns true
和
team.toString().equals(flag.getTeam().toString())
returns true
public class PlayerTimer extends BukkitRunnable {
Domination plugin;
Player player;
Team team;
public PlayerTimer(Domination plugin, Player player) {
this.plugin = plugin;
this.player = player;
for (Team team : plugin.getWorldGameScoreboards().get(plugin.getCurrentWorld()).getTeams()) {
for (OfflinePlayer offlinePlayer : team.getPlayers()) {
if (offlinePlayer.getPlayer() == player) {
this.team = team;
break;
}
}
if (this.team != null) break;
}
}
@Override
public void run() {
for (Flag flag : plugin.getWorldFlags().get(plugin.getCurrentWorld())) {
for (OfflinePlayer offlinePlayer : team.getPlayers()) {
if (offlinePlayer.isOnline()) {
Player player = offlinePlayer.getPlayer();
double scaledDistance = player.getLocation().distance(flag.getLocation()) / 5; // max 5 blocks away
if (scaledDistance < 1) {
plugin.log(team + " : " + flag.getTeam() + ", " + (team == flag.getTeam()) + "; " + team.equals(flag.getTeam()) + (team.hashCode() == flag.getTeam().hashCode()) + "^ " + team.toString().equals(flag.getTeam().toString());
...
}
}
}
}
}
}
为什么 ==
没有返回 true
?
答案是您正在尝试比较对象。两个对象可以有相同的值,但它们在内存中的位置不同。当您使用 == 时,您比较的是指针(它们在内存中具有不同的地址)而不是对象值。为此,您应该像在第三行中那样使用 .equals() 。 如果对象是在相同的 "way" 中创建的,那么 hashCode 将是相同的(使用相同的 class 和字段,因此 hashCode 方程给出相同的值 - 这是正确的)。总而言之,当你在两个具有相同属性值的对象上使用 == 时,它们实际上是两个具有不同内存地址的不同对象。
我认为误解来自 toString()
方法的实现方式。在一个对象上调用 toString
将产生一个字符串 equivalent to the following value
getClass().getName() + '@' + Integer.toHexString(hashCode())
要实现的关键点是 Object
的哈希码是 based on memory location, hashcode for a String
is based on the String
's value。因此可以产生相同的 toString()
输出,不同的 String
对象具有相同的内容。