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

发布于 2024-11-28 15:14:27 字数 1159 浏览 1 评论 0原文

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

In this piece of code i pass a name into a method that modifies the String literal name but not the object itself, when the code exits the method, the object (as identified by the hashcode) is the same, however not the name that is modified in the method.

How should i explain this?

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;
    }
}

Run results:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

久光 2024-12-05 15:14:27

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

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

在您的代码中,您正在创建一个单个 Bus 对象。将其视为现实生活中的公共汽车。它上面画有一个名字,上面刻有一个序列号(后者是哈希码)。当您调用该方法时,这会告诉该方法如何获取Bus对象 - 它不会创建一个新的Bus。该方法会用一个新名称覆盖名称,但这对序列号没有任何作用,序列号与以前相同。

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

You haven't overridden hashCode - therefore it will use the implementation in java.lang.Object, which doesn't vary over the course of an object's lifetime. You haven't overridden equals either... which means that a.equals(b) will only return true for Bus a and Bus b if a and b refer to the exact same object - rather than objects with equal name.

Note that the names in your code suggest that Java uses pass by reference. It doesn't - it always uses pass by value, but those values are always either primitives or references - never actual objects. The same is true for simple assignment etc.

In your code, you're creating a single Bus object. Think of it as a real life bus. It has a name painted on it, and a serial number embossed on it (the latter being the hash code). When you call the method, that's telling the method how to get to the Bus object - it's not creating a new Bus. The method comes and paints over the name with a new one, but that does nothing to the serial number, which is the same as it ever was.

Also note that name is not a string literal - it's a string variable. Its initial value comes from a string literal, but changing the value later does nothing to the original string object.

笑看君怀她人 2024-12-05 15:14:27

如果您希望哈希码依赖于变量(即 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 类。

If you want the hashcode to depend on a variable (i.e. name) then you'll need to override the hashCode method. A simple example:

public class Bus {
    private String name;

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

The hashCode implementation in java.lang.Object does not use any kind of reflection to look up variables, so you almost always need to override hashCode.

Note that you should always override equals if you override hashCode and vice versa.

There are a bunch of useful tools for helping you implement hashCode. Check out Apache Commons lang and take a look at their HashCodeBuilder class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文