Java对象作为函数参数传递

时间:2016-06-15 07:45:32

标签: java function object pass-by-reference pass-by-value

关于Java的以下陈述是假的吗?

在Java中,当一个类或对象的实例被指定为方法的参数时,正在创建该对象的副本

我知道Java中的函数是按值传递的,这意味着正在制作对象的副本吗?

但与此同时,如果java对象是引用并且你传递了一个引用,这与实际数据的副本不同吗?

如果你传递一个引用,当重新分配引用时,对象将被重新分配,使得Java传递引用不是按值传递的?

正如您所看到的,我非常对此感到困惑

5 个答案:

答案 0 :(得分:7)

在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

答案 1 :(得分:0)

如果是对象,则传递参考的副本。请注意,此 并不意味着传递了对象本身的副本 。您对该对象所做的任何更改也将反映在原始对象中。如果你没有正确复制你的对象,这可能会导致一些疯狂的事情。使用复制构造函数或类似的东西来复制对象。

另请阅读deep and shallow copy

答案 2 :(得分:0)

这是一个按值传递并在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

答案 3 :(得分:0)

我会尝试从第一个问题开始逐步回答你:

  

在Java中,当一个类或对象的实例被指定为   方法的参数,正在制作该对象的副本

这是 false ,当您将对象传递给方法时,Java永远不会复制它,因为 Davide Lorenzo 表示您正在传递对象的引用,不是对象本身所以如果方法修改了类的某些属性,你将在方法之外修改值。

所以我们可以回答第二和第三个问题:

  

我知道Java中的函数是按值传递的,这意味着   正在制作一个对象的副本?

不,Java不会复制。正如 Davide Lorenzo 所说,你传递的是参考文献的副本而不是对象的副本。

  

但与此同时,如果java对象是引用而你传递了一个   参考,这是不同的实际数据的副本不是吗?

是的,传递引用与传递对象的副本完全不同。 我将通过一个例子澄清一切。 假设我们的对象 Flower 的属性为 color

public 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

答案 4 :(得分:0)

  

在Java中,当一个类或对象的实例被指定为   方法的参数

这是你出错的地方。每个参数都有一个类型。 Java中唯一的类型是基本类型引用类型。因此,Java中参数(或任何其他变量或任何表达式的值)的值只能是基元或引用。不是“对象”。