1. why using exception
Normally, we have two choices when returning values from a method:
1) return true or false
2) return void
According to my experience, using true or false is only the option when the method is very simple, like compare two objects or somthing like that. When this method is complicate enough, when the method may fail for more than one reason, we'd better use exception. Cause you can return a exception with different error messages.
The other reason why using exception instead of simply true or false is you will have to check and maintain your code to make sure every exception is caught in proper place and handled.
2. what kind of exception to use
Let us take a look of the definition of RuntimeException first. RuntimeException is the superclass of those exceptions that can be thrown during the normal operation of the Java Virtual Machine.
Yes, RuntimeException is the one we are gonna use.
And, an exception can be two types. One is business logic exception, the other one is technical exception. For example, you want to delete a record, while the record has relation with other tables. As a result , you will get an error , says you cannot delete it. In such a situatino, what the exception type could be? In my opinion, table relations are defined based on business rules, it should be an business logic exception. Another example, you are trying to open a file, while it doesn't exist. What kind of exception you will thorw? The situation is, the file should be there, but for some unknow reason, it's not there. Or you cannot technically read it. That shoudl be a technical exception. Simillar to this, all network connection failure, database connection failure, IO failure are technical exceptions.
3, what does it look like
We need have a customised super class which extends RuntimeException:
public class MyRuntimeException extends RuntimeException {
private Throwable causeException = null;
public MyRuntimeException() {
super();
}
public MyRuntimeException(String message) {
super(message);
}
public MyRuntimeException(String message, Throwable causeException) {
super(message);
this.causeException = causeException;
}
public MyRuntimeException(Throwable causeException) {
super(causeException.getMessage());
this.causeException = causeException;
}
public Throwable getCauseException() {
return causeException;
}
public void printStackTrace() {
super.printStackTrace();
if (causeException != null) {
causeException.printStackTrace();
}
}
public void printStackTrace(java.io.PrintWriter printWriter) {
super.printStackTrace(printWriter);
if (causeException != null) {
causeException.printStackTrace(printWriter);
}
}
public void printStackTrace(java.io.PrintStream printStream) {
super.printStackTrace(printStream);
if (causeException != null) {
causeException.printStackTrace(printStream);
}
}
}
And our sub classes will simply extend this:
public class BusinessException extends MyRuntimeException {
public BusinessException() {
super();
}
public BusinessException(String message) {
super(message);
}
public BusinessException(String message, Throwable causeException) {
super(message, causeException);
}
public BusinessException(Throwable causeException) {
super(causeException);
}
}
4. how to use
The first question is should us extend these two to create more specific exceptions? I'm not very sure at this point. I think it depends on how you gonna catch it. If you catch it as a whole, don't care what the specific reason is, then it's ok. If you need to know the specific failure reason, and have different way to deal with it, you may need subclasses.
The second quesion is where to put exception classes. I checked the struture of JDK and some open sources projects' API. It seems the convension is put the exception under where it will happen. Like IOException locates in java.io package.
The thrid quesion is when to catch exceptions. This is quite related to software structure. Normally, different layer has different set of exceptions. In each layer, exceptions will be thrown until it reaches the interface(or facade). In the interface class, catch all exceptions, handle it, or wrap it and throw it to the upper layer.