java 对于从客户端Angular 来看有效的无效输入,要引发哪个异常

4si2a6ki  于 2023-01-07  发布在  Java
关注(0)|答案(6)|浏览(110)

我正在写代码来寻找两条线的交点。当两条线的斜率相等时,它们不相交。但另一方面,斜率相等的输入值是完全有效的。

public static Point calculateIntersection(Line line1, Line line2) {

    if (line1 == null || line2 == null) {
        throw new NullPointerException(" some message ");
    }

    if (line1.getConstant() == line2.getConstant()) {
        return new Point(0, line1.getConstant());
    }

    if (line1.getSlope() == line2.getSlope()) {
        throw new IllegalArgumentException("slopes are same, the lines do not intersect.");
    }

    int x = (line2.getConstant() - line1.getConstant()) / (line1.getSlope() - line2.getSlope());
    int y = line1.getSlope() * x + line1.getConstant();

    return new Point(x, y);
}

问题是抛出非法参数异常是正确的做法吗?因为输入是有效的,它不能完全说服我。
自定义异常是正确的做法吗?听起来是个不错的选择,但额外的意见会有所帮助。
谢啦,谢啦

sd2nnvve

sd2nnvve1#

问题是 * 抛出非法参数异常是正确的做法吗?*
没有单一的“正确的事情要做”,这取决于你想/需要如何“框定”这个条件;即它是一个bug,用户输入错误,还是程序应该能够处理的东西?

  • 如果两条线不相交的情况是一个明确的“bug”,那么IllegalArgumentException就可以了。这就是异常的设计目的。(注意,这是一个 unchecked 异常,所以期望它不会被捕获/恢复。
  • 如果您希望程序能够自行恢复,那么定制异常是最好的主意。这样,您可以减少代码被(比如)库方法抛出(比如)IllegalArgumentException...而不是表示“两行相交”以外的其他内容所混淆的可能性。
  • 如果您希望将这种情况作为输入验证的一部分报告给最终用户,那么一般的“验证错误”异常可能比特定的自定义异常更合适。但是,此方法看起来不像是专门用于(仅)用户输入验证的。

在某些上下文中,最好根本不抛出异常,但(IMO)这不是这些上下文中的一个。
抛出异常的替代方法是返回null或返回一个Point值,该值 * 意味着 * 调用代码“没有这样的点”。

  • 如果返回null,应用程序必须处理null情况......否则将出现NPE。
  • 没有自然的Point示例可以用来表示“不是点“1。

这并不是说你不能让这些替代方案发挥作用,只是在这种情况下,要做到这一点,* 很可能 * 需要更多的工作,而且 * 很可能 * 不会有切实的回报。
1 -我假设Pointjava.awt.Point或类似的。显然你 * 可以 * 定义和使用一个自定义的Point类,它提供了一个“no such point”示例。但是这是有代价的。你需要处理代码在一些计算中意外使用“no such point”示例的情况。你可能又回到了开始的地方;即抛出异常!

sirbozc5

sirbozc52#

这几乎肯定不会抛出异常,因为使用任意两个Line值调用这样的方法是非常有意义的,您已经适当地处理了空值。
你还非常合理地定义了类在一种定义不清的输入情况下的行为,即两条重合的“常量”(水平)线,在那里你返回那条线上x=0处的点,你应该为其他定义不清的输入情况类似地选择返回值:重合的垂直线、既不水平也不垂直的重合线以及不重合的平行线。
在我看来,最后一种情况--不重合的平行线--最自然的结果是null,反映了没有交点的事实。
然后由客户端来决定空交集是否保证异常、错误消息或任何东西。例如,提示用户要相交的线的交互式 shell 可能会打印错误消息并要求用户重试。一些更复杂的计算,例如,线性优化器试图定义其搜索的边界,如果引起平行线的约束彼此矛盾,则可能想要抛出IllegalArgumentException
当然,所有这些情况下的返回值(重合线或非重合平行线)都应该精确地记录在方法的javadoc中。

ih99xse1

ih99xse13#

我觉得你做得对你很早就发现了这个条件。要么是这样,要么人们会抱怨“你的程序有缺陷,看看这个输入数据,除以0”。
假设在99%以上的情况下不会出现这样的错误,这是一个异常条件,并且不允许声明一个已检查异常,因此未检查异常看起来确实是正确的选择。
现在,至于IllegalArgumentException是否是“好的”,它至少是描述这种情况的最接近的例外...你可以,如果你觉得你有一个更好的名字,总是创建你自己的继承RuntimeException

如果,另一方面,这种情况并不罕见,那么也许应该审查达到该函数的逻辑,以便从一开始就不遇到这种情况。

2ul0zpep

2ul0zpep4#

正如@安迪·洛瑞和@KamikazeCZ所说,这不应该是一个例外。

  • 这个 * 方法不应该关心客户端是否期望直线总是相交;它只需要费心去寻找两条线的交点----这本来是不可能发生的。

如果调用者返回一个指示没有交集的结果,那么这段代码可以决定它是否是无效输入,因为最终用户已经得到了适当的警告,或者他们可以处理(也许通过重新提示),或者抛出一个定制的异常。
那么,回到这个方法应该返回什么?某种标记值,与indexOf在集合库中返回-1的方式相同。返回null是一个合理的标记。在Java 8中,您可以返回一个Optional<Point>,以帮助提醒调用者可能没有正确的Point
你还有另外一个问题:一条直线与自身的交点是什么(从数学上讲,两条线的交点要么是点,要么是1点,要么是无限多个点。)您可能需要能够返回 * 两个 * sentinel值,这在Java中更复杂。这个方法这次可以通过说“在多个答案的情况下,这个方法可能返回其中的任何一个”来回避这种情况,或者(我可能会这样做)“...返回离原点最近的Point”。
顺便说一句,这种想法很大程度上来自单元测试的思维模式:首先定义正确的答案应该是各种极端情况下的输入,然后再启动代码,并有点承诺自己一定的返回类型等。
最后:当使用==比较getSlope()的结果时,注意浮点舍入错误。这可能是最好的方法,但仍然有问题。不过,假设(或舍入)交集为int s的方式表明,在您的问题中可能有非常特殊的约束/假设。

6g8kf2rb

6g8kf2rb6#

异常应该被用来捕捉程序流中的错误(“内部发生了什么”),而不是用来验证输入。我根本不会抛出异常。想想看,这不是“异常”的意思,因为用户输入两条斜率相等的线是完全正常的。

相关问题