我一直认为Java使用按引用传递。
然而,我看到一篇博客文章声称Java使用传递值。
我想我不明白他们的区别。
原因是什么?
Java总是通过值传递参数,而不是通过引用。
让我通过一个例子来解释这一点:
public class Main {
public static void main(String[] args) {
Foo f = new Foo("f");
changeReference(f); // It won't change the reference!
modifyReference(f); // It will modify the object that the reference variable "f" refers to!
}
public static void changeReference(Foo a) {
Foo b = new Foo("b");
a = b;
}
public static void modifyReference(Foo c) {
c.setAttribute("c");
}
}
我将分步骤解释这一点:
>
声明类型为Foo
的名为f
的引用,并为其分配一个类型为Foo
的新对象,该对象具有属性“f”
。
Foo f = new Foo("f");
从方法方面,声明了一个名为a
的Foo
类型的引用,并将其初始赋值为null
。
public static void changeReference(Foo a)
调用方法changeReference
时,引用a
将被指定作为参数传递的对象。
changeReference(f);
声明一个名为b
的Foo
类型的引用,并为其分配一个Foo
类型的新对象,该对象具有属性“b”
。
Foo b = new Foo("b");
a=b
对属性为“b”
的对象的引用a
,而不是f
,进行新赋值。
当您调用modifyReference(Foo c)
方法时,将创建一个引用c
,并为该对象分配属性“f”
。
c.setAttribute(“c”)
将更改引用c
指向它的对象的属性,并且它是引用f
指向它的同一个对象。
我希望您现在了解了在Java中作为参数传递对象的工作原理:)
我刚注意到你引用了我的文章。
Java规范说Java中的一切都是按价值传递的。在Java中不存在所谓的“通过引用”。
理解这一点的关键是
Dog myDog;
不是狗;它实际上是指向狗的指针。在Java中使用“参考”一词是非常误导的,也是造成这里大部分混乱的原因。他们所说的“引用”的行为/感觉更像我们在大多数其他语言中所说的“指针”。
这意味着,当你
Dog myDog = new Dog("Rover");
foo(myDog);
实际上,您将创建的Dog
对象的地址传递给foo
方法。
(我之所以这么说,主要是因为Java指针/引用不是直接地址,但最容易这样想。)
假设Dog
对象位于内存地址42。这意味着我们将42传递给方法。
如果方法定义为
public void foo(Dog someDog) {
someDog.setName("Max"); // AAA
someDog = new Dog("Fifi"); // BBB
someDog.setName("Rowlf"); // CCC
}
让我们看看发生了什么。
某些狗
设置为值42Dog
被创建。假设他在74号地址 某些狗
赋值给74Dog
(地址74的Dog
对象)现在让我们考虑一下在方法之外会发生什么:
myDog
有变化吗?
这是钥匙。
请记住,myDog
是指针,而不是实际的Dog
,答案是否定的。myDog
仍然具有值42;它仍然指向原始的Dog
(但是请注意,由于行“AAA”,它的名称现在是“Max”-仍然是同一只狗;myDog
的值没有改变。)
跟随地址并更改地址末尾的内容是完全有效的;但是,这不会改变变量。
Java的工作原理与C完全相同。您可以分配一个指针,将指针传递给一个方法,跟随方法中的指针,并更改指向的数据。但是,调用方将看不到您对指针指向的位置所做的任何更改。(在具有按引用传递语义的语言中,方法函数可以更改指针,调用方将看到该更改。)
在C、Ada、Pascal和其他支持按引用传递的语言中,实际上可以更改传递的变量。
如果Java有通过引用的语义学,我们上面定义的foo
方法将改变myDog
指向的位置,当它在行BBB上分配某些狗
时。
将引用参数视为传入变量的别名。分配该别名时,传入的变量也是如此。
Java总是按价值传递的。不幸的是,当我们处理对象时,我们实际上是在处理被称为引用的对象句柄,这些句柄也是按值传递的。这个术语和语义学很容易让很多初学者混淆。
事情是这样的:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
Dog oldDog = aDog;
// we pass the object to foo
foo(aDog);
// aDog variable is still pointing to the "Max" dog when foo(...) returns
aDog.getName().equals("Max"); // true
aDog.getName().equals("Fifi"); // false
aDog == oldDog; // true
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// change d inside of foo() to point to a new Dog instance "Fifi"
d = new Dog("Fifi");
d.getName().equals("Fifi"); // true
}
在上面的例子中,aDog。getName()
仍将返回“Max”
。main
中的值aDog
在函数foo
中不会随Dog
“Fifi”而改变,因为对象引用是通过值传递的。如果通过引用传递,则aDog。调用
foo
后,main
中的getName()将返回“fififi”
。
同样地:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
Dog oldDog = aDog;
foo(aDog);
// when foo(...) returns, the name of the dog has been changed to "Fifi"
aDog.getName().equals("Fifi"); // true
// but it is still the same dog:
aDog == oldDog; // true
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// this changes the name of d to be "Fifi"
d.setName("Fifi");
}
在上面的例子中,
菲菲
是调用foo(aDog)
后的狗的名字,因为对象的名字设置在foo(...)
内。任何foo
在d
上执行的操作,出于所有实际目的,都是在aDog
上执行的,但是不可能更改变量aDog
本身的值。
有关传递参考和传递值的更多信息,请参考以下答案:https://stackoverflow.com/a/430958/6005228.这更透彻地解释了这两种语言背后的语义和历史,也解释了为什么Java和许多其他现代语言在某些情况下似乎同时使用这两种语言。
问题内容: 我一直认为Java使用传递引用。 但是,我已经看到了几篇博客文章声称不是(博客文章说Java使用值传递)。 我不认为我能理解他们的区别。 有什么解释? 问题答案: Java总是按值传递。 不幸的是,我们根本不处理任何对象,而是处理称为引用的 对象句柄(当然是通过值传递)。选择的术语和语义很容易使许多初学者感到困惑。 它是这样的: 在上面的示例中仍将返回”Max”。值aDog内main未
本文向大家介绍JS是按值传递还是按引用传递,包括了JS是按值传递还是按引用传递的使用技巧和注意事项,需要的朋友参考一下 按值传递 VS. 按引用传递 按值传递(call by value)是最常用的求值策略:函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。 按引用传递(call by reference)时,函数的形参接收实参的隐式引用,而不再是副本。这意味着函数形参的值如果被
问题内容: 我读了许多文章,都说Java是通过价值传递的。但是我仍然不能解释按值传递和引用之间的区别。我写了一个示例程序,它像这样执行。 执行 谁能向我解释这些问题… 价值传递是什么意思? 答:它只是将存储在变量中的数字或值传递给函数。我是对还是错。 How do you say Java是通过价值传递? 为什么Java是按值传递而不是按引用传递? 上面的程序Tries是否显示了“按值传递”和“引
问题内容: 基本类型(数字,字符串等)按值传递,但对象未知,因为它们都可以按值传递(如果我们认为保存对象的变量实际上是对该对象的引用) )和按引用传递(当我们认为对象的变量包含对象本身时)。 尽管最后并没有什么大不了,但我想知道呈现通过惯例的参数的正确方法是什么。是否有JavaScript规范的摘录,其中定义了与此相关的语义? 问题答案: JavaScript很有趣。考虑以下示例: 产生输出: 如
问题内容: 如果我将数据帧传递给函数并在函数内部对其进行修改,那么它是按值传递还是按引用传递? 我运行以下代码 函数调用后,的值不变。这是否意味着价值传递? 我也尝试了以下 事实证明,变化并没有。为什么会这样呢? 问题答案: 简短的答案是,Python始终会传递值,但每个Python变量实际上都是指向某个对象的指针,因此有时看起来像是传递引用。 在Python中,每个对象都是可变的或不可更改的。例
我创建了一个MapReduce作业,该作业将计算键的数量,然后根据它们出现的次数对它们进行排序 处理输入时,如 最终目标将是一个类似于 我的地图阶段输出a 我的减少阶段有3个阶段:设置,我初始化一个数组列表来保存我的 数组列表中的值是我创建的一个对象myObject的值,它将文本和Int保存在一个元组中可写,我发现一个奇怪的地方是当我这样做的时候 key是传递到reducer的键,count是我通