在IndexOutOfBoundsException异常上返回什么?

use*_*441 4 java

我有以下方法

private ArrayList<User> allUsers = new ArrayList<User>();

public User getUser(int index) {
    try {
        return allUsers.get(index);
    }
    catch(IndexOutOfBoundsException e) {
        // What should I return here?? Say that you want index 0 and no User
        // exists in the ArrayList allUsers, what should I then return? The
        // method needs a User to be returned 
    }
}
Run Code Online (Sandbox Code Playgroud)

而且我不确定该怎么做,我确信这是一个简单的解决方法,但我应该在catch块中返回什么?Eclipse抱怨User必须返回.

a C*_*CVn 15

我的一般意见是你永远不应该抓住一个你不知道如何处理的例外.特别是在这种情况下,既然IndexOutOfBoundsException是a RuntimeException,因此不需要被捕获 - 你也可以让它在调用堆栈中向上传播.调用者通过列表索引要求一个对象,因此可能想知道要求哪个索引 - 然后,抛出或允许抛出的IndexOutOfBoundsException传播似乎是完全自然的.

唯一明显的选择是吞下异常return null,但是当没有合理的返回值时,我真的不喜欢这种方法来解决调用者的这种公然错误.您还可以返回一个特殊User实例(请参阅null对象模式),但即使这样也不能免除调用者检查返回内容的责任.取决于接口和User这种检查的实现可能是微不足道的,但它仍然需要在某处完成.

如果你想清楚该方法可以抛出异常,那就这样说:

public User getUser(int index) throws IndexOutOfBoundsException { ... }
Run Code Online (Sandbox Code Playgroud)

或者像@ Bela Vizer建议的那样,将它包装在IllegalArgumentException(也是RuntimeException)中.

正如@ lc指出的那样.,在尝试访问对象之前,最好首先检查对象是否存在.处理您期望的错误情况,而不是依赖于get()方法调用来抛出异常.您应该仍然清楚该方法可能抛出这样的异常这一事实,但是,例如,如果在检查和返回之间修改了集合.使用多核CPU上的多线程软件,已经知道发生了一些奇怪的事情.


lc.*_*lc. 11

问自己一个问题:"如果你想要索引0并且没有用户存在,你应该返回什么?" 并回答你的回答.

如果你没有答案,你应该重新抛出异常或者不是首先捕获它.

请注意,通常情况下,答案是返回null,如果要求不存在的用户是可接受的行为.


旁注:通常认为"良好做法"不依赖于捕获异常,而是首先测试错误情况.在你的情况下,你首先尝试get一个无效的对象索引,然后在getter爆炸时做出反应.相反,我建议首先测试index参数(确保它至少为零且小于长度allUsers),如果测试失败则返回null或抛出自己的异常.