为什么Java的HashMap对不同的对象有不同的行为?

时间:2011-03-13 22:33:27

标签: java reference hashmap

我有使用HashMap和泛型的以下Java代码:

import java.util.*;
import java.io.*;

public class Map{
    static HashMap<Integer, Integer> imap;
    static HashMap<Integer, Thing> tmap;

    public static void main(String[] args){

        imap = new HashMap<Integer, Integer>();
        imap.put(0,0);
        Integer i = imap.get(0);
        i = i + 1;
        System.out.println(imap.get(0));

        tmap = new HashMap<Integer, Thing>();
        tmap.put(0,new Thing(0));
        Thing t = tmap.get(0);
        t.a = t.a + 1;
        System.out.println(tmap.get(0).a);
    }
}

class Thing{
    public int a;
    public Thing(int n){
        this.a = n;
    }
}

打印出以下内容:

0
1

我希望它能打印两个(如果我正在修改引用)或两个零(如果我正在修改值)。那么为什么地图从整数到整数的行为不同于从整数到事物?

5 个答案:

答案 0 :(得分:5)

Java的整数类型不可变,因此您的第一个示例从地图中获取值,然后使用新值替换局部变量。但是,第二个示例从地图中获取对Thing实例的引用。

答案 1 :(得分:1)

通过执行i = i + 1,您不会增加存储在地图中包含的java.lang.Integer中的值。

答案 2 :(得分:0)

我认为i = i + 1;将不会更新对象,因为在分配到基元时,get将是按值复制的。因此,原始更新不会反映在地图中,因为您没有引用。使用Thing中的下一个示例,您将直接分配回Thing的公共原语,因此再次按值 - 但您更新public int。

答案 3 :(得分:0)

这是因为当您从第一个映射中获取Integer值时(通过将Integer指定给int),您将自动取消装箱整数值。那时你没有使用整数引用,你使用的是一个int原语,与地图中保存的整数引用无关。

由于java Integers是不可变的,所以你真的没办法在这里尝试演示。无法修改地图中整数引用所持有的内部原语int。你必须输出一个新的Integer来改变key 0所持的值。

答案 4 :(得分:0)

回答问题的第二部分(“但那为什么它会在第二个印刷声明中打印1?”),这是因为线条......

Thing t = tmap.get(0);
t.a = t.a + 1;

...获取对位于给定位置的hashmap内的对象的引用,然后修改引用对象的成员变量 。然后,println语句使用now-modified成员变量检索对该同一对象的另一个引用。