First, as already mentioned, use exceptions. Create your own hierarchy of exceptions and think about which of them make runtime and which not. Never use constructions like new Exception(...)
or new RuntimeException
. Instead, try to create and throw only adequate situations of exclusion. Instance creation Exception
or RuntimeException
- hack and unsubscribe instead of error handling.
Do not forget to check all the parameters in the constructors and, if possible, in the methods and promptly throw an IllegalArgumentException
. Use standard exceptions as appropriate. Use them for their intended purpose and never throw anything.
Use try
/ catch
/ finally
. Do not forget to destroy resources.
Use loggers instead of e.printStackTrace
. Never make catch
empty unless you are sure that you must ignore the exception.
When logging, use the full log
method with the logging level, message, and exception. Try to describe in the message to the log what exactly fell and add some information about the conditions in the try
block. This will help identify problems in combat conditions. Try to assign adequate levels of logging.
Customize the logger. In some cases, you should separate the logs for errors and variations. Otherwise, error messages can be lost and lost due to less important messages.
Hook something like an audit if the application is server-side. Perhaps it is worth it in especially fatal cases to send a letter to admins.
If this is a client application on a swing, then you can display an error message from the window or as a small icon in the status bar.
UPD1
When to make a RuntimeException
, and when just Exception
?
This is a rather complicated question and difficult to give general recommendations. But in general, one should be guided by the fatality of the error and its probability of occurrence. You should also consider the possible distance from the place of error generation to the place of actual processing. For example, IOException
cannot simply not be processed in any way and this is true. If it is not processed, then some resources may get stuck. And usually the processing of such an error is relatively close to its place of origin. At the same time, IllegalArgumentException
can not be caught ... because usually these are errors related to incorrect use of the API, incorrect configuration or insufficient validation of data from the user. And an attempt to catch such exceptions everywhere would lead to a crash: the code would simply be unreadable. In other words, common sense is required.
Is the only way to generate an error with a throw
statement?
No, it is not necessary to throw an exception. For example, in GWT (and not only) there is an AsyncCallback
interface that has an onError
method that accepts an exception as a parameter. The corresponding code does not throw
exception through throw
, but simply calls the callback method and passes the exception there. And the callback itself will decide what to do with this exception.
In what cases is it better to create, say, MyException extends Exception
, and then MyOtherException extends MyException
? In other words, how to see the need for a hierarchy of errors?
Obviously in cases where between the exceptions may be some kind of "related" connection. When some exception groups have something in common.
When to do something like this:
public void f() throws MyException { //некоторый код ... if (....){ throw MyException(...); } }
Always, if if
allows you to determine that something went wrong.
What are some other ways to generate errors?
Actually, assert
, throw
and just calling the handler with an exception parameter.
When is it more correct to transfer the error to the function level ( ... f() throws ...
)?
Again, the best example is an IOException
. This should always be done when there is an error, but you know for sure that the client (the caller of your method) may want to know about the error explicitly, and not by indirect signs. So, for example, if someone reads from a socket, then he wants to know that reading is impossible and simply to prepend the operation instead of checking every time whether the socket is working or making infinite ifs checking the error code after each read method.
UPD
Yes, perhaps, in my opinion, a good example of the wrong choice between Exception
and RuntimeException
is InterruptedException
. It would be much better if it was Runtime
. As a result, either everywhere you have to catch and ignore him, or throw around everywhere ... thinking up a case that will never happen. And these blockages badly spoil the code.