views:

2095

answers:

10

In Java (or any other language with checked exceptions), when creating your own exception class, how do you decide whether it should be checked or unchecked?

My instinct is to say that a checked exception would be called for in cases where the caller might be able to recover in some productive way, where as an unchecked exception would be more for unrecoverable cases, but I'd be interested in other's thoughts.

+8  A: 

From A Java Learner:

When an exception occurs, you have to either catch and handle the exception, or tell compiler that you can't handle it by declaring that your method throws that exception, then the code that uses your method will have to handle that exception (even it also may choose to declare that it throws the exception if it can't handle it).

Compiler will check that we have done one of the two things (catch, or declare). So these are called Checked exceptions. But Errors, and Runtime Exceptions are not checked for by compiler (even though you can choose to catch, or declare, it is not required). So, these two are called Unchecked exceptions.

Errors are used to represent those conditions which occur outside the application, such as crash of the system. Runtime exceptions are usually occur by fault in the application logic. You can't do anything in these situations. When runtime exception occur, you have to re-write your program code. So, these are not checked by compiler. These runtime exceptions will uncover in development, and testing period. Then we have to refactor our code to remove these errors.

Espo
A: 

The rule I use is: never use unchecked exceptions! (or when you don't see any way around it)

From the point of view of the developer using your library or the end-user using your library/application it really sucks to be confronted with an application that crashes due to an uncought exception. And counting on a catch-all is no good either.

This way the end user can still be presented with an error message, instead of the application completely disappearing.

A: 

Checked exceptions are useful for recoverable cases where you want to provide information to the caller (i.e. insufficient permissions, file not found, etc).

Unchecked exceptions are used rarely, if at all, for informing the user or programmer of serious errors or unexpected conditions during run-time. Don't throw them if you're writing code or libraries that will be used by others, as they may not be expecting your software to throw unchecked exceptions since the compiler doesn't force them to be caught or declared.

David Crow
+13  A: 

The rule I use is: never use unchecked exceptions! (or when you don't see any way around it)

There's a very strong case for the opposite: Never use checked exceptions. I'm reluctant to take sides in the debate but there seems to be a broad consensus that introducing checked exceptions was a wrong decision in hindsight. Please don't shoot the messenger and refer to those arguments.

Konrad Rudolph
+8  A: 

Here is my 'final rule of thumb'.
I use:

  • unchecked exception within the code of my method for a failure due to the caller (that involves an explicit and complete documentation)
  • checked exception for a failure due to the callee that I need to make explicit to anyone wanting to use my code

Compare to the previous answer, this is a clear rationale (upon which one can agree or disagree) for the use of one or the other (or both) kind of exceptions.


For both of those exceptions, I will create my own unchecked and checked Exception for my application (a good practice, as mentionned here), except for very common unchecked exception (like NullPointerException)

So for instance, the goal of this particular function below is to make (or get if already exist) an object,
meaning:

  • the container of the object to make/get MUST exist (responsibility of the CALLER
    => unchecked exception, AND clear javadoc comment for this called function)
  • the other parameters can not be null
    (choice of the coder to put that on the CALLER: the coder will not check for null parameter but the coder DOES DOCUMENT IT)
  • the result CAN NOT BE NULL
    (responsibility and choice of the code of the callee, choice which will be of great interest for the caller
    => checked exception because every callers MUST take a decision if the object can not be created/found, and that decision must be enforced at the compilation time: they can not use this function without having to deal with this possibility, meaning with this checked exception).

Example:


/**
 * Build a folder. <br />
 * Folder located under a Parent Folder (either RootFolder or an existing Folder)
 * @param aFolderName name of folder
 * @param aPVob project vob containing folder (MUST NOT BE NULL)
 * @param aParent parent folder containing folder 
 *        (MUST NOT BE NULL, MUST BE IN THE SAME PVOB than aPvob)
 * @param aComment comment for folder (MUST NOT BE NULL)
 * @return a new folder or an existing one
 * @throws CCException if any problems occurs during folder creation
 * @throws AssertionFailedException if aParent is not in the same PVob
 * @throws NullPointerException if aPVob or aParent or aComment is null
 */
static public Folder makeOrGetFolder(final String aFoldername, final Folder aParent,
 final IPVob aPVob, final Comment aComment) throws CCException {
 Folder aFolderRes = null;
 if (aPVob.equals(aParent.getPVob() == false) { 
    // UNCHECKED EXCEPTION because the caller failed to live up
    // to the documented entry criteria for this function
    Assert.isLegal(false, "parent Folder must be in the same PVob than " + aPVob); }

 final String ctcmd = "mkfolder " + aComment.getCommentOption() + 
  " -in " + getPNameFromRepoObject(aParent) + " " + aPVob.getFullName(aFolderName);

 final Status st = getCleartool().executeCmd(ctcmd);

 if (st.status || StringUtils.strictContains(st.message,"already exists.")) {
  aFolderRes = Folder.getFolder(aFolderName, aPVob);
 }
 else {
  // CHECKED EXCEPTION because the callee failed to respect his contract
  throw new CCException.Error("Unable to make/get folder '" + aFolderName + "'");
 }
 return aFolderRes;
}
VonC
A: 

I patched javac to make all exceptions unchecked.

Joshua
Wow people really don't like this answer.
Joshua
+6  A: 

On any large enough system, with many layers, checked exception are useless as, anyway, you need an architectural level strategy to handle how the exception will be handled (use a fault barrier)

With checked exceptions your error handling stategy is micro-managed and its unbearable on any large system.

Most of the time you don't know if an error is "recoverable" because you don't know in what layer the caller of your API is located.

Let's say that I create a StringToInt API that converts the string representation of an integer to an Int. Must I throw a checked exception if the API is called with the "foo" string ? Is it recoverable ? I don't know because in his layer the caller of my StringToInt API may already have validated the input, and if this exception is thrown it's either a bug or a data corruption and it isn't recoverable for this layer.

In this case the caller of the API does not want to catch the exception. He only wants to let the exception "bubble up". If I chose a checked exception, this caller will have plenty of useless catch block only to artificially rethrow the exception.

What is recoverable depends most of the time on the caller of the API, not on the writter of the API. An API should not use checked exceptions as only unchecked exceptions allows to choose to either catch or ignore an exception.

Stephane
+6  A: 

It's not just a matter of the ability to recover from the exception. What matter most, in my opinion, is whether the caller is interested in catching the exception or not.

If you write a library to be used elsewhere, or a lower-level layer in your application, ask yourself if the caller is interested in catching (knowing about) your exception. If he is not, then use an unchecked exception, so you don't burden him unnecessarily.

This is the philosophy used by many frameworks. Spring and hibernate, in particularly, come to mind - they convert known checked exception to unchecked exception precisely because checked exceptions are overused in Java. One example that I can think of is the JSONException from json.org, which is a checked exception and is mostly annoying - it should be unchecked, but the developer simply haven't thought it through.

By the way, most of the time the caller's interest in the exception is directly correlated to the ability to recover from the exception, but that is not always the case.

Yoni
+6  A: 

You're correct.

Unchecked exceptions are used to let the system fail fast which is a good thing. You should clearly state what is your method expecting in order to work properly. This way you can validate the input only once.

For instance:

/**
 * @params operation - The operation to execute.
 * @throws IllegalArgumentException if the operation is "exit"
 */
 public final void execute( String operation ) {
     if( "exit".equals(operation)){
          throw new IllegalArgumentException("I told you not to...");
     }
     this.operation = operation; 
     .....  
 }
 private void secretCode(){
      // we perform the operation.
      // at this point the opreation was validated already.
      // so we don't worry that operation is "exit"
      .....  
 }

Just to put an example. The point is, if the system fails fast, then you'll know where and why it did fail. You'll get an stacktrace like:

 IllegalArgumentException: I told you not to use "exit" 
 at some.package.AClass.execute(Aclass.java:5)
 at otherPackage.Otherlass.delegateTheWork(OtherClass.java:4569)
 ar ......

And you'll know what happened. The OtherClass in the "delegateTheWork" method ( at line 4569 ) called your class with the "exit" value, even when it shouldn't etc.

Otherwise you would have to sprinkle validations all over your code and that's error prone. Plus, sometimes it is hard to track what went wrong and you may expect hours of frustrating debugging

Same thing happens with NullPointerExceptions. If you have a 700 lines class with some 15 methods, that uses 30 attributes and none of them can be null, instead of validating in each of those methods for nullability you could make all those attributes read-only and validate them in the constructor or factory method.

 public static MyClass createInstane( Object data1, Object data2 /* etc */ ){ 
      if( data1 == null ){ throw NullPointerException( "data1 cannot be null"); }

  }


  // the rest of the methods don't validate data1 anymore.
  public void method1(){ // don't worry, nothing is null 
      ....
  }
  public void method2(){ // don't worry, nothing is null 
      ....
  }
  public void method3(){ // don't worry, nothing is null 
      ....
  }

Checked exceptions Are useful when the programmer ( you or your co-workers ) did everything right, validated the input, ran tests, and all the code is perfect, but the code connects to a third party webservice that may be down ( or a file you were using was deleted by another external process etc ) . The webservice may even be validate before the connection is attempted, but during the data transfer something went wrong.

In that scenario there is nothing that you or your co-workers can do to help it. But still you have to do something and not let the application just die and disappear in the eyes of the user. You use a checked exception for that and handle the exception, what can you do when that happens?, most of the time , just to attempt to log the error, probably save your work ( the app work ) and present a message to the user. ( The site blabla is down, please retry later etc. )

If the checked exception are overused ( by adding the "throw Exception" in the all the methods signatures ) , then your code will become very fragile, because everyone will ignore that exception ( because is too general ) and the quality of code will be seriously compromised.

If you overuse unchecked exception something similar will happen. The users of that code don't know if something may go wrong an a lot of try{...}catch( Throwable t ) will appear.

OscarRyz
Well said! +1. It always surprises me this distinction caller(unchecked)/callee(checked) is not more obvious...
VonC
+1  A: 

Barry Ruzek has written an excellent guide about choosing checked or unchecked exceptions.

http://www.oracle.com/technology/pub/articles/dev2arch/2006/11/effective-exceptions.html?_template=/ocom/print

sigget