从标题中可以清楚地看出我们应该采用哪种方法?
意图是传递一些方法参数并获得输出。我们可以传递另一个参数,方法会更新它,方法现在不需要返回任何东西,方法只会更新输出变量,它会反映给调用者。
我只想通过这个例子来构建问题。
List<String> result = new ArrayList<String>();
for (int i = 0; i < SOME_NUMBER_N; i++) {
fun(SOME_COLLECTION.get(i), result);
}
// in some other class
public void fun(String s, List<String> result) {
// populates result
}
与
List<String> result = new ArrayList<String>();
for (int i = 0; i < SOME_NUMBER_N; i++) {
List<String> subResult = fun(SOME_COLLECTION.get(i));
// merges subResult into result
mergeLists(result, subResult);
}
// in some other class
public List<String> fun(String s) {
List<String> res = new ArrayList<String>();
// some processing to populate res
return res;
}
我知道一个人通过了参考而另一个没有。
我们应该选择哪一种(在不同情况下)以及为什么?
更新:仅考虑可变对象。
答案 0 :(得分:16)
从函数返回值通常是编写代码的更简洁方法。由于创建和销毁指针的性质,传递值并修改它是更多的C / C ++风格。
开发人员通常不希望通过传递函数来修改它们的值,除非函数明确指出它修改了值(我们经常浏览文档)。
但也有例外。
考虑一下Collections.sort
的例子,它实际上确实做了一个列表。想象一下包含100万件物品的清单,你正在对它进行分类。也许你不想创建另外有100万个条目的第二个列表(即使这些条目指向原始条目)。
支持使用不可变对象也是一种好习惯。不可变对象在开发的大多数方面(例如线程)导致的问题要少得多。因此,通过返回一个新对象,您不会强制参数变为可变。
重要的是要明确你对方法的意图。我的建议是尽可能避免修改参数,因为它不是Java中最典型的行为。
答案 1 :(得分:7)
你应该退货。你提供的第二个例子是要走的路。
首先,它更清晰。当其他人阅读您的代码时,他们可能没有注意到参数被修改为输出。您可以尝试命名变量,但是当涉及到代码可读性时,它更可取。
BIG原因为什么你应该返回它而不是传递它,是不可变对象。 你的例子,List,是可变的,所以它可以正常工作。 但是如果你试图以这种方式使用String,那么就行不了。
由于字符串是不可变的,如果你将一个字符串作为参数传入,然后函数说:
public void fun(String result){
result = "new string";
}
您在中传递的结果值不会被更改。相反,本地范围变量'result'现在指向fun中的新字符串,但调用方法中的结果仍然指向原始字符串。
如果您致电:
String test = "test";
fun(test);
System.out.println(test);
它将打印:“test”,而不是“new string”!
所以当然,它优于回归。 :)
答案 2 :(得分:1)
返回它将使代码更清晰,并减少方法/类之间的耦合。
答案 3 :(得分:1)
根据伙计们的推荐和Java代码约定以及语法限制,这是一个坏主意,使代码更难以理解 但是您可以通过实现引用持有人类来做到这一点
public class ReferenceHolder<T>{
public T value;
}
,并将ReferenceHolder对象传递到要由方法填充或修改的方法参数中。 另一方面,该方法必须将其返回值分配给Reference值,而不是返回它。 这是通过ReferenceHolder而不是函数return来获取平均方法结果的代码。
public class ReferenceHolderTest {
public static void main(String[] args) {
ReferenceHolder<Double> out = new ReferenceHolder<>();
average(new int[]{1,2,3,4,5,6,7,8},out);
System.out.println(out.value);
}
public static void average(int[] x, ReferenceHolder<Double> out ) {
int sum=0;
for (int a : x) {
sum+=a;
}
out.value=sum/(double)x.length;
}
}
答案 4 :(得分:0)
这更多是关于最佳实践和您自己的编程方法。我想说如果你知道这将是一个值返回类型函数,如:
function IsThisNumberAPrimeNumber {}
然后你知道这只会返回一个布尔值。我通常使用函数作为帮助程序而不是大的子程序。我还应用命名约定来帮助指示我期望sub \ function将返回的内容。 例子:
GetUserDetailsRecords GetUsersEmailAddress IsEmailRegistered
如果你看看这3个名字,你可以告诉第一个是给你一些列表或类的多个用户详细记录,第二个会给你一个电子邮件的字符串值,第三个可能会给你一个布尔值。如果您更改名称,则更改含义,因此我会另外考虑这一点。
答案 5 :(得分:0)
我认为我们不理解的原因是这两种行为完全不同。将变量传递给函数是一种提供函数数据的方法。从函数返回它是一种将数据传递出函数的方法。
如果你的意思是这两个行动之间的区别:
public void doStuff(int change) {
change = change * 2;
}
和
public void doStuff() {
int change = changeStorage.acquireChange();
change = change * 2;
}
然后第二个通常更干净,但有几个原因(安全性,功能可见性等)可能会阻止您以这种方式传递数据。
这也是首选,因为它使重用代码更容易,并使其更加模块化。