从单个Java方法返回多个值
以下是场景: Java方法从单个Java方法返回多个值,java,return-type,Java,Return Type,以下是场景: Java方法public\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu submitData(数据)的 我可以想出三种方法 方法1: 返回一个可序列化的对象,其中包含确认号和返回代码作为实例字段 public class Foo { private String confirmationNumber; private ReturnC
public\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu submitData(数据)
的
我可以想出三种方法
方法1:
返回一个可序列化的对象,其中包含确认号和返回代码作为实例字段
public class Foo {
private String confirmationNumber;
private ReturnCode returnCode;
public Foo(ReturnCode returnCode) {
this(null, returnCode);
}
public Foo(String confirmationNumber, ReturnCode returnCode) {
if ((returnCode == ReturnCode.OK && confirmationNumber == null)
|| (returnCode != ReturnCode.OK && confirmationNumber != null)) {
throw new IllegalArgumentException("Bad combination of parameters.");
}
this.confirmationNumber = confirmationNumber;
this.returnCode = returnCode;
}
public enum ReturnCode {
OK, ERROR1, ERROR2, ERROR3, ERROR4, ERROR5;
}
}
这种方法的问题在于强制执行对象的正确实例化。调用代码需要知道对象创建的规则(例如,不能用ReturnCode.OK和null确认号实例化Foo)
方法2:
根据处理方法中数据的成功或失败,返回接口或抽象类型并创建Foo的变体,如下例所示:
public abstract class Foo {
public abstract String getConfirmationCode();
public abstract ReturnCode getReturnCode();
}
public class GoodFoo extends Foo {
private final String confirmationCode;
private final ReturnCode returnCode = ReturnCode.OK;
public GoodFoo(String confirmationCode) {
this.confirmationCode = confirmationCode;
}
@Override
public ReturnCode getReturnCode() {
return returnCode;
}
@Override
public String getConfirmationCode() {
return confirmationCode;
}
}
public class BadFoo extends Foo {
private final ReturnCode returnCode;
public BadFoo(ReturnCode returnCode) {
if (returnCode == ReturnCode.OK){
throw new IllegalArgumentException("BadFoo cannot have a good return code");
}
this.returnCode = returnCode;
}
@Override
public ReturnCode getReturnCode() {
return returnCode;
}
@Override
public String getConfirmationCode() {
return null;
}
方法3:
将返回类型设为字符串,并将返回确认号设为字符串,对于任何错误的返回代码,将抛出选中的异常。这是一种经过尝试和测试的方法,它肯定会工作,但是如果有额外的参数返回给调用方,不管响应是成功还是失败,该怎么办?或者如果成功有多个返回码(例如,ReturnCode.OK\u写入到\u DB,ReturnCode.OK\u排队等)
我想知道在这种情况下是否有最佳实践可以遵循?方法3是Java方式。返回值并将故障代码作为异常抛出
方法1更接近于Haskell方法,Haskell有办法克服您提到的限制(例如幻象类型),但对于Java,只需坚持使用异常,这是祖先所希望的方式。我将推荐一种方法4。如果成功,则返回确认号,但如果出现任何错误,则抛出自定义异常。使客户端负责处理异常,并在出现故障时从自定义异常对象检索代码 下面是一个例子:
public class InvalidDataException extends Exception {
public Integer errorCode;
public InvalidDataException (Integer errorCode) {
this.errorCode = errorCode;
}
}
public class ServiceClass {
public String submitData(Data data) {
//Do processing
if(error1) {
throw new InvalidDataException(100);
}
else if(error1) {
throw new InvalidDataException(200);
}
return UUID.randomUUID().toString(); //conf number
}
}
public class ClientClass {
public static void main(String[] args) {
String confNum = "";
Data data = new Data();
//Build data
ServiceClass sc = new ServiceClass();
try {
confNum = sc.submitData(data);
}
catch(InvalidDataException e) {
System.out.println("An error occurred with the code " + e.errorCode);
}
}
}
更新
如果有多个元素也与成功案例相关,我建议您开发一个定制的
结果
对象。服务将构建此对象并设置必要的属性,如成功|失败标志、错误代码和其他。方法的返回值将是这个结果
对象。客户端必须从结果
对象中获取必要的信息 “坏”案例是否被视为错误?在Java中,习惯用法是不必检查成功代码(如在C中)以明确标准大小写并使用异常进行错误处理。@chrylis是的,坏大小写意味着无论出于何种原因都无法处理数据。EJB服务的使用者是一个C应用程序,通信通过一个web服务进行。你认为这就是为什么他们要求一个成功代码,即使一个非空的确认号应该是成功的证明吗?我会选择一个选中的例外。保持预期的成功路径尽可能清晰易读。@bez这很可能。在这种情况下,包装器代码应该负责在习语之间进行翻译。@chrylis您的意思是,如果我使用选项3,web服务负责将响应转换为对客户端C应用程序有意义的内容?我在问题中更新了方法3。如果有更多的参数返回天气成功或失败,这将如何工作?@bez在这种情况下,我将结合方法1和方法3。使用方法1中的类,但是如果返回代码是错误,而不是返回它,则将其包装在异常中并抛出它。这样,返回值总是成功的,但是您仍然可以处理失败尝试{Foo goodFoo=getFoo();}catch(BadFooException e){Foo badFoo=e.getFoo();}
但是如果在这两种情况下都有多个参数要返回,并且如果有多个返回代码与成功关联,该怎么办?请参阅相关更新的方法3。@bez,如果有多个元素也与成功案例相关,我建议您开发一个自定义的结果对象。服务将构建此对象并设置必要的属性,如成功|失败标志、错误代码和其他。类似于问题中的方法1?