为什么参考会自动更新?

时间:2013-07-04 18:53:53

标签: java map hashmap comparator treemap

我有这个代码。它应该按整数值排序地图。

public class Main {

    public static void main(String[] args) {

        HashMap<String,Integer> map = new HashMap<>();
        ValueComparator bvc =  new ValueComparator(map);
        TreeMap<String,Integer> sorted_map = new TreeMap<>(bvc);

        map.put("A",5);
        map.put("B",4);
        map.put("C",4);
        map.put("D",2);

        System.out.println("unsorted map: "+map);

        sorted_map.putAll(map);

        System.out.println("results: "+sorted_map);


    }
}

class ValueComparator implements Comparator<String> {

    Map<String, Integer> base;
    public ValueComparator(Map<String, Integer> base) {
        this.base = base;
        System.out.println("Map: " + base);
    }

    public int compare(String a, String b) {
        if (base.get(a) >= base.get(b)) {
            return -1;
        } else {
            return 1;
        }
    }
}

它工作正常。 但首先作为ValueComparator实例的参数,我给构造函数一个空的hashmap。此空地图保存在 base 中。然后我用比较器创建树图。然后我将这些东西放在地图中,它会自动更新ValueComparator中名为 base 的引用。为什么地图会自动传递给ValueComparator更新?实际上 base 变量应该仍然是一个空映射。不是吗?

4 个答案:

答案 0 :(得分:2)

在java中,所有变量都是按值传递的(引用的副本),因此您将有2个引用相同对象的变量。所以当你改变那个对象时,它会反映在另一个对象中。

例如:

public class Test{

public static void main(String args []){
   Test test = new Test();
   Collection<String> collection = new LinkedList<>();
   collection.add("a");
   collection.add("b");
   someMethod(collection);
   System.out.println(collection); // will print [a,b];
   modifyCollection(collection);
   System.out.println(collection); // will print [a,b,c];
}

public void modifyCollection(Collection collection){
    collection.add("c");
}

public void someMethod(Collection collection){
    collection = new ArrayList();
    collection.add("nasda");
}

}

答案 1 :(得分:0)

在Java中,对类的引用是按值传递的。因此,当您将空HashMap传递给ValueComparator时,您实际上是在bvc中存储对它的引用。然后,当您修改HashMapbvc.base作为对它的引用时,会“自动更新”。

编辑:考虑到Jon Skeet的回复。

答案 2 :(得分:0)

  

为什么地图会自动传递给ValueComparator?

object变量传递给方法时,会传递reference variable的副本。因此,调用者和被调用的方法现在都具有相同的引用副本,因此它们将在堆上引用相同的精确object。这就是为什么另一个变量可以看到一个变量对对象所做的更改 这就是为什么map会在ValueComparator中放入内容时自动更新map

答案 3 :(得分:0)

实际上,基本变量应该仍然是空地图。不是吗?

不,您拨打ValueComparator bvc = new ValueComparator(map);

的那一刻

由于this.base = base;

,地图和底图都指的是同一个对象

以上证明为什么“然后我把这些东西放在地图中并自动更新名为base的ValueComparator中的引用”。