覆盖方法参数对象行为

时间:2017-11-06 14:55:12

标签: java

public void method (AmazingObject obj) {

    HashMap<Integer, AmazingObject> hashmap = new HashMap<>();

    for (int i = 0; i < 5; i++) {
        obj = new AmazingObject();
        hashmap.put(i, obj);
    }

    for (int i = 0; i < 5; i++) {
        System.out.println(hashmap.get(i).toString());
    } 

}

我编写了这段代码,看到数组包含每个元素完全不同的对象。如果我理解这一点:

1)该方法接受一个AmazingObject实例的reference copy

2)我使用reference type关键字为new分配了一个新地址。

3)包含我的新地址的另一个reference copy被抛入Hashmap。

因此,以前的值都不会被覆盖。这种行为的原因是Java是否经过reference copy并且没有通过reference?我希望数组中的每个元素都指向末尾的完全相同的对象(即最后分配的对象)。

3 个答案:

答案 0 :(得分:1)

如果我理解正确,您会期望以下代码:

HashMap<Integer, MyObject> hashmap ...    // Line 0
MyObject foo = new MyObject();            // Line 1
hashmap.put(1, foo);                      // Line 2
foo = new MyObject();                     // Line 3
hashmap.put(2, foo);                      // Line 4

将导致两个值相同的散列图。

让我们一步一步看看这个例子:

  1. Line 1之后
    • 堆栈有2个条目/指针(hashmap,foo),它们指向
    • 中的内存对象
    • (1 HashMap和1 MyObject个实例。)
  2. Line 2之后
    • 堆栈不变。
    • HashMap内存对象现在包含一个将1映射到指向MyObject
    • 实例的指针的条目
  3. Line 3之后
    • 堆栈指针 foo 现在指向堆上的不同内存位置(新创建的MyObject实例)
    • 现在拥有HashMap的<{1}}和两个实例
  4. MyObject之后
    • 堆栈不变。
    • Line 4内存对象现在包含2个条目(HashMap - &gt;指向第一个1实例| MyObject的指针 - &gt ;指向第二个2实例的指针)
  5. 我希望你理解我的意思但重要的是:变量/参数对象本身。它只是一个容器,它包含一个指向内存位置的指针。

    因此,如果您将该指针指向其他任何人的内存位置(在您的情况下为HashMap),那么其他位置将不知道该变量是否稍后更改!

答案 1 :(得分:0)

您可以在所有选项中使用相同的引用,但不能使用new关键字,而是:

for (int i = 0; i < 5; i++) {
    obj = new AmazingObject();
    hashmap.put(i, obj);
}

执行:

obj = new AmazingObject();
for (int i = 0; i < 5; i++) {
    hashmap.put(i, obj);
}

答案 2 :(得分:-1)

输入参数是无关紧要的,因为你在第一个for循环中不断重新分配它,所以是的,你最终得到了5个存储在地图中的新对象。这就是为什么我总是将输入参数设为最终的一个原因 - 它会阻止它们的重新分配,这会引起混淆,就像这个例子一样