繁体   English   中英

HashMap.values()/ HashMap.keySet()何时按引用返回,何时按值返回?

[英]When Does HashMap.values()/HashMap.keySet() Return By Reference And When Does It Return By Value?

以下代码指示值正在通过引用返回:

public class Playground {

    public static void main(String[] args) {
        Map<Integer, vinfo> map = new HashMap<Integer, vinfo>(); 
        map.put(1, new vinfo(true));
        map.put(2, new vinfo(true));
        map.put(3, new vinfo(true));


        for(vinfo v : map.values()){
            v.state = false;
        }

        printMap(map);
    }

    public static void printMap(Map m){
        Iterator it = m.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry pairs = (Map.Entry) it.next();
            Integer n = (Integer) pairs.getKey();
            vinfo v = (vinfo) pairs.getValue();
            System.out.println(n + "=" + v.state);
        }
    }
}

class vinfo{
    boolean state;

    public vinfo(boolean state){
        this.state = state;
    }
}

输出:
1 =伪
2 =假
3 =假

在下面的代码中,它们是按值返回的。 然而; 我正在使用Integer对象。

public class Playground {

    public static void main(String[] args) {
        Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 
        map.put(1, 1);
        map.put(2, 1);
        map.put(3, 1);


        for(Integer n : map.values()){
            n+=1;
        }

        printMap(map);
    }

    public static void printMap(Map m){
        Iterator it = m.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry pairs = (Map.Entry) it.next();
            Integer n = (Integer) pairs.getKey();
            Integer n2 = (Integer) pairs.getValue();
            System.out.println(n + "=" + n2);
        }
    }
}

输出:
1 = 1
2 = 1
3 = 1

我怎么知道我何时直接更改值(或与此相关的键),或者我必须执行完整的.remove()和.put()。

整数是不可变的。 一旦构造了整数的特定实例,就无法更改其值。 但是,您可以将Integer变量设置为等于Integer的其他实例(除非将该变量声明为final)。 您的分配(+ =)正在构造一个新的Integer对象,并将您的变量n设置为引用它。

您的类vinfo不是不可变的,因此其行为符合您的预期。

简而言之,java对象具有一些非常特殊的属性。

通常,java具有直接通过值传递的原始类型(int,bool,char,double等)。 然后,java具有对象(所有从java.lang.Object派生的对象)。 实际上,对象总是通过引用(引用是您无法触摸的指针)来处理的。 这意味着实际上,对象是通过值传递的,因为引用通常并不有趣。 但是,这确实意味着您无法更改指向哪个对象,因为引用本身是通过值传递的。

为了简化您的问题,请参见以下代码

@Test
public void testIntegerValue() {
    Integer num = new Integer(1);
    setInteger(num);
    System.out.println(num); // still return one, why? because Integer will convert to 
                            // int internally and int is primitive in Java, so it's pass by value

}

public void setInteger(Integer i) {
    i +=1;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM