返回里面只是尝试

时间:2019-03-09 16:09:03

标签: java try-catch

我想问您关于如何最好地管理这种情况的建议:

public Unit createUnit(final int unitLevel) {
    final List<String> widgetClassNames = getUnitsClasses();
    try {
        return (Unit) Class.forName(widgetClassNames.get(unitLevel))
        .getConstructor(Player.class).newInstance(getOwner().get());
    } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
            | NoSuchMethodException | SecurityException | ClassNotFoundException e) {
        e.printStackTrace();
    }
    return null;

}

此方法创建一个单元并返回它,但我不喜欢在发生异常的情况下我返回return null的事实。 我该怎么解决?

谢谢!

2 个答案:

答案 0 :(得分:4)

创建一个合适的新Exception,它可以管理自定义数据,例如输入unitLevel的值。

public class UnitCreationException extends Exception {
   ...

   // Package-private constructor.
   // Don't expose too much to the outer world
   UnitCreationException(
        final String message,
        final int unitLevel,
        final Throwable cause) { ... }
}

就地捕获Exception,记录您认为可能是有用的信息,这些信息只能在那时才能访问

public Unit createUnit(final int unitLevel) throws UnitCreationException {
    final List<String> widgetClassNames = getUnitsClasses();

    try {
        return (Unit) Class.forName(widgetClassNames.get(unitLevel))
                           .getConstructor(Player.class)
                           .newInstance(getOwner().get());
    } catch (InstantiationException 
            | IllegalAccessException 
            | IllegalArgumentException 
            | InvocationTargetException
            | NoSuchMethodException 
            | SecurityException 
            | ClassNotFoundException e) {
        // Do not log the Exception stack-trace here, you'll do that
        // at a hihger level
        logger.error("Error message");

        // Re-throw your custom and more meaningful Exception
        throw new UnitCreationException("Error message", unitLevel, e);
    }
}

在更高级别上,您将被迫抓住UnitCreationException

try {
   final Unit unit = createUnit(10);
} catch (final UnitCreationException e) {
   // Here you can log the Exception stack-trace
   logger.error("Error message", e);

   // Do something with the information contained in the custom Exception
   final int erroredUnitLevel = e.getUnitLevel();
   ...
}

一直以来,关于检查的Exception s vs RuntimeException s一直存在争议。我觉得这是一个经过检查的好用例,尤其是如果它是可以供多个客户端使用的库的一部分时。

您希望能够从这样的错误中以某种方式恢复,而不必停止整个应用程序(也许使用重试逻辑)。


我目睹了开发人员使用Optional<T>作为返回类型,只是为了避免使用null。这会产生适得其反的作用,因为您丢失了错误的实际原因,并且无法对它自己的分支(catch分支)中的错误做出反应

最终,Java为您提供了一种自定义Exception的方法,因此请使用此功能。

答案 1 :(得分:0)

最重要的是,您的呼叫者会获得createUnit()呼叫失败的信息。您已经说过null是一个糟糕的选择,我完全同意。

最好的方法是向呼叫者抛出一个异常,但是哪一个呢?

  • 原来的一个?

  • 还是新创建的一个?

我们应该考虑哪些方面?

  • 如果使用(无效的)错误处理行使代码混乱,则代码的可读性会降低。相反,您应该专注于您真正想做的事情-这很复杂。因此,应该删除在不牺牲鲁棒性的情况下可以避免的任何try / catch / throw。
  • 您的呼叫者需要呼叫失败的信息,这就是异常的含义,因此他应该收到一个信息。
  • 一个问题只应在某个顶级级别或服务边界上记录一次。为了支持这一点,该异常应包含用于以后的问题分析的信息。 Java系统异常已经包含了大量有用的信息,但是有时您想添加更多上下文信息。不需要记录较低级别的错误。
  • 调用方是否会编写取决于异常类型的代码,即对不同的异常类型尝试/捕获具有不同反应的块?他还能做到吗?他是否可以/应该足够了解您方法的内部工作原理,从而知道在这种或那种例外情况下该怎么做?通常不会。因此,异常类通常无关紧要。
  • 应用程序最终将如何通知用户某些功能失败?您的例外情况可以帮助完成该任务吗,例如通过提供适当的消息?但是您知道哪种措辞可能适合您的呼叫者的申请吗?因此,我怀疑您在这里会有所帮助。

因此,我看到的将较低级别的异常包装在较高级别的异常中的唯一原因是,如果要添加对日志记录有用的上下文信息(或者某些固定方法签名迫使您转换原始异常)