【问题标题】:Is it good practice to use Exception to prevent class from being instantiated with unwanted parameter使用 Exception 来防止使用不需要的参数实例化类是一种好习惯吗
【发布时间】:2020-07-20 21:56:49
【问题描述】:

我是 Java 新手。我写了一个名为QueryCondition的类,用来表示SQL命令中的查询条件,比如id > 5bankBalance < 100等。显然,像这样的查询条件需要有两个操作数,所以在QueryCondition 的构造函数我检查空操作数或空操作数,如果是这种情况则抛出异常。这是好的做法吗?

public class QueryCondition
{
  public enum Comparator
  {
    smallerThan,
    smallerThanOrEqualTo,
    largerThan,
    largerThanOrEqualTo,
    equals,
    doesNotEqual
  }

  private final String _leftOp;
  private final String _rightOp;
  private final Comparator _comp;
  public QueryCondition( String leftOperand, Comparator compare, String rightOperand ) throws Exception
  {
    if( leftOperand == null || leftOperand.isEmpty() ||
        rightOperand == null || rightOperand.isEmpty() )
    {
      throw new Exception("QueryCondition cannot be constructed with empty operands.");
    }
    
    _leftOp = leftOperand;
    _rightOp = rightOperand;
    _comp = compare;
  }
  
}

【问题讨论】:

  • 这取决于你想在抛出异常时如何处理它。您是否打算在调用 QueryCondition 类的地方处理它?还是在适当的位置处理错误并从那里响应用户会更好吗?这些是你必须自己考虑的事情。
  • 根据你想要做什么,你总是可以设置它们的默认值以防它们为空而不是抛出Exception。虽然,如果您想继续处理异常,我建议您创建一个个性化的异常并使用该异常。即QueryException
  • @Fullslack.dev 我想让异常向上传播并让它终止程序,因为这会告诉程序员他们使用 QueryCondition 的方式有问题,这应该会有所帮助他们更正了他们的代码。这是好的做法吗?
  • IMO,这是可以接受的。但是,有人可能会争辩说,如果您在上游设置保护措施,以便在实例化查询条件对象之前所需的参数不为空,那么您的情况会更好。如果这与您的输入验证器相关,那么我说 OK。
  • 如果你想让异常向上传播,我只能同意 NeoChiri 和 Hulk 继续使用选择的路径。简而言之:是的,这对您的用例来说是一种很好的做法。

标签: java exception


【解决方案1】:

是的,在构造函数中绝对推荐这种前置条件检查。构造函数负责建立类的不变量。由于构造函数除了抛出异常之外没有任何其他方式来表示失败,因此在大多数情况下,这是唯一(也是正确)要做的事情。

抛出哪种类型的Exception取决于你,但目前最惯用的方式是NullPointerException用于空参数,IllegalArgumentException用于其他非法值。

标准库中甚至还内置了一些支持: Objects.requireNonNull 允许您将空检查编写为

public QueryCondition( String leftOperand, Comparator compare, String rightOperand )
{
    _leftOp = Objects.requireNonNull(leftOperand, "left operand null");
    _rightOp = Objects.requireNonNull(rightOperand, "right operand null");
    _comp = Objects.requireNonNull(compare, "compare null");
}

不过,这不会检查是否为空。如果第一个参数是null,它会抛出一个NullPointerException,并将消息作为第二个参数给出。

一些库为此类检查提供额外的实用功能(例如apache commons StringUtils

【讨论】:

    【解决方案2】:

    这取决于如何构造这些对象。这些保护习惯中的许多都来自 C/C++ 时代,当时一个错误的参数可能会引发令人困惑的内存转储。使用 VM,故障报告通常更清晰。

    在您的情况下,我不会检查字符串,但会分配 Comparator 值(我认为这是您真正想要的),以便真正正确创建对象。如果要从字符串进行转换,我通常会添加一个静态工厂方法,将所有错误检查分离出来,留下一个最小的构造函数。

    还有一点,Java 中不需要前导下划线。这是易碎语言和 ascii 终端留下的另一个习惯。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-18
      • 2017-06-14
      • 1970-01-01
      • 2017-11-23
      相关资源
      最近更新 更多