有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java,如果我想从函数返回不同的类型呢?

public WHATTOWRITEHERE test()
{
    try
    {
        transaction.begin();
        code which may trigger exception
        transaction.commit();
        return true;
    }
    catch (javax.script.ScriptException ex)
    {
        transaction.rollback();
        return ex.getMessage();
    }
}

上面的代码打算做一些事情,如果它正常,那么返回true。如果没有(发生错误),应该返回这个错误消息string。它可以通过Php实现,但不能通过Java实现

编辑:expection不能出去,必须在这里处理


共 (6) 个答案

  1. # 1 楼答案

    如果您坚持,您可以返回Object。在这种情况下,true将自动装箱到Boolean.TRUE。当然不建议这样做,这会给调用者带来一些额外的麻烦,让他们弄清楚返回的对象是String还是Boolean。更糟糕的是,调用方不能保证返回类型仅限于上述两种,但还应该考虑到它可能是另一个类

    更好的选择取决于情况,所以我可能无法告诉你什么是最好的。我想到了几个想法,但请不要不加批判地使用:(1)返回String,并在成功时返回null,而不是true。(2) 设计自己的返程舱;例如,它可能同时包含布尔值和消息字符串

  2. # 2 楼答案

    不要退回任何东西。就在你退后re-throw the original exception

    public void test()
    {
        try
        {
            transaction.begin();
            code which may trigger exception
            transaction.commit();
        }
        catch (javax.script.ScriptException ex)
        {
            transaction.rollback();
            throw ex;     // re-throw the original exception
        }
    }
    
  3. # 3 楼答案

    1. 在您的情况下,异常可能应该被使用,而不是隐藏。这不是一个结果,而是一个错误。了解如何在事务中处理异常

    2. 函数式编程的粉丝们会提倡一种类似于Monad的结构,正如你可以在Java8的Optional<T>API中找到的那样

      也就是说,您可以返回Optional<String>,并在成功时将其置为未设置状态(如果您没有return falsereturn true

    3. 为了清晰起见,最好使用自定义类构建类似的内容:

      interface Result {}
      class BooleanResult implements Result {
        boolean result;
        public boolean getResult() { return result; }
      }
      class ErrorResult implements Result {
        Exception cause;
        public Exception getCause() { return cause; }
      }
      
    4. 可以用null值模拟Optional(如果只有一个布尔结果)。成功后,返回null。非空值表示错误

      String perform() { 
        try{
          ...
          return null; // No error
        } except(Exception e) { // bad code style
          return e.getMessage(); // Pray this is never null
        }
      }
      
      String err = perform();
      if (err != null) { throw up; }
      

      类似的API在旧的C库中相当常见。除0之外的任何返回值都是错误代码。成功后,结果将写入方法调用时提供的指针

    5. 你可以使用Object

      public Object perform() {...}
      
      Object o = perform();
      if (o instanceof Boolean) { ...
      

      这是80年代的编程风格这就是PHP所做的,所以它实际上在Java中是可能的!这是糟糕的,因为它不是lpnger类型安全的。这是最糟糕的选择

    我希望你能试试。,3., 2., 4., 5. 在这个偏好中。或者更好的是,只考虑选项1和3。

    至于选项1。你真的应该学会如何使用资源。您的事务资源

    正确完成后,您的代码将如下所示:

    try(Transaction a = connection.newTransaction()) {
      doSomethingThatMayFail(a);
      a.commit();
    } // No except here, let try handle this properly
    

    如果发生异常,Java将调用a.close()甚至。然后它会向上抛出异常。Sour事务类应该有这样的代码来处理回滚:

    public void close() {
      if (!committed) rollback();
    }
    

    这是最优雅的最短的安全使用的方法,因为Java确保了close()的调用抛出异常,然后正确处理它。你上面展示的代码是反模式的,并且非常容易出错

  4. # 4 楼答案

    不能返回多个类型,但可以重新设计,这样就不必返回。一些可能性:

    1. 不要返回错误消息。而是抛出或重新抛出异常,并让调用方处理它
    2. 创建一些可以封装成功和错误状态以及所有相关信息的类,并返回该类的实例

    我建议选择1。您已经在处理一个异常,您可以看到它在错误处理中的作用。没有理由让它停在那里,处理任何本地清理,然后让它继续向来电者报告


    现在我回到键盘前,一些仓促构建的示例只是为了说明概念,而不是详尽无遗或必须逐字使用:

    清理然后重新清理:

    public boolean test () throws javax.script.ScriptException {
        try {
            transaction.begin();
            ...
            transaction.commit();
            return true;
        } catch (javax.script.ScriptException ex) {
            transaction.rollback();
            throw ex;
        }
    }
    

    清理,然后根据需要重新显示不同的异常类型:

    public boolean test () throws MyGreatException {
        try {
            transaction.begin();
            ...
            transaction.commit();
            return true;
        } catch (javax.script.ScriptException ex) {
            transaction.rollback();
            throw new MyGreatException(ex);
        }
    }
    

    返回一个提供状态信息的对象(这只是一个简单的例子):

    public class TransactionResult {
    
        private final boolean failed;
        private final String reason;
    
        /** Construct a result that represents a successful transaction. */
        public TransactionResult () { 
            failed = false; 
            reason = null;
        }
    
        /** Construct a result that represents a failed transaction with a reason. */
        public TransactionResult (String failedReason) {
            failed = true;
            reason = failedReason;
        }
    
        public boolean isFailed () {
            return failed;
        }
    
        public String getReason () {
            return reason;
        }
    
    }
    

    然后:

    public TransactionResult test () {
        TransactionResult result;
        try {
            transaction.begin();
            ...
            transaction.commit();
            result = new TransactionResult();
        } catch (javax.script.ScriptException ex) {
            transaction.rollback();
            result = new TransactionResult(ex.getMessage());
        }
        return result;
    }
    

    等等

  5. # 5 楼答案

    Exceptions can't go outside, it has to be handled here.

    我必须说,这种限制只会使界面更难使用。假设您希望返回一些内容,以便调用方检查此方法中是否发生异常,而调用方无论如何都可以忽略返回的值。所以我想你应该给打电话的人一些灵活性:如果可能的话,他/她不需要担心最终结果。但是,使用异常方法,调用方仍然可以使用空(不推荐)catch子句来实现这一点

    例外是这里最好的方法。除非“外部”环境不支持异常。然后你别无选择,只能在Scala中想出类似Try的东西

  6. # 6 楼答案

    难看的解决方法但是如果你真的想这么做,你可以定义一个Helper类来包装状态和错误消息,但是我更喜欢@JsonC的方法

    // Helper class 
    class Pair<First,Second>{
        private First first;
        private Second second;
        Pair(First first,Second second){ 
            this.first = first;
            this.second = second; 
        } 
        public First getFirst(){ return this.first; } 
        public First getSecond(){ return this.second; }
    }
    
    // Function returning two types
    public Pair<boolean,String> returnSomething(){
        try {
           return new Pair<boolean,String>(true,null);
        }catch(Exception e){
           return new Pair<boolean,String>(false,e.getMessage());
        }
    }
    
    // Calling this method would look like this
    Pair<String,boolean> result = returnSomething();
    
    // Retrieve status 
    boolean status = result.getFirst();
    
    // Retrieve error message (This is null if an exception was caught!)
    
    String errorMessage = result.getSecond();