我们可以在java中使用引用传递吗?如果否 java.util.Arrays.sort 如何工作?
Posted
技术标签:
【中文标题】我们可以在java中使用引用传递吗?如果否 java.util.Arrays.sort 如何工作?【英文标题】:Can we use pass by reference in java? If No How does java.util.Arrays.sort works? 【发布时间】:2015-08-04 06:25:19 【问题描述】:我曾经认为 Java 支持传递值和传递引用,但我遇到了很多讨论,例如
-
Java is always pass by value, with no exceptions, ever .
Java is always pass-by-value
Java always passes arguments by value NOT by reference.
Java passes references by value.So you can't change the reference that gets passed in.
如果 java 只支持按值传递 java.util.Array.sort()
或 Collections.sort(unsortList)
如何工作?
int iArr[] = 2, 1, 9, 6, 4;// sorting array
Arrays.sort(iArr);
System.out.println("The sorted int array is:");
for (int number : iArr)
System.out.println("Number = " + number);
更新: 传递引用(按值)实际上意味着什么?它与 C 或 C++ 中数组的引用传递行为有何不同?
更新: 如果我错了,请纠正我。在C中我们通过引用传递变量的地址。在Java中我们将引用传递给对象(或值)。只要方法中的变量指向对象,对象的值就会随着变量的变化而变化调用的方法。 没有对象或引用的副本!,我只能看到 2 个不同的变量指向与通过引用传递相同的对象。在 C++ 中类似,通过引用传递两个不同的变量指向相同的地址。
【问题讨论】:
我投票结束这个问题,因为问题中的链接答案已经回答了这个问题。 this问题的前三个答案。 它用详细的例子解释了你问题的第二部分。你有什么不明白的? 引用来自this 回答If it were passed by reference, then the aDog.getName() in main would return "Fifi" after the call to foo
的评分最高的答案。这解释了按值传递与按引用传递有何不同。引用第二个评分最高的答案:myDog still has the value 42; it's still pointing to the original Dog (but note that because of line "AAA", its name is now "Max")
。请解释一下您从答案中不明白的地方?他们回答你问什么。
我非常理解你的问题。不管你怎么说,java 都是按值传递的,如果你明白这意味着什么,你就不必问任何与 Java 中的引用如何工作有关的问题。
【参考方案1】:
数组是引用类型,因此iArr
变量持有对数组的引用。
换句话说,当你打电话时
Arrays.sort(iArr);
您将引用(按值)传递给 sort 方法,该方法对 iArr
引用的数组进行排序。
来自 cmets:
传递引用(按值)实际上意味着什么?
通过引用传递意味着您基本上是将变量本身传递给方法。即,该方法对变量所做的任何事情都会影响外部变量。在 Java 中从来没有这种情况。 (尝试实现一个交换方法,您就会明白我的意思。)按值传递意味着您传递存储在变量中的值。在这种情况下,值是一个引用,所以它通过值传递一个引用。
回复。第二次更新:
从你的形象来看,我认为你已经很好地理解了这种情况,我认为这归结为术语。
如果我们暂时忘记 C++,它真的很简单。您需要记住的是 (A) 当您调用 method(var)
时,参数是 var
包含的任何内容的副本,并且 (B) 非原始变量的内容是引用(“指针”如果你喜欢)。
请注意,在您的问题中
int iArr[] = 2, 1, 9, 6, 4;
相当于
int[] iArr = new int[] 2, 1, 9, 6, 4 ;
所以一切都检查出来了:iArr
持有一个引用,new
返回一个引用。
当您调用Arrays.sort(iArr)
时,iArr
的内容被传递(即对数组的引用)。这仍然不是按引用传递,因为传递的是值,而不是变量本身。如果将方法内部的形参重新赋值为指向其他数组,iArr
在方法返回时仍将指向原始数组。
如果我们做用 C++ 来思考,事情往往会更复杂一些; C++ 的引用概念略有不同。通过 C++ 参考,您实际上可以实现真正的swap
:
void swap(int &x, int &y)
int temp = x;
x = y;
y = temp;
即您可以传入“变量”(而不仅仅是变量的内容)。我喜欢这样想,因为您正在与您正在调用的方法共享变量的范围。这不能在 Java 中完成。
因此,考虑到这一点,我会说 Java 引用更像 C++ 指针,只是它们在某种意义上受到限制,因为您不能像在 C++ 中那样使用 *
运算符取消引用(你可以' t 在 Java 中执行 *person
,即使 person
存储与指向人的指针相对应的内容)并且您无法使用 &
运算符获取对象的地址。你也不能做任何指针算术。例如,您不能使用 iArr + 3
来获取数组的第四个元素。
【讨论】:
传递引用(按值)实际上意味着什么?它与 C 或 C++ 中数组的引用传递行为有何不同? 按引用传递 的意思是您基本上是将变量 传递给方法。即,该方法对变量所做的任何事情都会影响外部变量。在 Java 中情况并非如此。 (尝试实现swap
方法,您就会明白我的意思。)按值传递意味着您传递存储在变量中的值。在这种情况下,值是一个引用,所以它通过值传递一个引用。
支持@aioobe 评论,查看Why can't you swap in Java?
@JishnuPrathap,不客气。我认为您所链接的问题中没有任何答案令人满意,但目前无法发布接近顶部的新答案。
Yes(但 C++ 引用仍然更强大,因为编译器在内部将使用 *
或那个指针,这在 Java 中无法实现)。【参考方案2】:
Java 总是使用按值传递。按值传递意味着“值”在传递时被复制。在传递对象时,被复制的“值”是对对象的“引用”,而不是对象本身。因此,如果您要对方法内的对象进行更改,这些更改将在方法执行后得到反映。但是,例如将传递的“引用”设置为“null”将无效。
【讨论】:
如果不是因为 “当涉及到传递对象...”,我会赞成,因为对象一开始就没有被传递。如果您更新,请回复,以便我得到一个 ping。【参考方案3】:Java 总是按值传递。 但传递参数值取决于您传递的实体类型..
Primitives - 传递原始值。所以在被调用方法中所做的更改不会影响调用方法中的原始值。
Objects - 传递引用该对象的内存地址(即堆内存中的位置)。因此,在被调用方法中所做的更改会反映在调用方法中。
【讨论】:
通过说“但是传递参数值取决于你传递的实体的类型..”你只是在增加混乱!没有区别。在这两种情况下 都传递了原始值。因此,在被调用方法中所做的更改不会影响调用方法中的原始值。归结为解释iArr
的“原始值”是对堆上某些东西的引用。不管方法做什么,都不能改变iArr
的内容。【参考方案4】:
Java 仅支持按值传递。它不支持按引用传递。
查看以下代码:
public static void main(String[] args)
List l1 = new ArrayList(Arrays.asList(4,6,7,8));
System.out.println("Printing list before method calling:"+ l1);
foo(l1);
System.out.println("Printing list after method calling:"+l1);
public static void foo(List l2)
l2.add("done"); // adding elements to l2 not l1
l2.add("blah");
看起来像通过引用传递。但在内部仅按价值运作。
输出:
Printing list before method calling:[4, 6, 7, 8]
Printing list after method calling:[4, 6, 7, 8, done, blah]
此示例与您的帖子几乎相似。您正在将数组传递给数组方法,例如Arrays.sort(iArr)
。我将列表参数传递给我的方法 foo 即:foo(list1)
。
查看帖子了解更多信息
Java pass by reference issue with List
【讨论】:
“即使我们在内部通过引用传递......”不,我们不是,说我们是只是令人困惑的事情。以上是关于我们可以在java中使用引用传递吗?如果否 java.util.Arrays.sort 如何工作?的主要内容,如果未能解决你的问题,请参考以下文章