【问题标题】:Returning multiple values from single Java method从单个 Java 方法返回多个值
【发布时间】:2017-09-18 06:11:14
【问题描述】:

这是场景:

Java 方法public _____ submitData(Data data) 的调用者在成功处理提交的数据时需要一个确认号,如果没有,则需要一个返回码。

我可以想到三种方法来做到这一点。

方法一:

返回一个包含确认号和 ReturnCode 作为实例字段的可序列化对象。

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。)

方法二:

返回一个接口或抽象类型,并根据处理方法中数据的成功或失败创建 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;
    }

方法三:

将返回类型设为字符串并将确认编号作为字符串返回,并且对于任何错误的返回代码都会引发检查异常。这是一种久经考验的方法,它肯定会起作用,但是如果有额外的参数要返回给调用者,无论响应是成功还是失败怎么办?或者,如果有多个成功返回代码(例如 ReturnCode.OK_WRITTEN_TO_DB、ReturnCode.OK_QUEUED 等)

我想知道在这种情况下是否可以遵循最佳做法?

【问题讨论】:

  • “坏”情况是否被视为错误?在 Java 中,不必检查成功代码(如在 C 中)以明确标准情况并使用异常处理错误是惯用的。
  • @chrylis 是的,坏情况意味着无论出于何种原因都无法处理数据。 EJB 服务的使用者是一个 C 应用程序,通信通过 Web 服务进行。你认为这就是为什么他们要求提供成功代码,即使非空确认号应该是成功的证明?
  • 我会选择检查异常。保持预期的成功路径尽可能简洁易读。
  • @bez 很有可能。在这种情况下,包装代码应该负责在成语之间进行翻译。
  • @chrylis 你的意思是如果我选择选项 3,将响应转换为对客户端 C 应用程序有意义的东西是 Web 服务的责任?

标签: java return-type


【解决方案1】:

方法3是Java方式。返回值并将失败代码作为异常抛出。

方法 1 更接近于 Haskell 方式,Haskell 有办法克服您提到的限制(例如幻像类型),但对于 Java,只需按照祖先的意图坚持例外。

【讨论】:

  • 我在我的问题中更新了方法 3。如果有更多参数来返回天气成功或失败,这将如何工作?
  • @bez 在这种情况下,我要做的是结合方法 1 和 3。使用方法 1 中的类,但如果返回代码是错误,而不是返回它,将其包装在异常并抛出它。这样,返回值始终是成功,但你仍然可以处理失败try { Foo goodFoo = getFoo(); } catch(BadFooException e) { Foo badFoo = e.getFoo(); }
【解决方案2】:

我会推荐一个方法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);
        }
    }
}

更新

如果还有多个与成功案例相关联的元素,我建议您开发一个自定义 Result 对象。该服务将构建此对象并设置必要的属性,例如成功 |失败标志、错误代码等。该方法的返回值将是这个Result 对象。客户端必须从Result 对象中获取必要的信息。

【讨论】:

  • 但是如果在这两种情况下都有多个参数要返回,并且如果有多个与成功相关的返回码呢?请参阅有问题的更新方法 3。
  • @bez,如果还有多个与成功案例相关联的元素,我建议您开发一个自定义的Result 对象。该服务将构建此对象并设置必要的属性,例如成功 |失败标志、错误代码等。
  • 问题中的方法1之类的?
猜你喜欢
  • 2017-08-30
  • 2012-09-20
  • 2013-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-19
  • 2012-08-11
相关资源
最近更新 更多