我读了那个Java passes arrays to functions by reference (sort of),它允许修改它,这将反映在原始数组上。
我不确定上述链接中的引用部分,因为有人说Java is always pass by value, with no exceptions, ever.但我确实知道对参数数组的修改也会改变原始数组。
这是否意味着当我返回通过参数传递的相同数组时,Java会返回原始数组的副本?虽然不这样做,而使用原始数组代替将节省一些内存和CPU使用?或两种情况下Java都复制了数组吗?
例如,以下两个功能是相同的还是第一个保存内存和CPU资源?:
public void modifyArray (int[] arr)
{
for (int i = 0; i < arr.length; i++) arr[i] = i + 1;
}
public int[] modifyArray (int[] arr)
{
for (int i = 0; i < arr.length; i++) arr[i] = i + 1;
return arr;
}
修改
为了更清楚,我只关心性能(特别是在处理大型数组时)并且我实际上并不需要复制数组,我有一个现有的代码可以做到这一点并想知道如果移除重新调整部分会提高性能。
答案 0 :(得分:4)
Java按值传递引用。这意味着更换阵列没有任何危害,即
public void f(String[] a)
{
a = new String[42];
}
但更改其中的任何内容都会更改原始数组。一般对象的深度复制可能非常耗时,并且在对象包含引用对象的对象的情况下也很困难......因此标准行为是避免它。
答案 1 :(得分:2)
这两个函数都修改传入的数组。值传递的是指向数组的指针,因此当你操作它指向的底层数组时,你正在改变传入的数组。因此,第二个函数在对它进行一些更改后返回传入的相同数组。
现在,如果你将arr = ...
放在函数中的某个位置然后对其进行处理,你将不修改传入的数组,并且返回的内容会有所不同。这就是为什么有人说Java正在传递价值。只是该值是所有非原始情况下的指针。
答案 2 :(得分:1)
您提供的方法在某种程度上是相同的,它们都会修改作为参数传递的数组。返回数组时没有隐式深层复制。
但是,要么返回深度副本的数组/集合,要么使其无法修改,这是一个很好的做法。
您可以通过System.arraycopy创建数组的副本,这应该超级快,或者,在使用容器时,通过Collections.unmodifiableList/Set/etc()
注意:这仅适用于&#34; 1D&#34;如果您有n维数组或容器,则需要进行深层复制。
答案 3 :(得分:1)
每个primitve都是通过Java传递的。
看看这个例子:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp" ng-controller="mainController as mainCtrl">
<!--<pre>{{mainCtrl.items | json : 2}}</pre>-->
<pre class="selection">
selected items:
{{ mainCtrl.items | filter: {'checked':true} | json: 2}}
</pre>
<select ng-options="count for count in mainCtrl.checkCounts" ng-model="mainCtrl.checkedItemsCount" ng-change="mainCtrl.selectItems()">
<option style="display:block" value=""></option>
</select>
<ul>
<li ng-repeat="item in mainCtrl.items">
{{item.id}} <input type="checkbox" ng-model="item.checked"/>{{item.value}}
</li>
</ul>
</div>
如果您运行它:
public void test2(int s) {
s = 2;
System.out.println(2);
}
Java将按值传递s。它不会影响原始价值。 k的输出仍然是5.
如果是对象 - 它总是按值引用。它通过引用原始值并修改它。
回答你的问题 - 在第二个例子中,你只需返回对原始数组的引用。无论是否返回引用 - 原始引用都会受到影响(因为数组是对象)。
答案 4 :(得分:1)
你可以这样做;有一个方法返回作为参数传递给该方法的相同数组。
但这使得该方法的“界面”有点难以理解。
换句话说:除非我们说的是非常大的数组;或称为每秒数百次的方法;那么你应该专注于清晰,可读的代码,不会给读者带来惊喜;与无正当理由添加退货声明。
你知道,你的方法的调用者应该知道他在做什么。换句话说:他已经把一些阵列传给了你;为什么你认为你应该把它归还给他?