返回多个值的Java方法的最佳实践?
我需要一个非静态实例方法来返回多个值。为了一个简单的例子,让我们假设它们是返回多个值的Java方法的最佳实践?,java,class,object,methods,return,Java,Class,Object,Methods,Return,我需要一个非静态实例方法来返回多个值。为了一个简单的例子,让我们假设它们是布尔成功和对象obj——但在一般情况下,它们可能更多,并且可能彼此无关。可以想出几种不同的方法来实现这一点: 解决方案1 private boolean aMethod(int aParam, Object obj) { ...set obj parameter & return value... } 解决方案2 private Pair<Boolean, Object> aMethod(int aP
布尔成功
和对象obj
——但在一般情况下,它们可能更多,并且可能彼此无关。可以想出几种不同的方法来实现这一点:
解决方案1
private boolean aMethod(int aParam, Object obj) { ...set obj parameter & return value... }
解决方案2
private Pair<Boolean, Object> aMethod(int aParam) { ...set return pair values... }
解决方案4
private class MethodReturn { // Nested class - could be a separate class instead
boolean success;
Object obj;
// ... Getters and setters omitted for brevity
}
private MethodReturn aMethod(int aParam) { ...set return object values... }
还有什么我可能错过的可能性吗?还有谁能评论一下每种方法的优缺点(理想情况下,在大多数情况下,哪种方法可能是最好的)?一般来说,我会根据具体情况选择第四种方法或地图,但如果需要返回多个不相关的值,我认为您存在严重的设计问题(检查) 在特定的情况下(在您的评论之后),我肯定会使用第四种方法,使用所有必需的字段对响应进行建模。也可以使用ResponseSuccessful和ResponseFailure进行子类型划分。使用
Object[] aMethod(){
//Create and fill an array of object and return it
}
在我的程序中,如果返回的对象在逻辑上有某种关联,它们可能需要有自己的类:一个
布尔值,一个字符串可能是一个消息状态
(编辑:我看这是你的第四个解决方案)。
给你一个具体的例子:
public class TurnToken {
/**
* Number of available Quick Actions
*/
private int quickActionTimes;
/**
* Number of available Main Actions
*/
private int mainActionTimes;
[...Etcetera with setters and getters]
此类仅由两个整数组成,但它在逻辑上表示可以被视为实体本身的某个事物
编辑:我不小心取消了第一部分。如果对象不是基本体,而是逻辑关联的,则可以创建一个接口来收集它们:
public interface Adjectivable{
//If they have a commong method even better}
你的方法呢
public List<Adjectivable> myMultiReturningMethod{
List<Adjectivable> theStuffToReturn = new ArrayList<>();
Etcetera...
}
公共列表myMultiReturningMethod{
列出stufforeturn=newarraylist();
等等。。。
}
解决方案5-回调
通过回调,您甚至可以返回多个2元组:
private void aMethod(int aParam, BiConsumer<Boolean, String> callback) {
…
callback.accept(success1, msg1);
…
callback.accept(success2, msg2);
…
}
此外,您还可以按组合返回(n>2)-元组,而无需自定义类-例如,对于4-元组:
<A, B, C, D> void aMethod(int aParam, BiFunction<A, B, BiConsumer<C, D>> callback) {
callback.apply(a, b).accept(c, d);
}
aMethod(42, (a, b) -> (c, d) -> log.debug("" + a + b + c + d));
解决方案1不起作用,因为java中的字符串是不可变的
解决方案3您不能总是应用,因为您将结果保存在实例中,所以只要您需要结果,您可能也无法从该实例运行您的方法
这就给我们留下了非常相似的解决方案2和4。正如在这两种情况下一样,返回结果包装在自定义类中。如果您认为Pair
对您来说足够了,我会说,使用它,然后使用解决方案2。如果结果是固定的,您可以在这里使用enum
public Enum Status {
OK("OK"),
CREATED("Created"),
ACCEPTED("Accepted"),
NO_CONTENT("No Content"),
FORBIDDEN("Forbidden"),
NOT_FOUND("Not Found");
private final String reason;
Status(final String reasonPhrase) {
this.reason = reasonPhrase;
}
}
private Status aMethod(int aParam) {
................
return Status.OK;
}
好问题。在大多数情况下,我个人使用解决方案2。这应该在CodeReviews中移动。解决方案2和4是最不令人惊讶的,因为它们至少没有副作用,并且更清楚地说明了该方法的作用。如果您决定返回其他内容,那么解决方案4将更容易重构。我首先会质疑这种方法的必要性,因为它似乎有不止一种责任,并建议重构以避免这种情况,我习惯于引用dotnet,但Java中有吗@MarioAlexandroSantini除非OP发布了他们真正的工作代码,而不是用注释替换代码的方法框架,否则这在代码评审中是离题的。请参阅之前的参考文章到该网站。谢谢你的回答。为了稍微详细说明实际用例,SpringMVC控制器中的私有保存方法返回操作是否成功的指示以及要重定向到的页面。我可能是错的,但不要认为这违反了SRP。那么它们不是无关的,你可以在一个响应对象中对其进行建模,该对象对HTTP请求(或其中的一部分)进行建模@chrylis:这并不总是一个好的选择,例如,从函数式编程POV中,抛出异常就像跳转一样。最好使用、可选或回调来处理错误。@charlie函数管道是与标准Java代码完全不同的范例。当然,类似于承诺的回调链在这里更有意义,但这是一个不同的环境。我同意,异常应该只在例外情况下使用,而不是出于验证失败等常见原因。显然,现实世界的应用程序(和框架!)并不总是同意这一点!像这样移动数据会很麻烦,就像你移动整辆车是为了只卖一个冰淇淋一样,但是这种方法运行得很慢,很难找到答案,也很难找到解决方案1!我也不喜欢解决方案3的想法,我不确定我是否完全理解你的评论,但它是否适用,因为它是一种私人方法?(但是我认为这个解决方案可能也有并发性问题,所以我几乎不考虑它。)我想2和4之间的选择很可能归结为个人偏好,我目前倾向于4…更新:现在已经将问题改为使用对象而不是字符串来解决解决方案1问题。或者甚至将其与解决方案2结合使用:enum Status implements Pair
,然后让private Pair aMethod()
决定何时返回预定义状态,如return Status.OK
或类似于return pairOf(success,msg)的新代码代码>,视情况而定。认为此答案是指此处的示例/用例,而不是指参数可能不是枚举的一般情况。Re:解决方案2注释-您是指中的自定义Tuple2
实现吗?@SteveChambers:是,或任何其他类似的实现。但是,正如本文所解释的,函数参数也会形成一个元组,因此调用回调直接等同于返回元组。此外,接收函数可以多次调用回调函数。对于一个简单的方法来说,这是不必要的复杂。它在从线程程序和未来返回值方面很有用,但它使理解flo变得复杂
<A, B, C, D> void aMethod(int aParam, BiFunction<A, B, BiConsumer<C, D>> callback) {
callback.apply(a, b).accept(c, d);
}
aMethod(42, (a, b) -> (c, d) -> log.debug("" + a + b + c + d));
private MethodReturn aMethod(int aParam) {
…
return new MethodReturn() {
@Override
public Boolean first() { return success; }
@Override
public String second() { return msg; }
};
}
public Enum Status {
OK("OK"),
CREATED("Created"),
ACCEPTED("Accepted"),
NO_CONTENT("No Content"),
FORBIDDEN("Forbidden"),
NOT_FOUND("Not Found");
private final String reason;
Status(final String reasonPhrase) {
this.reason = reasonPhrase;
}
}
private Status aMethod(int aParam) {
................
return Status.OK;
}