如何在Java11中设置HashMapFinal的键值对?

如何在Java11中设置HashMapFinal的键值对?,java,hashmap,final,java-11,Java,Hashmap,Final,Java 11,问题1: 如果我将exits声明为private final Map exits,它为什么不起作用? 问题2: 还有其他方法可以达到同样的效果吗? P:我是java新手,所以如果我可能会混淆C++概念和java java,那么请纠正我。 < P>答案1: map < /Cord>不是Java中的有效语法。我不知道你这是什么意思。这个用法使我想起C++中的代码> const < /Cord>修饰符,但最终不是const,无论如何,字符串和整数都是不可变的 回答2:您的getExits方法返回地图的

问题1:
如果我将
exits
声明为
private final Map exits,它为什么不起作用
问题2:
还有其他方法可以达到同样的效果吗?

P:我是java新手,所以如果我可能会混淆C++概念和java java,那么请纠正我。

< P>答案1:<代码> map < /Cord>不是Java中的有效语法。我不知道你这是什么意思。这个用法使我想起C++中的代码> const < /Cord>修饰符,但最终不是const,无论如何,字符串和整数都是不可变的

回答2:您的
getExits
方法返回地图的可修改副本。这是可行的,但更常见的是返回数据结构的不可修改视图。它是一个轻量级修饰符,如果调用方试图进行更改,但调用原始映射中的方法,则会引发异常。如果调用方需要映射,则必须复制映射本身

import java.util.HashMap;
import java.util.Map;

public class Foo {
    private final Map<String, Integer> exits;

    public Foo(Map<String, Integer> exits) {
        this.exits = exits;
    }

    public Map<String, Integer> getExits() {
        return new HashMap<>(exits);
    }

    public void show() {
        for (String i : exits.keySet()) {
            System.out.println(i + ": " + exits.get(i));
        }
    }
}

class Bar {
    public static void main(String[] args) {
        Map<String, Integer> temp=new HashMap<>();
        temp.put("A", 1);
        temp.put("B", 2);
        Foo foo = new Foo(temp);

        foo.show();
        //Okay, no problem.
        //Output: A: 1
        //        B: 2
        foo.getExits().replace("A", 10);
        foo.getExits().remove("B");
        foo.show();
        //Output: A: 1
        //        B: 2
    }
}
publicmap getExits(){
返回集合。不可修改映射(退出);
}
第一个问题: 实际上,在第二段代码中,当您每次调用getexits时,它都会返回一个不同的浅层副本(新Hashmap)。浅层副本是出口的不同副本,您只能修改返回的映射,而不能修改在foo类中声明的原始映射。因此,foo.getexits()是您返回的完全不同的映射,它每次都在修改新的hashmap,而不是临时映射或foo(temp)。如果您这样编码

public Map<String, Integer> getExits() {
    return Collections.unmodifiableMap(exits);
}
而不是

    temp.replace("A",10);
    temp.remove("B");
    foo.show(); 
然后它将打印与第一个程序相同的输出。(它还将修改)。 很快,您的第二个代码不会被修改,因为每次您返回和修改一个与temp无关的新hashmap时,这些都不会影响您的foo(temp)

第二个问题: 如果确实不想修改main类中的任何内容,则可以在第二个程序的getexits()方法中编写如下代码:

    foo.getExits().replace("A", 10);
    foo.getExits().remove("B");
    foo.show();
不要像你那样改变第二个程序的任何内容,它会抛出

  return Collections.unmodifiableMap(exits);

每当你想用foo.getexits()修改并阻止你修改它时。但是你仍然可以单独修改temp,因为它与getexits方法没有关系。我和你一样也是初学者,但我试着用我的小知识回答你的问题。希望,这会有帮助

你想要
集合.unmodifiableMap()
或者像Guava的
ImmutableMap
@chrylis onstrike这样的不可变版本-你能更详细地向我解释一下吗?阅读关于集合.unmodifiableMap.Final的内容。Final只会使引用成为Final,所以你不能将它指向新的地图。它与使数据不可变的c的常量不同。通过创建一个类不公开的重复映射,您可能能够实现您所追求的目标。当调用getExits时,返回一个不可修改的映射(它只是现有映射的一个视图)。编辑:如您的额外示例。或Java12的
Map.copyOf()
  return Collections.unmodifiableMap(exits);
 java.lang.UnsupportedOperationException