代码之家  ›  专栏  ›  技术社区  ›  Navin Gelot

Scala case类使用浅拷贝还是深拷贝?

  •  6
  • Navin Gelot  · 技术社区  · 6 年前
    case class Person(var firstname: String, lastname: String)
    
    val p1 = Person("amit", "shah")
    val p2 = p1.copy()
    p1.firstname = "raghu"
    p1
    p2
    
    p1 == p2
    

    case类使用浅拷贝

    但这个例子的输出我无法破解

    我已经从p1创建了一个副本作为p2人,然后我就改变了

    因此,在浅层复制的情况下,它应该更改p2.firstname的值 但这不是在这里发生的

    参考文献: https://docs.scala-lang.org/tour/case-classes.html

    2 回复  |  直到 6 年前
        1
  •  13
  •   sarveshseri    6 年前

    你的困惑在于 variables values .

    val p1 = Person("amit", "shah")
    val p2 = p1.copy()
    

    那么 p2 是一个肤浅的 p1 ,所以 变量 p1.firstname p2.firstname value String "amit"

    当你在做 p1.firstname = "raghu" ,你实际上是在告诉我 指向另一个 字符串 类型是 "raghu" . 在这里,您不是在更改值本身,而是在更改 variable

    如果你换成 本身,然后两者 第1页 第2页 值在Scala中是不可变的,因此不能修改

    让我用一些可以修改的,比如 ArrayBuffer .

    scala> import scala.collection.mutable.ArrayBuffer
    // import scala.collection.mutable.ArrayBuffer
    
    scala> case class A(s: String, l: ArrayBuffer[Int])
    // defined class A
    
    scala> val a1 = A("well", ArrayBuffer(1, 2, 3, 4))
    // a1: A = A(well,ArrayBuffer(1, 2, 3, 4))
    
    scala> val a2 = a1.copy()
    // a2: A = A(well,ArrayBuffer(1, 2, 3, 4))
    
    // Lets modify the `value` pointed by `a1.l` by removing the element at index 1
    scala> a1.l.remove(1)
    // res0: Int = 2
    
    // You will see the impact in both a1 and a2.
    
    scala> a1
    // res1: A = A(well,ArrayBuffer(1, 3, 4))
    
    scala> a2
    //res2: A = A(well,ArrayBuffer(1, 3, 4))
    
        2
  •  11
  •   Ryan Leach    6 年前

    您可以将字符串变量的值想象为对存储在某个值存储中的字符串的引用。 enter image description here

    但是,由于JVM将字符串引用视为值,因此在分配firstname时,它现在指向“raghu”

    如果我们把这个字符串包装到另一个类中,我们就调用它 case class Box(var s:String)

    然后JVM(以及scala)将使用对橙色“box”的引用,而不是字符串。

    val p1 = Person(Box("amit"), Box("shah"))
    val p2 = p1.copy()
    p1.firstname = Box("raghu")
    

    浅的 收到。

    所有的参考文献都是副本,现在指向方框,橙色。

    enter image description here

    如果有某种理论上的“深度复制”方法。 enter image description here


    字符串在JVM上很奇怪。它们的行为类似于值,有时是单例值,它们的引用相等性(在java中)因此而混乱,但这是一个实现细节,对java和Scala都是隐藏的。所以我们可以把字符串当作值(看见 What is Java String interning? 更多信息,但目前可能太高级)和Scala线程: https://www.scala-lang.org/old/node/10049.html