在 returned 值是作为参数提供的对象的函数中使用 return 是一种好习惯吗?
Is it a good practice to use the return of a function where the returned value is an object supplied as an argument?
我只是想问一下这是否是一个好的 java 做法,或者有更好的方法(官方方法)来做同样的事情。
首先,我需要更新一些hashmap信息:
Map<Date, Object> rows = new HashMap<Date, Object>();
这是一个 excel 行的对象,每个日期(即十月一日、十月二日等...)和一个包含该行信息的对象。
所以,为了得到这些信息,我有一些方法比如:
rows = performQuery1(rows, foo, bar, initDate, endDate);
rows = performQuery2(rows, someDAO, foo);
还有...
private HashMap<Date, Object> performQuery1(rows, foo, bar, Date, Date) {
// Some code that adds or removes elements from the hashmap "rows"
rows.put(date1, o1);
//Then return the same object
return rows;
}
所以我的问题是:这是一个很好的 java 做法吗?
rows = performQuery1(rows, foo, bar, initDate, endDate);
rows = performQuery2(rows, someDAO, foo);
要不要?
问题的核心归结为 Is Java "pass-by-reference" or "pass-by-value"?
此外,您应该 return 新创建的对象或修改参数引用的对象,但不能同时进行。有一些有用的例外
喜欢 Method chaining,但这里似乎并非如此。
当您从您的方法中 return 数据时,程序员会期望数据是新创建的对象,而通过参数引用的对象保持不变。使方法 return void(或成功代码)提示程序员该方法修改参数引用的对象而不是 returning 新对象并使您的代码更易于阅读。
这个问题确实很宽泛,或者,关注 "best practices" 部分,可能基于意见 - 但不是 主要 基于意见,因为有一个有效的论点对于这样的模式。
通常您有一个方法可以在某处获取数据,并且应该将其放入目标数据结构(在您的情况下可能是集合或地图)。
这种方法的签名有多种选择(大致符合您的示例,但可以推广这种模式)。
第一个可能是
/**
* Computes ... something, and returns the result as a map
*/
Map<Date, Result> execute(Date d0, Date d1) { ... }
第二个可能是
/**
* Computes ... something, and places the results into the
* given map
*/
void execute(Date d0, Date d1, Map<Date, Result> results) { ... }
但是,为了获得最大的灵活性,我经常参考第三种选择(您实际询问的那个):
/**
* Computes ... something, and places the results into the
* given map, which is then returned. If the given map is
* null, then a new map will be created and returned.
*/
Map<Date, Result> execute(
Date d0, Date d1, Map<Date, Result> results) { ... }
这有几个优点:
你方便让调用创建一个新地图:
Map<Date, Result> results = execute(d0, d1, null);
可以确定目标数据结构的实现。例如,如果您总是返回一张新地图,那么就无法在 HashMap
或 LinkedHashMap
之间进行选择。将目标数据结构传递给方法允许您调用
Map<Date, Result> results =
execute(d0, d1, new HashMap<Date, Result>());
或
Map<Date, Result> results =
execute(d0, d1, new LinkedHashMap<Date, Result>());
分别
您不必为每次调用创建新地图。例如,您可以创建一系列调用
Map<Date, Result> results = new HashMap<Date, Result>();
execute(d0, d1, results);
execute(d2, d3, results);
在给定的地图中累积结果
当考虑到它可以简单地模拟两种选择时,这种方法的力量可能会变得更加明显:
class DB {
// The private method that can emulate both public methods:
private Map<Date, Result> executeImpl(
Date d0, Date d1, Map<Date, Result> results);
// The implementation that returns a new map
public Map<Date, Result> execute(Date d0, Date d1) {
return executeImpl(d0, d1, null);
}
// The implementation that fills a given map
public void execute(Date d0, Date d1, Map<Date, Result> results) {
executeImpl(d0, d1, results);
}
}
旁白:Java SDK 的某些地方也使用了类似的模式。例如,在不同的应用案例中:BufferedImageOp#filter:
BufferedImage filter(BufferedImage src, BufferedImage dest)
... If the destination image is null, a BufferedImage with an appropriate ColorModel is created.
Returns: The filtered BufferedImage
我只是想问一下这是否是一个好的 java 做法,或者有更好的方法(官方方法)来做同样的事情。
首先,我需要更新一些hashmap信息:
Map<Date, Object> rows = new HashMap<Date, Object>();
这是一个 excel 行的对象,每个日期(即十月一日、十月二日等...)和一个包含该行信息的对象。
所以,为了得到这些信息,我有一些方法比如:
rows = performQuery1(rows, foo, bar, initDate, endDate);
rows = performQuery2(rows, someDAO, foo);
还有...
private HashMap<Date, Object> performQuery1(rows, foo, bar, Date, Date) {
// Some code that adds or removes elements from the hashmap "rows"
rows.put(date1, o1);
//Then return the same object
return rows;
}
所以我的问题是:这是一个很好的 java 做法吗?
rows = performQuery1(rows, foo, bar, initDate, endDate);
rows = performQuery2(rows, someDAO, foo);
要不要?
问题的核心归结为 Is Java "pass-by-reference" or "pass-by-value"?
此外,您应该 return 新创建的对象或修改参数引用的对象,但不能同时进行。有一些有用的例外 喜欢 Method chaining,但这里似乎并非如此。
当您从您的方法中 return 数据时,程序员会期望数据是新创建的对象,而通过参数引用的对象保持不变。使方法 return void(或成功代码)提示程序员该方法修改参数引用的对象而不是 returning 新对象并使您的代码更易于阅读。
这个问题确实很宽泛,或者,关注 "best practices" 部分,可能基于意见 - 但不是 主要 基于意见,因为有一个有效的论点对于这样的模式。
通常您有一个方法可以在某处获取数据,并且应该将其放入目标数据结构(在您的情况下可能是集合或地图)。
这种方法的签名有多种选择(大致符合您的示例,但可以推广这种模式)。
第一个可能是
/**
* Computes ... something, and returns the result as a map
*/
Map<Date, Result> execute(Date d0, Date d1) { ... }
第二个可能是
/**
* Computes ... something, and places the results into the
* given map
*/
void execute(Date d0, Date d1, Map<Date, Result> results) { ... }
但是,为了获得最大的灵活性,我经常参考第三种选择(您实际询问的那个):
/**
* Computes ... something, and places the results into the
* given map, which is then returned. If the given map is
* null, then a new map will be created and returned.
*/
Map<Date, Result> execute(
Date d0, Date d1, Map<Date, Result> results) { ... }
这有几个优点:
你方便让调用创建一个新地图:
Map<Date, Result> results = execute(d0, d1, null);
可以确定目标数据结构的实现。例如,如果您总是返回一张新地图,那么就无法在
HashMap
或LinkedHashMap
之间进行选择。将目标数据结构传递给方法允许您调用Map<Date, Result> results = execute(d0, d1, new HashMap<Date, Result>());
或
Map<Date, Result> results = execute(d0, d1, new LinkedHashMap<Date, Result>());
分别
您不必为每次调用创建新地图。例如,您可以创建一系列调用
Map<Date, Result> results = new HashMap<Date, Result>(); execute(d0, d1, results); execute(d2, d3, results);
在给定的地图中累积结果
当考虑到它可以简单地模拟两种选择时,这种方法的力量可能会变得更加明显:
class DB {
// The private method that can emulate both public methods:
private Map<Date, Result> executeImpl(
Date d0, Date d1, Map<Date, Result> results);
// The implementation that returns a new map
public Map<Date, Result> execute(Date d0, Date d1) {
return executeImpl(d0, d1, null);
}
// The implementation that fills a given map
public void execute(Date d0, Date d1, Map<Date, Result> results) {
executeImpl(d0, d1, results);
}
}
旁白:Java SDK 的某些地方也使用了类似的模式。例如,在不同的应用案例中:BufferedImageOp#filter:
BufferedImage filter(BufferedImage src, BufferedImage dest)
... If the destination image is null, a BufferedImage with an appropriate ColorModel is created.
Returns: The filtered BufferedImage