4

我有以下方法

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 
    }
}

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

4

8 回答 8

15

我的一般意见是,您永远不应该捕获您不知道如何处理的异常。特别是在这种情况下,因为IndexOutOfBoundsExceptionis aRuntimeException并且因此不需要被捕获 - 您也可以让它在调用堆栈上传播。调用者通过列表索引请求对象,因此大概知道要请求哪个索引 - 然后,抛出或允许抛出的 IndexOutOfBoundsException 传播似乎非常自然。

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

如果您想清楚该方法可以抛出异常,只需这样说:

public User getUser(int index) throws IndexOutOfBoundsException { ... }

或者像@Bela Vizer建议的那样,将其包装在 IllegalArgumentException 中(这也是一个 RuntimeException)。

正如@lc所指出的那样,最好先自己检查对象是否存在,然后再尝试访问它。自己处理您期望的错误情况,而不是依靠get()方法调用来引发异常。但是,您仍然应该清楚该方法可能会引发此类异常的事实,例如,如果在检查和返回之间修改了集合。借助多核 CPU 上的多线程软件,已知会发生奇怪的事情。

于 2012-11-17T18:29:39.813 回答
11

问自己一个问题:“如果你想要索引 0 并且没有用户存在,你应该返回什么?” 并返回您回答的任何内容。

如果您没有答案,您应该重新抛出异常或不首先捕获它。

请注意,如果请求不存在的用户null可以接受的行为,则答案通常是返回。


旁注:通常认为“良好做法”不依赖于捕获异常,而是首先测试错误条件。在您的情况下,您首先尝试get使用无效的对象索引,然后在 getter 爆炸时做出反应。相反,我建议先测试index参数(确保它至少为零且小于 的长度allUsers),如果它未能通过测试来做某事(返回 null 或抛出您自己的异常)。

于 2012-11-17T18:28:44.807 回答
4

有很多可能性。其中一些取决于你的信念。

  • 您可以抛出 IllegalArgumentException,因为传递的参数无效。

  • 您可以抛出 IndexOutOfBoundsException。

  • 如果您想确保客户端(此方法的调用者)必须处理它,您甚至可以声明一个检查异常(定义您的异常类扩展 Exception),因为 IllegalArgumentException 和 IndexOutOfBoundsException 是运行时异常,这意味着您没有明确地准备自己。

我通常检查索引是否在范围内,如果不返回 null 并在 javadoc 中提到它可以返回 null 如果...

于 2012-11-17T18:29:16.093 回答
4

如果找不到用户,我会抛出异常。调用该方法时会捕获此异常。如果需要,您可以在此处修改代码以使用自定义异常。就像是:

public User getUser(int index) throws IndexOutOfBoundsException {
    if(index >= allUsers.size()){
        throw new IndexOutOfBoundsException("User doesn't exist");
    }
    return allUsers.get(index);
}
于 2012-11-17T18:29:53.243 回答
2

不要听 Eclipse。

你有两个选择,它们都可以是好的或坏的,这取决于具体情况。

  1. 你可以退货null
  2. 您可以重新抛出异常(或者更确切地说,根本不捕获它),要求调用方法处理它。

还有更多变体,但基本选择在上述两种之间:就地处理问题或将任务委托给调用者。

仅从该代码无法判断哪个是正确的解决方案,只有您可以知道什么更适合这种情况。

但是,无论您采取哪种选择,最好手动检查索引 ( 0<=index<allUsers.size()),而不是依赖RuntimeExceptions 来获得正常的程序行为。

于 2012-11-17T18:28:53.980 回答
2

假设index是用户输入,只需让它IndexOutOfBoundsException传播并在可以显示错误消息的位置更远地捕捉它。

事实上,您甚至可以在尝试查找做同样的事情之前index先进行验证。allUsers.size()通常应尽早验证用户输入。

于 2012-11-17T18:29:00.937 回答
2

我会返回null,但是,如果您觉得您的应用程序可能因此崩溃,您可以简单地返回一个“nobody”用户,如下所示:

return new User("nobody", ...);

并在函数之外处理这种情况。

另一种选择是抛出异常并在外部处理它。

于 2012-11-17T18:30:01.717 回答
1

你有几个选择:

  1. 返回一个null。如果用户可以合理地输入任何索引,请执行此操作
  2. 不要捕获异常。如果用户输入错误数据是完全出乎意料的,则执行此操作,换句话说,输入已被检查,因此这是导致这种情况的“编程错误”(或错误)
  3. 抛出一个检查异常。如果您认为调用代码可以并且应该处理问题,请执行此操作
于 2012-11-17T18:40:07.480 回答