Kotlin是"按值传递"还是"按参考传递"?

Rah*_*ana 35 kotlin

据我所知,Java是这篇文章的传值.我来自Java背景我想知道Kotlin用于传递两者之间的值.像在扩展方法等.

Pel*_*cho 28

每当我听到"传递价值"与"传递参考"Java辩论时,我总是这么认为.我给出的答案:"Java传递引用的副本(按值传递)"(传递引用).所以每个人都很开心.我会说Kotlin和基于JVM的一样

  • 好吧,我会成为那个人,因为必须有人:Java 传递基元的实际值,而不是引用。更好的理解方法是它传递值,对于对象来说,值是一个引用。 (27认同)
  • 我不是在争论。Java 在其规范中将自身定义为按值传递:https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.1 但是不,我不会这样做争论。通过*引用传递与传递*a*引用不同。在按值传递中,如果传入引用,您将获得引用的值。在按引用传递中,如果传入引用,您将获得对引用的引用。后者在 Java 中没有很好的模拟,这可能是混乱的根源。 (3认同)
  • @BobLiberatore 你用两句话完美地概括了它 (3认同)

has*_*sen 20

语义与Java相同.

在Java中,当您拥有对象的实例并将其传递给方法时,该方法可以更改该对象的状态,并且在该方法完成后,更改将应用​​于调用站点上的对象.

这同样适用于Kotlin.


Ami*_*lan 16

对于除数组之外的所有基本类型,都会传递值。对于其余部分,传递对该对象的引用。

注意:基本类型通俗地称为“基元”,尽管它们实际上是 Kotlin 中的对象。

我将用两个例子来解释:

代码:

fun main() {
    var a = 5
    var b = a
    a = 6
    println("b = $b")
}
Run Code Online (Sandbox Code Playgroud)

印刷:b = 5aKotlin 传递to的值,b因为a它是“原语”。所以a事后改变不会有影响b

代码:

fun main() {
    var a = Dog(5)
    var b = a
    a.value = 6
    println("b = ${b.value}")
}
    
class Dog (var value: Int)
Run Code Online (Sandbox Code Playgroud)

打印,b = 6因为这次a不是“原始”,因此传递的是对对象(Dog)的引用b而不是其值。因此,更改a会影响指向它的所有对象。

总之,数字(字节、短整型、整数、长整型)、布尔值、字符和字符串都是按值传递。其余的都是通过引用传递。


s1m*_*nw1 11

它使用与Java相同的原理。它始终是按值传递的,您可以想象传递了一个副本。对于原始类型,例如,Int这很明显,此类参数的值将被传递到函数中,并且外部变量将不会被修改。请注意,由于Kotlin中的参数的行为类似于vals,因此无法重新分配:

fun takeInt(a: Int) {
    a = 5
}
Run Code Online (Sandbox Code Playgroud)

该代码将无法编译,因为a无法重新分配。

对于对象来说,这有点困难,但它也是按值调用的。如果使用对象调用函数,则其引用的副本将传递给该函数:

data class SomeObj(var x: Int = 0)

fun takeObject(o: SomeObj) {
    o.x = 1
}

fun main(args: Array<String>) {
    val obj = SomeObj()
    takeObject(obj)
    println("obj after call: $obj") // SomeObj(x=1)
}
Run Code Online (Sandbox Code Playgroud)

您可以使用传递给函数的引用来更改实际对象。这将影响您传入的参数。但是,引用本身(即变量的值)将永远不会通过函数调用进行更改。


小智 5

在Java原语类型(如int,float,double,boolean)中,它们按值传递给方法,如果您在接收器方法中对其进行修改,则它们不会更改为调用方法。但是,如果属性/变量类型不是基元,则像基元数组或其他类一样,当它们在方法内部更改并接收它们作为参数时,它们也会在调用方方法中更改。但是对于Kotlin来说,似乎没有什么是原始的,因此我认为所有内容都是通过引用传递的。