【问题标题】:Built-in exception length shorter than expected?内置异常长度比预期短?
【发布时间】:2020-04-06 08:42:14
【问题描述】:

我检查了 JDK 中的所有内置异常,当大小超过预期长度时,我只找到 SizeLimitExceededException。但是,如果我想在大小限制低于预期长度时抛出异常,没有我可以调用的内置异常类吗?

更新:

SSN 为 9 位长度。如果输入的 SSN 小于 9 位长度,那么我想抛出这个异常。

【问题讨论】:

  • 如果某些内容低于某个限制,我不确定引发异常的原因,但您始终可以创建自己的类。
  • 没有理由不创建自己的异常类。
  • @Marvin 我没有看到 JDK 开箱即用的“SizeLimitExceededException”的任何原因,但不是“SizeLimitBelowException”之类的东西。 JDK应该有的,而不是我们自己创建的。
  • 出现这样的异常有什么意义? JDK 应该为常见和合理的用例和SizeLimitBelowException 提供内置类,我也没有看到。您想详细说明和澄清您的情况吗?
  • @Marvin 我的问题很简单,为什么 JDK 现在有 'SizeLimitExceededException' 而没有像 'SizeLimitBelowException' 这样的东西?

标签: java exception


【解决方案1】:

虽然使用合适的例外是一种很好的做法,并且您应该花一些时间来寻找合适的例外(就像您所做的那样),但通常也没有必要过度使用它。

在你的例子中,如果你只是抛出一个new IllegalArgumentException("SSN is only of length <X> but length 9 is required"),我会认为它完全没问题。它将使执行失败并为您提供有意义的堆栈跟踪。

请注意,将异常用于控制流被视为bad practice。所以请永远不要使用类似的东西

try {
    person.setSSN(ssn);
catch (SSNTooShortException e) {
    println("SSN too short! Please try again");
}

而是使用自定义验证器在设置 SSN 之前对其进行检查,并且仅使用异常来防止编程错误。

if (!SSNFormat.matches(ssn)) { // <-- whoops condition is inverted
    person.setSSN(ssn);
}

希望这个 sn-p 很快会在您的(单元)测试中失败,并且您会知道您的编程逻辑有缺陷。

当然,根据您的应用程序,您可以并且应该使用众多验证器框架之一(例如,查看Hibernate's constraints,但几乎所有大型框架都支持一个或一个验证器,而不是使用您的自定义验证器)另一种形式)。

【讨论】:

    【解决方案2】:

    假设有一个内置的 JDK SizeLimitSubceededException(我刚刚了解到 subceeded 与超出的相反)。检查 SSN 长度的代码是否会抛出一个异常 - SizeLimitExceededException - 如果大小超过预期大小,以及另一个异常 - SizeLimitSubceededException - 如果大小低于预期大小?

    这会很尴尬:

    1. 您必须在方法的throws 子句中指定这两个异常(假设SizeLimitSubceededException 将是一个检查异常,与SizeLimitExceededException 相同)。
    2. 方法的调用者必须同时处理这两个异常。

    如果大小正确,但有其他错误怎么办?例如,SNN 包含非数字字符?你会为此抛出第三个异常吗?

    我的意思是,最好从设置 SSN 的方法中抛出单一类型的异常。

    如果您希望这是一个已检查的异常(我建议这样做,以强制调用者处理它),我建议定义您自己的自定义异常 - 也许是InvalidSSNException。此异常可以有一个带有多个参数的构造函数 - 其中一个是无效的 SSN,另一个可能是 boolean,它指示异常是否由于长度不正确而引发。

    然后您的自定义异常可以生成与失败原因相匹配的错误消息:

    1. 如果输入的 SSN 长度错误(不管是太长还是太短都没有关系),消息将指定预期长度 (9)。

    2. 如果输入的 SSN 长度正确,消息将指定有效字符(仅限数字)。

    例子:

    class Person {
    
        ...
    
        public setSSN (String ssn) throws InvalidSSNException
        {
            if (ssn == null) {
                throw new InvalidSSNException (ssn, false);
            }
            if (ssn.length() != 9) {
                // exception thrown as a result of invalid length
                throw new InvalidSSNException (ssn, true);
            }
            for (char c : ssn.toCharArray()) {
                if (c < '0' || c > '9') {
                    // exception thrown as a result of invalid character
                    throw new InvalidSSNException (ssn, false);
                }
            }
            this.ssn = ssn;
        }
        ...
    
    }
    

    【讨论】:

      【解决方案3】:

      也许你想要 IndexOutOfBoundsException 之类的东西。抛出它表示某种数据的索引超出范围。 https://docs.oracle.com/javase/7/docs/api/java/lang/IndexOutOfBoundsException.html

      【讨论】:

      • IndexOutOfBoundsException 不是最合适的;当您访问 SSN 字符串的 9. 字符时,它会由字符串本身抛出,但它太短了。
      【解决方案4】:

      你可以创建一个异常

      public class UnderBottomException extends Exception {
        public UnderBottomException(int dim, int param) {
            super();
            System.out.println("you entered a length of : " + dim + " whereas the minimum length expected is : " + param);
        }
      }
      

      这个异常可以在你的 POJO 中以这种方式实现:

      public class Register {
        private int[] registre;
        private int minRange = 9;
      
        public Register(int[] parametre) throws UnderBottomException {
          if (parametre.length < this.minRange) {
              throw new UnderBottomException(parametre.length, this.minRange);
          }
          else {  
              this.registre = new int[parametre.length];
              for (int i = 0 ; i < this.registre.length; i++)
                  this.registre[i] = parametre[i];
          }
        }
      
        public int[] getRegistre() {
          return registre;
        }
      
        public int getMinRange() {
          return minRange;
        }
      }
      

      最后你使用你的对象捕获异常:

      public class Main {
        public static void main(String[] args) {
          int[] a = {1,2,3,4,5,6,7,8};
          try {
              Register monRegistre = new Register(a);
              System.out.println("Nickel le sous registre de rang 2 = " + monRegistre.getRegistre()[1]);
          }
          catch(UnderBottomException e) {
          }
        }
      }
      

      输出: you entered a length of : 8 whereas the minimum length expected is : 9

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-27
        • 2017-08-12
        • 1970-01-01
        • 1970-01-01
        • 2014-07-13
        • 1970-01-01
        • 2015-06-29
        • 2011-03-25
        相关资源
        最近更新 更多