Java 中的 True-way 解决方案:从 2 个字符串中解析 2 个数字,然后返回它们的总和

2022-08-31 12:10:21

给定代码:

public static int sum(String a, String b) /* throws? WHAT? */ {
  int x = Integer.parseInt(a); // throws NumberFormatException
  int y = Integer.parseInt(b); // throws NumberFormatException
  return x + y;
}

你能判断它是否是好的Java吗?我说的是,是一个不受检查的例外。您不必将其指定为签名的一部分。此外,据我所知,未经检查的异常的想法只是为了表明程序的实现不正确,甚至更多,捕获未经检查的异常是一个坏主意,因为它就像在运行时修复坏程序一样。NumberFormatExceptionsum()

有人可以澄清一下:

  1. 我应该指定作为方法签名的一部分。NumberFormatException
  2. 我应该定义我自己的检查异常(),在方法内部处理,并将其重新抛出为.BadDataExceptionNumberFormatExceptionBadDataException
  3. 我应该定义我自己的检查异常(),像正则表达式一样以某种方式验证两个字符串,如果它不匹配,则抛出我的。BadDataExceptionBadDataException
  4. 你的想法?

更新

想象一下,它不是一个开源框架,你应该出于某种原因使用它。你看着方法的签名,然后想 - “好吧,它永远不会抛出”。然后,有一天,你得到了一个例外。这正常吗?

更新 2

有一些评论说我的设计很糟糕。我绝对同意,但对于那些认为如果我们有好的设计,原始问题永远不会出现的人来说,这里有一个额外的问题:sum(String, String)

问题定义是这样的:您有一个数据源,其中数字存储为 s。这个来源可以是XML文件,网页,带有2个编辑框的桌面窗口,等等。String

您的目标是实现采用这 2 s 的逻辑,将它们转换为 s 并显示消息框,指出“总和是 xxx”。Stringint

无论您使用什么方法来设计/实现它,您都将拥有以下两个内部功能点

  1. 一个你转换的地方Stringint
  2. 添加 2 秒的地方int

我的原始帖子的主要问题是:

Integer.parseInt()期望传递正确的字符串。每当你传递一个坏字符串时,这意味着你的程序是不正确的(而不是“你的用户是白痴”)。你需要实现这段代码,一方面你有具有MUST语义的Integer.parseInt(),另一方面你需要对输入不正确的情况感到满意 - SHOULD语义

所以,简而言之:如果我只有MUST库,我该如何实现 SHOULD 语义


答案 1

在我看来,最好尽可能在上方处理异常逻辑。因此,我更喜欢签名

 public static int sum(int a, int b);

有了你的方法签名,我不会改变任何东西。要么你是

  • 以编程方式使用不正确的值,您可以反而验证生产者算法
  • 或从例如用户输入发送值,在这种情况下,该模块应执行验证

因此,在这种情况下,异常处理成为文档问题。


答案 2

这是一个好问题。我希望更多的人会考虑这样的事情。

恕我直言,如果您已传递垃圾参数,则抛出未经检查的异常是可以接受的。

一般来说,你不应该抛出,因为你不应该使用异常来控制程序流。例外情况适用于例外情况。您的方法的调用方可以在调用它之前知道他们的字符串是否是数字,因此传入垃圾是可以避免的,因此可以将其视为编程错误,这意味着可以抛出未经检查的异常。BadDataException

关于声明 - 这不是那么有用,因为很少有人会注意到,因为NumberFormatException被取消选中。但是,IDE可以利用它并提供正确的包装。一个好的选择是也使用javadoc,例如:throws NumberFormatExceptiontry/catch

/**
 * Adds two string numbers
 * @param a
 * @param b
 * @return
 * @throws NumberFormatException if either of a or b is not an integer
 */
public static int sum(String a, String b) throws NumberFormatException {
    int x = Integer.parseInt(a); 
    int y = Integer.parseInt(b); 
    return x + y;
}

编辑
评论者提出了有效的观点。你需要考虑如何使用它以及应用的整体设计。

如果该方法将到处使用,并且所有调用方处理问题都很重要,则将该方法声明为引发已检查的异常(强制调用方处理问题),但用块使代码混乱。try/catch

另一方面,如果我们对我们信任的数据使用此方法,则按上述方式声明它,因为它预计不会爆炸,并且您避免了基本上不必要的块的代码混乱。try/catch


推荐