繁体   English   中英

Java中的Pass引用值是什么意思?

[英]What does Pass Reference by Value in Java mean?

我在网站上研究Java论点时一直看到这一点,但我相信我误解了它。

问题1: Java是“通过引用传递”还是“按值传递”?

问题2: Java是否通过引用传递?

人们一直说java引用类型是按值传递的,因此引用本身不会改变。 而且我相信我的困惑来自于“引用本身”。

最初我将其解释为意味着参数所指的内容,无法以任何方式更改或修改,例如添加到列表中的内容。 遗憾的是,这在某种程度上是错误的并且已经产生了有趣的结果

当我运行下面的简单代码时,我得到[test1, test2] ,所以在我看来“引用” list已经改变了。

import java.util.ArrayList;
import java.util.List;

public class HelloWorld {
    public static void main(String[] args)
    {
        List list = new ArrayList();
        list.add("test1");
        breakStuff(list);
        System.out.println(list.toString());
    }

    public static void breakStuff( List l ) {
        l.add("test2");
    }
}

根据我目前对人们意味着什么的“想法”( 问题1的答案),当事情发生变化时,他们错了。 我不理解或忽视什么?

是否有人提到您可以修改参数引用的数据这一事实,但您无法更改参数所指的“数据/对象”?

public class HelloWorld {
    public static void main(String[] args)
    {
        List list = new ArrayList(); // here list is a "reference" to an "ArrayList" Object
        list.add("test1"); // adding data to the "Object" using the "reference"
        breakStuff(list); // passing the "reference-by-value"
        System.out.println(list.toString()); // printing
    }

    public static void breakStuff( List l ) { // getting the same reference as the original. So l==list is true.
        l.add("test2"); // adding to the same/original object because the reference is same.
l=null; // try this and see what happens. l will point to a "different" object i/e, null while list will be pointing to the original one.
    }
}

是否有人提到您可以修改参数引用的数据这一事实,但您无法更改参数所指的“数据/对象”?

对,就是这样。 例如:

public class HelloWorld {
  public static void main(String[] args)
  {
    List list = new ArrayList();
    list.add("test1");
    breakStuff(list);
    System.out.println(list.toString());
  }

  public static void breakStuff( List l ) {
    l.add("test2");
    l = new ArrayList();
    l.add("foo");
  }
}

不会将原始list更改为具有名为foo的单个元素的新列表。 这就是通过值传递引用的含义:如果使引用的值副本引用新对象,则原始引用仍引用相同的旧对象。

它的意思是

a = c ;
f(a) { a = b; }
// after we are out of f() here a == c

然而

a.x = 0
f(a) { a.x = 1 }
// after we are out of f() here a.x == 1

引用指向对象。

您没有更改引用而是更改对象。

这会改变引用,但它不会更改变量list因为引用本身会被复制:

public static void breakStuff( List l ) {
        l = new ArrayList();
}

这意味着当您通过值传递引用时,您可以更改其值,并且不会发生任何事情。

void passReferenceByValue(List list) {//Java code

    list = new ArrayList(); //We assign new value to reference
    list.add("reftByValue")'

}
void passReference(List* list) {//Non Java code

   list = new ArrayList(); //We assign new value to reference 
   list.add("reference")'
}

我们测试一下:

  void testPassing() {

    List start = null;

    passByValue(start);

    System.out.println("PassByValue: " + start);

    passReference(start);

    System.out.println("PassReference:" + start);
  }

输出:

PassByValue: null
PassByValue: {reference}

常见误解的原因是实例的变异而不是参考的变化。

   void mutationTest(List list) {

         list.add("mutationOfList"); // In this case we mutate the object that reference point.
   }

ArrayList对象实际上在堆上。 ArrayList对象始终保持在堆上的位置。

您的引用“list”(类型为List)是“指向”堆上的该对象。 或者说另一种方式:“list”包含该对象的内存地址!

将该引用传递给另一个方法时 - 您将在堆上传递该对象的位置。 或者换句话说:您将堆上(静止)对象的地址从一个方法传递到另一个方法。

当breakstuff方法使用“l”引用时,它将修改“l”指向的对象。

一个愚蠢的,但通知类比:你在你家旁边山上的一只红鹿瞄准一支魔术步枪。 然后你将步枪发给下一个城镇的朋友。 当朋友透过步枪瞄准镜时,步枪立即转动并指向那只红鹿的山丘。

你熟悉另一种语言吗? 比较将是有益的。

Java代码:

public class HelloWorld {
    public static void main(String[] args)
    {
        List list = new ArrayList();
        list.add("test1");
        breakStuff(list);
        System.out.println(list.toString());
    }

    public static void breakStuff( List l ) {
        l.add("test2");
    }
}

等效的C ++:

class HelloWorld {
public:
    static void main(String[] args)
    {
        List *list = new ArrayList();
        list->add("test1");
        breakStuff(list);
        System::out->println(list->toString());
    }

    static void breakStuff( List *l ) {
        l->add("test2");
    }
}

你会说在C ++中有引用传递吗? 或者全部通过价值?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM