【问题标题】:Java error handling, what's the correct way to handle this?Java错误处理,处理这个的正确方法是什么?
【发布时间】:2014-04-01 16:39:27
【问题描述】:

Java 中处理方法参数/内部错误的正确方法是什么?

这三种方法都做同样的事情,第二个方法略有不同,其中异常也有一个“由”部分。

请注意,在第三种方法中,每次我想退出时都必须重复返回。

还要考虑 java 中的异常处理非常昂贵(我在某处读过这个)。

谢谢!!

public static String method(String arg) {
  block: {
    if (arg == null) {
      logger.error("arg is null");
      break block;
    }
    try {
      ...  
      return "ok";
    } catch (Exception e)
      logger.error("help!", e);
    }
  }
  return "ko";
}

public static String method(String arg) {
  try {
    if (arg == null) {
      throw new Exception("arg is null");
    }
    ...
    return "ok";
  } catch (Exception e) {
    logger.error("help!", e);
    return "ko";
  }
}

public static String method(String arg) {
  String result = "ko";
  if (arg == null) {
    logger.error("arg is null");
    return result;
  }
  try {
    ..
    result = "ok";
  } catch(Exception e) {
    logger.error("help!", e);
  }
  return result;
}

编辑: 另外,在第二种方法中,您可以通过使用 RuntimeException(或自定义的)来区分内部方法错误,坏主意?

【问题讨论】:

  • 抛出异常并在几行之外用相同的方法捕获它是没有意义的。否则,第一种和第三种方案之间的选择是个人喜好之一(以及其他设计压力)。
  • 我会让方法抛出异常

标签: java exception error-handling


【解决方案1】:

我认为“正确”的方式不是这三种中的任何一种。

Java有一个只针对无效参数的异常,叫做IllegalArgumentException,实际上是一个RuntimeException,所以你不用声明它。这个想法是,如果你提供了一个非法的参数,这是调用方的一个错误,所以调用方必须捕获并处理异常。

当你的方法返回一个“非法”参数的有效结果时,IMO,你的参数并不是真的非法,所以不应该有异常,然后就没有什么可恢复的了。所以,你的代码应该是这样的

    public static String method(String arg) {
        return arg==null?"ko":"ok";
    }

这里没有例外。

现在,如果 null 参数是您必须处理的特殊情况,我认为正确的方法是在调用方处理它。在 JDK 中,您会找到显式和隐式无效参数异常的示例,例如:

显式

 * @param      s   the string to be parsed.
 * @return     a {@code Double} object holding the value
 *             represented by the {@code String} argument.
 * @throws     NumberFormatException  if the string does not contain a
 *             parsable number.
 */
public static Double valueOf(String s) throws NumberFormatException {
    return new Double(FloatingDecimal.readJavaFormatString(s).doubleValue());
} 

隐式

 * @param   uri
 *          the URI to convert
 *
 * @return  the resulting {@code Path}
 *
 * @throws  IllegalArgumentException
 *          if preconditions on the {@code uri} parameter do not hold. The
 *          format of the URI is provider specific.
   (...)
 */
public static Path get(URI uri) {
    String scheme =  uri.getScheme();
    if (scheme == null)
        throw new IllegalArgumentException("Missing scheme");
    (...)

我认为这里的整个想法是

  1. 如果 null arg 是一种异常情况,而您的方法没有预料到,那么这是一个错误,您必须在调用的方法之外从中恢复。如果被调用的方法可以处理空参数(例如返回一些有效值,例如“ko”),那么这不是一个例外情况,而只是一个有效参数,它有一个有效的结果,所以这里不需要例外。
  2. 否则,您必须抛出异常(显式或非显式)并让调用者处理它

我就是这么想的。

【讨论】:

    【解决方案2】:

    支持第一个,因为它更优雅,但第三个更清晰易读且不易出错。

    【讨论】:

    • 这只是基于意见。除此之外,应不惜一切代价避免使用标签;它们主要用于支持自动代码生成。
    【解决方案3】:

    您应该使用最容易阅读的那个。请记住,代码编写一次,多次读取。

    第三个是最容易阅读的。

    另一个非常好的规则。每种方法都存在一个条目。 最好只使用一个 return 语句。

    原因是下一个读者更容易理解代码的想法。

    有关此类问题的更多信息,您可以阅读 Clean Code http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882

    一种入口存在解决方案的建议:

    public static String method(String arg) {
        String outString = "ko";
        try {
            if (arg != null) {
                outString = "ok";
            } else {
                logger.debug("arg is null");
            }
        } catch (Exception e) {
            logger.error("Help!", e);
        }
        return outString;
    }
    

    【讨论】:

    • 所以你是在告诉我,虽然第三个更容易阅读,但第一个实现了“一次进入/一次退出”规则,而不是更好的遵循方式?
    • 其中没有一个遵循一个条目一个存在的规则。我会编纂这样的事情。我试图在评论中添加代码。但不能。所以我用新的例子更新了我的回复。
    • 你错过了 else 子句中的 return,因为它会继续执行。
    • @Seby。我不确定我是否同意你的看法。 else 不应该有任何 return 语句。 one-entry-one-exist 背后的整个想法是,你应该只存在一个。那是方法中最后的返回语句。我的建议就是这样。 outString 不必在 else 中设置。由于该字符串中已经包含负值。因此,如果您在“相同”的 JUnit 测试中运行所有这四种情况。然后你会看到他们做同样的事情。此外,只有当 arg 为空时才会运行 else。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-02
    • 2017-09-20
    • 2021-12-16
    • 2018-09-21
    • 1970-01-01
    相关资源
    最近更新 更多