内置异常长度比预期短?
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
【讨论】:
以上是关于内置异常长度比预期短?的主要内容,如果未能解决你的问题,请参考以下文章
如何修复 Invariant Violation:元素类型无效:预期为字符串(对于内置组件)