[英]What does Pass Reference by Value in Java mean?
我在网站上研究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.