方法中修改了对象内容,但对象哈希码保持不变
在这段代码中,我将一个名称传递给一个方法,该方法修改字符串文字 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您尚未覆盖
hashCode
- 因此它将使用java.lang.Object
中的实现,该实现在过程中不会发生变化一个对象的生命周期。您也没有重写equals
...这意味着a.equals(b)
只会为Bus a 返回
和true
Bus b
如果a
和b
引用完全相同的对象 - 而不是具有相同名称的对象。请注意,代码中的名称表明 Java 使用引用传递。它不是 - 它总是使用按值传递,但这些值始终是基元或引用 - 从来不是实际对象。对于简单的赋值等也是如此。
在您的代码中,您正在创建一个单个
Bus
对象。将其视为现实生活中的公共汽车。它上面画有一个名字,上面刻有一个序列号(后者是哈希码)。当您调用该方法时,这会告诉该方法如何获取到Bus
对象 - 它不会创建一个新的Bus
。该方法会用一个新名称覆盖名称,但这对序列号没有任何作用,序列号与以前相同。另请注意,
name
不是字符串文字 - 它是字符串变量。它的初始值来自字符串文字,但稍后更改该值对原始字符串对象没有任何影响。You haven't overridden
hashCode
- therefore it will use the implementation injava.lang.Object
, which doesn't vary over the course of an object's lifetime. You haven't overriddenequals
either... which means thata.equals(b)
will only returntrue
forBus a
andBus b
ifa
andb
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 theBus
object - it's not creating a newBus
. 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.如果您希望哈希码依赖于变量(即
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 thehashCode
method. A simple example:The
hashCode
implementation injava.lang.Object
does not use any kind of reflection to look up variables, so you almost always need to overridehashCode
.Note that you should always override
equals
if you overridehashCode
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 theirHashCodeBuilder
class.