我在网站上研究Java参数时一直看到这一点,但我相信我误解了它。
问题1:Is Java "pass-by-reference" or "pass-by-value"?
问题2:Does Java pass by reference?
人们一直说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");
}
}
用我目前的想法"人们的意思(Question 1的答案),当事情发生变化时,他们错了。我不理解或忽视什么?
人们是否提到您可以修改参数引用的数据这一事实,但您无法更改哪些"数据/对象"这个论点是指?
答案 0 :(得分:2)
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.
}
}
答案 1 :(得分:1)
人们是否提到您可以修改数据的事实 参数是引用,但你不能改变哪个“数据/对象” 论证是指?
是的,确切地说。例如:
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
的单个元素的新列表。这就是引用按值传递的含义:如果使引用的值副本引用新对象,则原始引用仍引用相同的旧对象。
答案 2 :(得分:0)
这意味着
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
答案 3 :(得分:0)
引用指向对象。
你没有改变引用而是对象。
这会改变引用,但它不会更改变量list
,因为引用本身会被复制:
public static void breakStuff( List l ) {
l = new ArrayList();
}
答案 4 :(得分:0)
这意味着当您按值传递引用时,您可以更改其值,但不会发生任何事情。
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.
}
答案 5 :(得分:0)
ArrayList对象实际上在堆上。 ArrayList对象始终保持在堆上的位置。
您的参考"列表" (类型列表)是"指向"到堆上的那个对象。或者说另一种方式:" list"包含该对象的内存地址!
将该引用传递给另一个方法时 - 您将在堆上传递该对象的位置。或者换句话说:你将堆上(静止)对象的地址从一个方法传递给另一个方法。
当breakstuff方法使用" l"引用它将修改对象" l"指着。
一个愚蠢的,但通知类比:你在你家旁边山上的一只红鹿上瞄准一支魔术步枪。然后你将步枪发给下一个城镇的朋友。当朋友透过步枪瞄准镜时,步枪立即转动并指向那只红鹿的山丘。
答案 6 :(得分:0)
你熟悉另一种语言吗?比较是有益的。
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 ++中有引用传递吗?或者全部按值传递?