是否有标准的java异常类,意味着"找不到对象"?

abl*_*abl 57 java exception standard-library

考虑以下一般形式的功能:

Foo findFoo(Collection<Foo> foos, otherarguments)
throws ObjectNotFoundException {
    for(Foo foo : foos){
        if(/* foo meets some condition*/){
            return foo;
        }
    }
    throw new ObjectNotFoundException();
}
Run Code Online (Sandbox Code Playgroud)

例如,一个具体的案例是:

User findUserByName(Collection<User> users, String name)
throws ObjectNotFoundException {
    for(User user : users){
        if(user.getName().equals(name)){
            return user;
        }
    }
    throw new ObjectNotFoundException();
}
Run Code Online (Sandbox Code Playgroud)

如果找不到对象,这些函数会抛出异常.我可以为此目的创建一个自定义异常类(在示例中ObjectNotFoundException),但我更喜欢使用现有的类.但是,我在标准java库中找不到具有此含义的任何异常类.您知道是否有可以在这里使用的标准例外吗?

Ste*_*n C 66

您知道是否有可以在这里使用的标准例外吗?

有几个例外可以使用(例如NoSuchElementExceptionIllegalArgumentException),但答案实际上取决于您打算传达的语义:

  • NoSuchElementException 当您单步执行序列或枚举时,往往会使用它,您在这里查找的是查找.

  • IllegalArgumentException 倾向于暗示参数是错误的,但在这种情况下,可能是调用者的假设是不正确的,或者是特定于应用程序逻辑的东西.

  • 自定义异常允许您(在javadocs中)确切地说出异常的含义.您也可以声明要检查 ...如果合适的话.

(但不要试图使用UnknownUserException.那将是非常错误的;阅读javadoc!)


它也值得考虑返回null,特别是如果查找失败可能是您的应用程序中相当常见(非异常)的事件. 然而,返回的缺点null是呼叫者需要检查null或冒险意外NullPointerExceptions.实际上,我认为过度使用null比过度使用异常更糟糕.前者可能导致不可靠的应用程序,而后者"仅"对性能不利.

对于Java 8及以后版本,返回Optionala将比返回a更清晰null.


在这些事情中,重要的是要超越教条,并根据实际情境需要做出决定.


MGo*_*gon 6

创建例外以标记异常行为.在我看来,未找到对象的情况并非例外.如果找不到用户,我会重写你的方法以返回null.

User findUserByName(Collection<User> users, String name) {
   for(User user : users){
       if(user.getName().equals(name)){
           return user;
      }
    }
  return null; 
}
Run Code Online (Sandbox Code Playgroud)

这是许多Java集合的标准行为.例如,当没有带有指定键的条目时,http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#get(java.lang.Object)将返回null.地图.

您应该避免依赖程序逻辑中的异常.

  • 你怎么知道这不是特例?这取决于应用程序!对不起,但除了循环逻辑之外没有办法证明缺少用户永远不是特殊情况. (15认同)
  • `null`是邪恶的 - 如果你可以使用java 8那么你应该使用`Optional`如果方法可能不返回请求的对象(因此名称).否则取决于.我更喜欢在公共方法中抛出异常并在私有中返回`null`. (7认同)
  • IMO,无论情况是否异常取决于调用该方法的代码.如果传递的集合以_should_包含元素的方式构造,那么对象不存在的事实应该有一个例外. (6认同)
  • @MGorgon - 现在你正在使用循环逻辑.*"异常不应该用于应用程序逻辑"*dogma*假定*应用程序逻辑与处理异常事件之间存在明显的区别.没有这种明显的区别.这是判断/意见的问题. (2认同)

Pau*_*aul 6

IllegalArgumentException 有时在这里使用,但使用您自己的 Exception 完全没问题。

顺便说一句,我建议使用 MapString name作为键和User值。这样就没有必要对集合进行迭代,这将防止集合中有两个具有相同名称的用户。如果您不想使用地图,那么至少要NullPointerException像这样防御:

User findUserByName(Collection<User> users, String name) throws ObjectNotFoundException
{
  if (name == null)
  {
    throw new IllegalArgumentException("name parameter must not be null");
  }
  if (users == null)
  {
    throw new IllegalArgumentException("Collection of users must not be null");
  }
  for(User user : users)
  {
    if(name.equals(user.getName()))
    {
      return user;
    }
  }
  throw new ObjectNotFoundException("Unable to locate user with name: " + name);
}
Run Code Online (Sandbox Code Playgroud)


Ala*_*ody 5

对于 Java 8,我建议在此用例中使用Optional。

Optional<User> findUserByName(Collection<User> users, String name){
    Optional<User> value = users
        .stream()
        .filter(a -> a.equals(name))
        .findFirst();
}
Run Code Online (Sandbox Code Playgroud)

这也让调用者非常清楚,如果找不到该值,可选值可以为空。如果确实想抛出异常,可以使用orElseThrowsOptional来实现。