当前位置: 首页 > 知识库问答 >
问题:

静态编程语言是“按值传递”还是“按引用传递”?

颜文康
2023-03-14

从这篇文章中我知道Java是按值传递的。我来自Java背景,我想知道Kotlin是用什么在它们之间传递值的。比如扩展或方法等。

共有3个答案

齐修贤
2023-03-14

语义与Java相同。

在Java中,当您拥有一个对象的实例,并将其传递给一个方法时,该方法可以更改该对象的状态,当该方法完成时,这些更改将在调用站点应用于该对象。

这同样适用于静态编程语言。

龙弘盛
2023-03-14

它使用与Java相同的原理。它总是按值传递,您可以想象一个副本被传递。对于基元类型,例如<code>Int</code>,这是显而易见的,这样一个参数的值将被传递到函数中,外部变量不会被修改。请注意,Kotlin中的参数不能重新分配,因为它们的行为类似于vals:

fun takeInt(a: Int) {
    a = 5
}

此代码将无法编译,因为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)
}

您可以使用传入函数的引用来更改实际的对象

澹台玉石
2023-03-14

每次我听到关于“传递值”与“传递引用”的Java争论时,我总是这么想。我给出的答案是:“Java传递引用(按引用传递)的副本(按值传递)”。所以每个人都很开心。我想说,Kotlin的功能与基于JVM的语言相同。

更新

好的,所以这个答案已经有一段时间了,我认为应该包括一些澄清。正如@robert-liberatore在评论中提到的,我所描述的行为对于对象是正确的。每当方法需要任何对象时,您都可以假设 JVM 将在内部复制对该对象的引用并将其传递给您的方法。这就是为什么拥有这样的代码

void doSomething(List<Integer> x) {
  x = new ArrayList<Integer>()
}

List<Integer> x = Arrays.asList(1, 2, 3);
doSomething(x);
x.length() == 3

行为就像它一样。您正在将引用复制到列表中,因此“重新分配它”在实际对象中无效。但由于您引用的是同一个对象,修改其内部内容将影响外部对象。

为了实现不变性,将属性定义为< code>final时,您可能会忽略这一点。您将无法重新分配它们,但是没有什么可以阻止您更改其内容

当然,对于有引用的对象也是如此。在原语的情况下,它不是对包含某物的对象的引用,而是对“某物”本身的引用,事情是不同的。Java仍然会复制整个值(就像复制整个引用一样)并将其传递给方法。但原语只是值,你不能“修改它的内在值”。所以方法内部的任何变化都不会影响外部的值

现在,谈论 Kotlin

在科特林,你“没有”原始的价值观。但是你“确实有”原始类。在内部,编译器会尝试在需要的地方使用JVM原语值,但是您可以假设您总是使用JVM原语的装箱版本。因此,在可能的情况下,编译器只会复制原始值,而在其他情况下,它会复制对对象的引用。或者用代码

fun aJvmPrimitiveWillBeUsedHere(x: Int): Int = x * 2

fun aJvmObjectWillBeUsedHere(x: Int?): Int = if (x != null) x * 2 else 1

我想说,Kotlin场景比Java安全一点,因为它强制其参数是最终的。所以你可以修改它的内部内容,但不能重新分配它

fun doSomething(x: MutableList<Int>) {
    x.add(2)                  // this works, you can modify the inner state
    x = mutableListOf(1, 2)   // this doesn't work, you can't reassign an argument
}
 类似资料:
  • 问题内容: 基本类型(数字,字符串等)按值传递,但对象未知,因为它们都可以按值传递(如果我们认为保存对象的变量实际上是对该对象的引用) )和按引用传递(当我们认为对象的变量包含对象本身时)。 尽管最后并没有什么大不了,但我想知道呈现通过惯例的参数的正确方法是什么。是否有JavaScript规范的摘录,其中定义了与此相关的语义? 问题答案: JavaScript很有趣。考虑以下示例: 产生输出: 如

  • 本文向大家介绍JS是按值传递还是按引用传递,包括了JS是按值传递还是按引用传递的使用技巧和注意事项,需要的朋友参考一下 按值传递 VS. 按引用传递 按值传递(call by value)是最常用的求值策略:函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。   按引用传递(call by reference)时,函数的形参接收实参的隐式引用,而不再是副本。这意味着函数形参的值如果被

  • 问题内容: 我一直认为Java使用传递引用。 但是,我已经看到了几篇博客文章声称不是(博客文章说Java使用值传递)。 我不认为我能理解他们的区别。 有什么解释? 问题答案: Java总是按值传递。 不幸的是,我们根本不处理任何对象,而是处理称为引用的 对象句柄(当然是通过值传递)。选择的术语和语义很容易使许多初学者感到困惑。 它是这样的: 在上面的示例中仍将返回”Max”。值aDog内main未

  • 问题内容: 如果我将数据帧传递给函数并在函数内部对其进行修改,那么它是按值传递还是按引用传递? 我运行以下代码 函数调用后,的值不变。这是否意味着价值传递? 我也尝试了以下 事实证明,变化并没有。为什么会这样呢? 问题答案: 简短的答案是,Python始终会传递值,但每个Python变量实际上都是指向某个对象的指针,因此有时看起来像是传递引用。 在Python中,每个对象都是可变的或不可更改的。例

  • 问题内容: 我读了许多文章,都说Java是通过价值传递的。但是我仍然不能解释按值传递和引用之间的区别。我写了一个示例程序,它像这样执行。 执行 谁能向我解释这些问题… 价值传递是什么意思? 答:它只是将存储在变量中的数字或值传递给函数。我是对还是错。 How do you say Java是通过价值传递? 为什么Java是按值传递而不是按引用传递? 上面的程序Tries是否显示了“按值传递”和“引

  • 我创建了一个MapReduce作业,该作业将计算键的数量,然后根据它们出现的次数对它们进行排序 处理输入时,如 最终目标将是一个类似于 我的地图阶段输出a 我的减少阶段有3个阶段:设置,我初始化一个数组列表来保存我的 数组列表中的值是我创建的一个对象myObject的值,它将文本和Int保存在一个元组中可写,我发现一个奇怪的地方是当我这样做的时候 key是传递到reducer的键,count是我通