Is there a standard java exception class that means “The object was not found”?

那年仲夏 提交于 2019-11-28 21:01:26

Do you know if there is a standard exception that can be used here?

There are a couple of exceptions that could be used (e.g. NoSuchElementException or IllegalArgumentException) but the answer really depends on the semantics that you intend to convey:

  • NoSuchElementException tends to be used when you are stepping through an sequence or enumeration, where what you have here is a lookup.

  • IllegalArgumentException tends to imply that the argument is in error, but in this case, it could be that the assumptions of the caller are incorrect, or something that is specific to the application logic.

  • A custom exception allows you to say (in the javadocs) exactly what the exception means. You can also declare it to be checked ... if that it appropriate.

(But don't be tempted to use UnknownUserException. That would be horribly wrong; read the javadoc!)


It is also worth considering returning null, especially if lookup failure is likely to be a fairly common (non-exceptional) event in your application. However, the downside of returning null is that the caller needs to check for null or risk unexpected NullPointerExceptions. Indeed, I would argue that over-use of null is worse than over-use of exceptions. The former can result in unreliable applications, whereas the latter is "only" bad for performance.

For Java 8 and onwards, returning an Optional would be a cleaner choice than returning a null.


In these things, it is important to look beyond the dogmas, and make up your mind based on what the actual context requires.

Exceptions are created to mark exceptional behaviour. In my opinion, object not found situation is not exceptional. I would rewrite your method to return null, if user is not found.

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

This is standard behaviour for many Java Collections. For example, http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#get(java.lang.Object) will return null, when no entry with specified key is in the map.

You should avoid relying on exceptions in your programms logic.

Paul

IllegalArgumentException is sometimes used here but using your own Exception is perfectly fine.

As an aside I'd recommend using a Map with String name as the key and User as the value. Iterating over the collection would then be unnecessary and it would prevent having two users with the same name in the collection. If you don't want to use a Map then at least defend against NullPointerException like so:

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

It depends on your method's documented interface contract:

If your method's documentation states that the name argument must correspond to the name of an existing user, then it's appropriate to throw IllegalArgumentException if the name isn't found, because it means the caller violated the method's requirements by passing a name that doesn't correspond to a user.

If your method doesn't say that the name must correspond to an existing user, then passing an unknown name is not an error and you shouldn't throw an exception at all. Returning null would be appropriate in this situation.

Note that your findUserByName method is basically reinventing the Map.get method, which returns null if the specified key isn't found.

With Java 8, I would recommend using an Optional for this use case.

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

This also makes it very clear to the caller that the optional can be empty if the value is not found. If you really want to throw an exception, you can use orElseThrows in Optional to achieve it.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!