内置异常长度比预期短?

Posted

技术标签:

【中文标题】内置异常长度比预期短?【英文标题】: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' 这样的东西? 【参考方案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 - 如果大小低于预期大小?

这会很尴尬:

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

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

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

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

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

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

    如果输入的 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

【讨论】:

以上是关于内置异常长度比预期短?的主要内容,如果未能解决你的问题,请参考以下文章

Javascript 基础学习常用内置对象

不变违规:元素类型无效:预期为字符串(用于内置组件)

如何修复 Invariant Violation:元素类型无效:预期为字符串(对于内置组件)

Python中的常用内置函数都有哪些呢?

Mongoose Schema 未按预期在对象的内置 Getter 中进行转换

Python基础:内置异常(未完待续)