【问题标题】:Object contents modified in method but object hashcode remains the same方法中修改了对象内容,但对象哈希码保持不变
【发布时间】:2011-10-22 13:12:32
【问题描述】:

在这段代码中,我将名称传递给修改字符串文字name 但不修改对象本身的方法,当代码退出方法时,对象(由哈希码标识)是相同的,但是不是方法中修改的name

我该如何解释?

public class ObjectContentsPassByReferenceApp {
    private static void modifyObject(Bus bus) {
        bus.setName("SBS Transit");
    }

    public static void main(String args[]) {
        Bus bus;

        bus = new Bus();
        bus.setName("Trans Island Bus");

        System.out.println("Bus initially set to (hashcode): " + bus);
        System.out.println("Bus name: " + bus.getName());

        modifyObject(bus);

        System.out.println("After calling modifyObject (hashcode): " + bus);
        System.out.println("Bus name: " + bus.getName());
    }
}

class Bus {
    private String name;

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

运行结果:

Bus initially set to (hashcode): sg.java.concepts.passByReference.Bus@8d2ed0
Bus name: Trans Island Bus
After calling modifyObject (hashcode): sg.java.concepts.passByReference.Bus@8d2ed0
Bus name: SBS Transit

【问题讨论】:

    标签: java pass-by-reference pass-by-value


    【解决方案1】:

    您尚未覆盖hashCode - 因此它将使用java.lang.Object 中的实现,不会在对象的生命周期中发生变化。你也没有覆盖equals...这意味着a.equals(b) 只会返回trueBus aBus b 如果ab 指的是完全相同的对象 - 而不是对象同名。

    请注意,代码中的名称表明 Java 使用按引用传递。它没有——它总是使用按值传递,但这些值总是原始或引用——从不是实际的对象。简单赋值等也是如此。

    在您的代码中,您正在创建一个单个 Bus 对象。把它想象成一辆现实生活中的巴士。它上面画着一个名字,上面印有一个序列号(后者是哈希码)。当您调用该方法时,它告诉该方法如何获取Bus 对象- 它不是创建一个新的Bus。方法来了,并用新的名称覆盖了名称,但这对序列号没有任何影响,与以往一样。

    还要注意name 不是字符串文字 - 它是字符串变量。它的初始值来自一个字符串字面量,但稍后更改该值对原始字符串对象没有任何作用。

    【讨论】:

    • 嗨 Jon,这与 String 的“可变性”有什么关系吗?
    • @Chin:哪个位?哈希码保持不变?绝对不。您尚未覆盖 hashCode 方法,因此无论您做什么,它在对象的整个生命周期内保持不变。将 String 更改为其可变表亲 StringBuilder 根本不会影响这一点。
    【解决方案2】:

    如果您希望哈希码依赖于变量(即name),那么您需要覆盖hashCode 方法。一个简单的例子:

    public class Bus {
        private String name;
    
        public int hashCode() {
            return name.hashCode();
        }
    }
    

    java.lang.Object 中的hashCode 实现不使用任何类型的反射来查找变量,因此您几乎总是需要覆盖hashCode

    请注意,如果您覆盖 hashCode,则应始终覆盖 equals,反之亦然。

    有很多有用的工具可以帮助您实现hashCode。查看Apache Commons lang 并查看他们的HashCodeBuilder 课程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-25
      • 1970-01-01
      • 1970-01-01
      • 2019-04-02
      • 2015-01-06
      • 1970-01-01
      • 2012-08-02
      • 2018-08-25
      相关资源
      最近更新 更多