作为函数参数传递的Java对象[重复]
Posted
技术标签:
【中文标题】作为函数参数传递的Java对象[重复]【英文标题】:Java Objects passed as Function Parameters [duplicate] 【发布时间】:2016-10-16 04:44:28 【问题描述】:以下关于 Java 的说法是真是假?
在 Java 中,当一个类或对象的实例被指定为方法的参数时,会生成该对象的副本
我知道 Java 中的函数是按值传递的,这意味着正在制作对象的副本?
但同时,如果 java 对象是引用,而你传递一个引用,这与实际数据的副本是不同的,不是吗?
如果你传递一个引用,当引用被重新分配时,对象将被重新分配,使得 Java 传递引用而不是传递值?
如您所见,我非常对此感到困惑
【问题讨论】:
这是一个非常完整的question 示例。没有制作对象的副本,正在制作引用的副本。 【参考方案1】:在java中,一切都是通过副本传递的。
原语通过副本传递。所以在函数内部改变它不会反映在外部。
对于对象,传递给函数的是引用的副本(不是对象的副本)。这意味着更改函数内部的属性外部引用会看到修改,但更改引用本身(例如分配 null)不会反映在函数外部。
请举一些例子来更好地解释。
改变原语的函数:
public void notChange(int a)
a = 3;
// Here a is 3
int a = 0;
notChange(a);
// Here a is 0
对于改变对象内部内容的函数
public void changeContent(List<String> list)
list.add("x");
// Here list has one more element
List<String> list = new ArrayList<String>();
// Here list has size 0
changeContent(list);
// Here list has size 1
对于改变对象引用的函数
public void changeReference(List<String> list)
list = null;
List<String> list = new ArrayList<String>();
changeReference(list);
// Here list is not null
【讨论】:
【参考方案2】:如果是对象,则传递一个引用的副本。请注意,这并不意味着传递了对象本身的副本。您对对象所做的任何更改也将反映在原始对象中。如果您没有正确复制对象,这可能会导致一些疯狂的事情。使用复制构造函数或类似复制对象的东西。
另外,阅读deep and shallow copy。
【讨论】:
【参考方案3】:这是一个在c++中按值传递和按引用传递的例子。在此示例中,java 的行为类似于按值传递版本。值是指向对象的指针。
#include <stdio.h>
class Obj
int value;
public:
Obj(int v)
value = v;
void echo()
printf("%d\n", value);
;
void byValue(Obj* obj)
obj = new Obj(-1);
obj->echo();
void byReference(Obj*& obj)
obj = new Obj(-1);
obj->echo();
int main(int argc, char** args)
Obj* o = new Obj(1);
byValue(o);
o->echo();
byReference(o);
o->echo();
return 0;
(抱歉泄漏,这不是一个好的实践示例) 输出是:
-1
1
-1
-1
【讨论】:
【参考方案4】:我会从你的第一个问题开始一步步回答你:
在 Java 中,当一个类或对象的实例被指定为 方法的参数,正在制作该对象的副本
这是 false,当您将对象传递给方法时,Java 永远不会复制它,正如 Davide Lorenzo 所说,您正在传递对对象的引用,不是对象本身,因此如果该方法修改了类的某些属性,那么您的值也会在该方法之外进行修改。
所以我们可以回答第二个和第三个问题:
我知道 Java 中的函数是按值传递的,这意味着 正在制作对象的副本?
不,Java 不会复制。正如 Davide Lorenzo 所说,您传递的是引用的副本而不是对象的副本。
但同时,如果 java 对象是引用并且你传递了一个 参考,这与实际数据的副本不同吗?
是的,传递引用与传递对象的副本确实不同。 我将举例说明一切。 假设我们有一个具有 color
属性的对象 Flowerpublic class Flower
String color = "red";
enter code here
我们可以想象AnotherObject的方法setColor
public void setColor(Flower flower, String color_string)
flower.color = color_string;
我们可以有以下情况
public static void main(String args[])
Flower myFlower = new Flower();
AnotherObject otherObject = new AnotherObject();
otherObject.setColor(myFlower, "yellow");
System.out.println("The color of the flower is: "+myFlower.color);
这段代码的输出将是:
The color of the flower is yellow
这就是为什么你要传递对象的引用,而不是对象本身。
现在您可以问为什么 Java 被视为 按值传递? 在this previous post 上有一个非常有趣的讨论,我会引用它的最佳答案:
Java 总是按值传递。不幸的是,他们决定打电话 指针引用,从而使新手感到困惑。因为那些参考 按值传递。
最后但并非最不重要的一点是,只有原始类型不是通过 Java 中的引用来管理的,所以传递 int 与传递 Integer 确实不同,我建议你看看this post关于这个论点。
【讨论】:
【参考方案5】:在 Java 中,当一个类或对象的实例被指定为 方法的参数
这就是你出错的地方。每个参数都有一个类型。 Java 中仅有的类型是原始类型和引用类型。因此,Java 中的参数值(或任何其他变量,或任何表达式的值)只能是原语,或引用。不是“对象”。
【讨论】:
以上是关于作为函数参数传递的Java对象[重复]的主要内容,如果未能解决你的问题,请参考以下文章