Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 每次创建对象时,哈希代码都会更改_Java_Hashcode - Fatal编程技术网

Java 每次创建对象时,哈希代码都会更改

Java 每次创建对象时,哈希代码都会更改,java,hashcode,Java,Hashcode,关于hashCode,有一些东西我没有意识到。我知道如果我超越 等于,那么我也必须重写哈希代码。我也知道如果两个物体 相等,则两个对象的哈希代码必须相等。如果在equals方法中检查的字段没有更改,那么hashCode就不应该更改,对吗 如果是这样,那么我就无法理解为什么每次创建下面对象的实例时,都会得到不同的哈希代码: public class Effect { private long timestamp; private int damage; private S

关于hashCode,有一些东西我没有意识到。我知道如果我超越 等于,那么我也必须重写哈希代码。我也知道如果两个物体 相等,则两个对象的哈希代码必须相等。如果在equals方法中检查的字段没有更改,那么hashCode就不应该更改,对吗

如果是这样,那么我就无法理解为什么每次创建下面对象的实例时,都会得到不同的哈希代码:

public class Effect {

    private long timestamp;
    private int damage;
    private SquareType squareType;

    public Effect(long timestamp, int damage, SquareType squareType) {
        this.timestamp = timestamp;
        this.damage = damage;
        this.squareType = squareType;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public int getDamage() {
        return damage;
    }

    public SquareType getSquareType() {
        return squareType;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Effect effect = (Effect) o;

        if (getDamage() != effect.getDamage()) return false;
        return getSquareType() == effect.getSquareType();
    }

    @Override
    public int hashCode() {
        int result = getDamage();
        result = 31 * result + (getSquareType() != null ? getSquareType().hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        String ret = "Effect hashcode: " + hashCode();
        return ret;
    }
}
在代码中,我随着时间的推移不断创建此类对象。每次更改的唯一字段是“timestamp”,但其他两个字段不会更改(除非有特定事件)。发生的情况是,hashCode值总是不同的,即使“损害”和“平方类型”是相同的。 我在equals和hashCode中没有使用“timestamp”,所以我不明白为什么会出现这种行为

更新

这是方形的:

public enum SquareType {
    FIRE, WIND, WATER, EARTH
}
更新2

例如,如果我创建了10个Effect实例,我迭代它们,然后 打印它们(toString()返回hashCode值)我得到10个不同的值

如果效果的两个实例具有相同的“损害”和“平方类型”,则它们必须相等并具有相同的哈希代码

更新3

效果如下所示:

@Override
public void friendlyFire(BaseBullet bullet, BaseSquare square) {
    square.notifyFriendlyFire(new Effect(TimeUtils.millis(),
            square.getDamage(), square.getSquareType()), new MyKey(square.getUniqueID()));
}
唯一改变的效果字段是时间戳,我不在equals和hashCode中使用它

public void notifyFriendlyFire(Effect newEffect, MyKey key) {
    // System.out.println("The map contains the key? " + effectMap.containsKey(key));
    if(effectMap.containsKey(key)) {
        Effect oldEffect = effectMap.get(key);
        System.out.println(newEffect);
        if(!oldEffect.equals(newEffect)) {
            System.out.println("old effect changed!");
            // remove the old effect
            removeEffect(oldEffect);
            // update the map with the new effect
            effectMap.put(key, newEffect); // 
            // apply the new effect
            applyEffect(newEffect);
        }
    }
    else {
        // new effect
        effectMap.put(key, newEffect);
        applyEffect(newEffect);
    }
}
检查“if(!oldEffect.equals(newEffect))”始终为真,即使损坏和类型相同

更新4


我找到了窃听器。伤害持续增加。现在,我只想弄清楚为什么…

以下是我对您的实现的近似尝试:

package cruft;

import java.util.Date;

/**
 * Equals and hashCode test
 * Creation date 1/16/2016.
 * @link https://stackoverflow.com/questions/34826585/hashcode-changes-each-time-the-object-is-created
 */
public class OverrideDemo {

    private long timestamp;
    private int damage;
    private SquareType squareType;


    public OverrideDemo(int damage, SquareType squareType) {
        this(damage, squareType, new Date().getTime());
    }

    public OverrideDemo(int damage, SquareType squareType, long timestamp) {
        if (squareType == null) throw new IllegalArgumentException("square type cannot be null");
        this.timestamp = timestamp;
        this.damage = damage;
        this.squareType = squareType;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public int getDamage() {
        return damage;
    }

    public SquareType getSquareType() {
        return squareType;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) { return true; }
        if (o == null || getClass() != o.getClass()) { return false; }

        OverrideDemo that = (OverrideDemo) o;

        if (damage != that.damage) { return false; }
        return squareType == that.squareType;

    }

    @Override
    public int hashCode() {
        int result = damage;
        result = 31 * result + squareType.hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "OverrideDemo{" +
                "timestamp=" + timestamp +
                ", damage=" + damage +
                ", squareType=" + squareType +
                '}';
    }
}

enum SquareType { FIRE, WIND, WATER, EARTH }
下面是一个Junit测试,它显示了这些方法的行为。所有测试均通过;我认为这个实现是正确的

package cruft;

import org.junit.Assert;
import org.junit.Test;

/**
 * Junit test demonstrates testing equals and hashcode contract
 * Created by Michael
 * Creation date 1/16/2016.
 * @link https://stackoverflow.com/questions/34826585/hashcode-changes-each-time-the-object-is-created
 */
public class OverrideDemoTest {

    @Test
    public void testEquals_Null() {
        OverrideDemo x = new OverrideDemo(5, SquareType.EARTH);
        Assert.assertFalse(x.equals(null));
    }

    @Test
    public void testEquals_Reflexive() {
        OverrideDemo x = new OverrideDemo(5, SquareType.EARTH);
        Assert.assertTrue(x.equals(x));
    }

    @Test
    public void testEquals_Symmetric() {
        OverrideDemo x = new OverrideDemo(5, SquareType.EARTH);
        OverrideDemo y = new OverrideDemo(5, SquareType.EARTH);
        Assert.assertTrue(x.equals(y));
        Assert.assertTrue(y.equals(x));
        Assert.assertTrue(x.hashCode() == y.hashCode());
    }

    @Test
    public void testEquals_Transitive() {
        OverrideDemo x = new OverrideDemo(5, SquareType.EARTH);
        OverrideDemo y = new OverrideDemo(5, SquareType.EARTH);
        OverrideDemo z = new OverrideDemo(5, SquareType.EARTH);
        Assert.assertTrue(x.equals(y));
        Assert.assertTrue(y.equals(z));
        Assert.assertTrue(z.equals(x));
        Assert.assertTrue(x.hashCode() == y.hashCode());
        Assert.assertTrue(y.hashCode() == z.hashCode());
        Assert.assertTrue(z.hashCode() == x.hashCode());
    }

    @Test
    public void testEquals_DifferentDamage_NotEqual() {
        OverrideDemo x = new OverrideDemo(5, SquareType.EARTH);
        OverrideDemo y = new OverrideDemo(10, SquareType.EARTH);
        Assert.assertFalse(x.equals(y));
        Assert.assertFalse(y.equals(x));
        Assert.assertFalse(x.hashCode() == y.hashCode());
    }

    @Test
    public void testEquals_DifferentSquareType_NotEqual() {
        OverrideDemo x = new OverrideDemo(10, SquareType.EARTH);
        OverrideDemo y = new OverrideDemo(10, SquareType.FIRE);
        Assert.assertFalse(x.equals(y));
        Assert.assertFalse(y.equals(x));
        Assert.assertFalse(x.hashCode() == y.hashCode());
    }
}

你能发布
SquareType
吗?它可能不会覆盖hashCode。SquareType的hashCode是如何计算的?您可以发布一个完整的代码来演示这个问题吗?为什么不按照Tunaki的要求发布演示代码呢?也许您正在做一些愚蠢的事情,比如创建带有损坏和时间戳参数changedJust的效果对象,以确保:在toString方法中,print还返回损坏和方形类型,以确保对象与预期的相等