在方法中修改的对象内容但对象哈希码保持不变

时间:2011-08-08 16:26:49

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

在这段代码中,我将一个名称传递给修改字符串文字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

2 个答案:

答案 0 :(得分:6)

您尚未覆盖hashCode - 因此它将使用java.lang.Object中的实现,在对象的生命周期中不会变化。您尚未覆盖equals ...这意味着a.equals(b)只返回true Bus aBus b a {} {1}}引用完全相同的对象 - 而不是具有相同名称的对象。

请注意,代码中的名称表明Java使用pass by reference。它没有 - 它总是使用pass by value,但这些值总是基元或引用 - 从不是实际的对象。对于简单的任务等也是如此。

在您的代码中,您正在创建单个 b对象。把它想象成一辆真正的公共汽车。它上面有一个名字,上面印有一个序列号(后者是哈希码)。当你调用方法时,它告诉方法如何获取Bus对象 - 它不会创建新的Bus。该方法使用一个新方法绘制名称,但这对序列号没有任何作用,这与以前一样。

另请注意,Bus不是字符串文字 - 它是字符串变量。它的初始值来自字符串文字,但稍后更改值对原始字符串对象没有任何作用。

答案 1 :(得分:1)

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

public class Bus {
    private String name;

    public int hashCode() {
        return name.hashCode();
    }
}

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

请注意,如果您覆盖equals总是覆盖hashCode,反之亦然。

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