传递参数与从函数返回参数

从标题中可以清楚地看出我们应该采用哪种方法?

意图是传递一些方法参数并获得输出。 我们可以传递另一个参数,方法会更新它,方法现在不需要返回任何东西,方法只会更新输出变量,它会反映给调用者。

我只想通过这个例子来构建问题。

List result = new ArrayList(); 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 result) { // populates result } 

 List result = new ArrayList(); for (int i = 0; i < SOME_NUMBER_N; i++) { List subResult = fun(SOME_COLLECTION.get(i)); // merges subResult into result mergeLists(result, subResult); } // in some other class public List fun(String s) { List res = new ArrayList(); // some processing to populate res return res; } 

我明白一个人通过了参考而另一个没有。

我们应该选择哪一种(在不同情况下)以及为什么?

更新 :仅考虑可变对象。

从函数返回值通常是编写代码的更简洁的方法。 由于创建和销毁指针的性质,传递值并修改它是更多的C / C ++风格。

开发人员通常不希望通过传递函数来修改它们的值,除非函数明确声明它修改了值(我们经常浏览文档)。

但也有例外。

考虑一下Collections.sort的例子,它实际上确实做了一个列表的排序。 想象一下包含100万件物品的清单,你正在对它进行分类。 也许你不想创建另外有100万条目的第二个列表(即使这些条目指向原始条目)。

支持使用不可变对象也是一种好习惯。 不可变对象在开发的大多数方面(例如线程)引起的问题要少得多。 因此,通过返回一个新对象,您不会强制参数变为可变。

重要的是要明确你在方法中的意图。 我的建议是尽可能避免修改参数,因为它不是Java中最典型的行为。

你应该归还它。 你提供的第二个例子是要走的路。

首先,它更清楚。 当其他人阅读您的代码时,他们可能没有注意到参数被修改为输出。 您可以尝试命名变量,但是当涉及到代码可读性时,它更可取。

你应该返回而不是传递它的大原因是使用不可变对象。 你的例子,List,是可变的,所以它可以正常工作。 但是如果你试图以这种方式使用String, 它将无法工作。

由于字符串是不可变的,如果你将一个字符串作为参数传递,然后该函数说:

 public void fun(String result){ result = "new string"; } 

您传入的结果值不会被更改。 相反,本地范围变量’result’现在指向一个有趣的新字符串,但您的调用方法中的结果仍然指向原始字符串。

如果你打电话:

 String test = "test"; fun(test); System.out.println(test); 

它将打印:“测试”,而不是“新字符串”!

所以肯定,它优于回归。 🙂

返回它将使代码更清晰,并减少方法/类之间的耦合。

这更多是关于最佳实践和您自己的编程方法。 我会说如果你知道这将是一个值返回类型函数,如:

函数IsThisNumberAPrimeNumber {}

然后你知道这只会返回一个布尔值。 我通常使用函数作为帮助程序而不是大的子程序。 我还应用命名约定来帮助指示我期望sub \ function将返回的内容。 例子:

GetUserDetailsRecords GetUsersEmailAddress IsEmailRegistered

如果你看看这3个名字,你可以告诉第一个是给你一些列表或类的多个用户详细记录,第二个会给你一个电子邮件的字符串值,第三个可能会给你一个布尔值。 如果你改变了名字,你改变了意思,所以我想再考虑这个。

我认为我们不理解的原因是这两种行为完全不同。 将变量传递给函数是一种提供函数数据的方法。 从函数返回它是一种将数据传递出函数的方法。

如果你的意思是这两个动作之间的区别:

 public void doStuff(int change) { change = change * 2; } 

 public void doStuff() { int change = changeStorage.acquireChange(); change = change * 2; } 

然后第二个通常更干净,但有几个原因(安全性,function可见性等)可以阻止您以这种方式传递数据。

它也是首选,因为它使重用代码更容易,并使其更加模块化。