在这段代码中,我将一个名称传递给修改字符串文字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
答案 0 :(得分:6)
您尚未覆盖hashCode
- 因此它将使用java.lang.Object
中的实现,在对象的生命周期中不会变化。您尚未覆盖equals
...这意味着a.equals(b)
只返回true
Bus a
和Bus 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
课程。