Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用“不可变”;val";在Scala中从Java导入_Java_Scala - Fatal编程技术网

使用“不可变”;val";在Scala中从Java导入

使用“不可变”;val";在Scala中从Java导入,java,scala,Java,Scala,我在Scala中使用以下示例来说明我的困惑: import java.util.HashMap val jhm = new HashMap[String, Int] jhm.put("myId", 1) jhm.put("yourId", 2) 它允许添加到“jhm”中 现在,如果我在Scala中执行此操作: val nmap = Map() nmap += ("myId" -> 1) 它不允许出现预期的情况。我的问题:为什么它允许在第一种情况下更改不可变的“val”?val创建一个不

我在Scala中使用以下示例来说明我的困惑:

import java.util.HashMap
val jhm = new HashMap[String, Int]
jhm.put("myId", 1)
jhm.put("yourId", 2)
它允许添加到“jhm”中

现在,如果我在Scala中执行此操作:

val nmap = Map()
nmap += ("myId" -> 1)

它不允许出现预期的情况。我的问题:为什么它允许在第一种情况下更改不可变的“val”?

val创建一个不可变的引用,这意味着这个val将始终指向同一个对象。它不能保证对象本身不会改变它自己的状态。

HashMap上的put()会改变映射,并且不会返回新的引用。在第二种情况下,您将向不可变映射添加一个值,因此将返回一个新映射。Java示例的Scala等价物是:

import collection.mutable.Map

val nmap = Map()[String, Int]
nmap += ("a" -> 1)

您正在混合两种不同的不变性“用法”

您可以对某个对象进行可变(var)或不可变(val)引用,并且该对象本身可以是可变的或不可变的

例:

问题是当“某物”时,引用“具有内部状态”。像
Int
String
这样的基本类型没有这个问题,但任何类都可能有这个问题。scala集合对于新的scala程序员来说是一个常见的难题,因为存在和

不同之处在于,对不可变集合的任何操作都会返回一个新集合,但原始集合保持不变,而在可变集合中,集合本身会被修改

在您的例子中,您使用的scala
Map
是一个不可变的映射,它不包含这样的方法。您可以执行
myMap++(键->值)
并获得一个新地图

当您将引用中的可变性与对象中的可变性/状态混合在一起时,会出现更大的混乱。你应该自己玩一些东西,比如:

val x1 = scala.collection.mutable.ListBuffer(1,2,3) // immutable reference to mutable object

// please, never use this in real code
var x2 = scala.collection.mutable.ListBuffer(1,2,3) // mutable reference to mutable object

// please, try to use this as much as possible
val x3 = scala.collection.immutable.List(1,2,3) // immutable reference to immutable object 

var x4 = scala.collection.immutable.List(1,2,3) // mutable reference to immutable object

如果您有任何疑问,请告诉我/我们,以便我们能够提供帮助

管理摘要

您没有在等效类上调用等效方法。使用
mutable.Map
并将
+=
替换为
put(…)
,两者都将执行相同的操作

详细答案

这里有两种截然不同的操作。第一个是向映射添加元素。java映射上的方法
put(…)
相当于scala中的
put(…)
操作,not
+
,它创建了一个新的
映射。编译器完全可以执行以下操作:

val map = Map[Int, Int]()
map: scala.collection.mutable.Map[Int,Int] = Map()

map.put(1, 2)
res0: Option[Int] = None

map
res1: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2)
通过将属性放入键值对,
map
改变其状态。这不会导致您的错误。但是,您没有调用
put(…)
方法,而是调用
+=
。这基本上意味着两种操作:

  • 调用
    +
    方法
  • 将结果赋给变量
  • 与之相反,
    put(…)
    ()
    +
    ()不会更改映射,而是创建一个类似于
    immutable.map
    的新映射。 创建新映射后,尝试将其重新分配给
    val
    ,这会引发编译器错误

    在java中也可以看到同样的行为:

    final int answer = 42;
    answer = 23;
    

    这将导致编译器错误
    java:cannot assign value to final variable answer

    put只是在添加值,而不是在第二个实例中创建不可变映射时更改jhm的引用,然后说put并更改nmap的实例。但是,当它是Java类的对象,而当它是纯Scala类型时,则不允许更改。@NKM val并不意味着对象本身不能更改。它只是意味着引用不能更改。使用Java HashMap,您可以改变一个可变对象,但是对它的引用仍然指向同一个对象。对于Scala不可变映射,添加键值对将返回一个新映射,因此引用将更改。@NKM:val
    val
    不会更改。被
    val
    引用的对象确实存在。我知道了。谢谢你的详细解释。
    final int answer = 42;
    answer = 23;