Exceptions in Java

Asked

Viewed 1,796 times

6

I am studying about exceptions in Java and would like to understand better.

When declaring an object, if the programmer predicts that a failure may occur in the execution of the method, he will launch an object of the type Exception. (right?)

I wanted to understand how the capture and release of the exception works.

Why the RuntimeException and its subclasses are not verified by the compiler.

If the block try/catch is only used to deal with exceptions or if there is other purpose of use.

When a block try executes an exceptional method, at the time the method throws the exception, the rest of the method code will not occur together with the remaining code of try, jumping to catch? If yes and in the case of a multi-exceptional method?

And lastly, what is the class Throwable?

Thank you!

1 answer

11


Exceptions are a form of detour, as well as ifs, breaks, returns, etc. Its utility is to allow a code to be stopped if it is unable to continue, in a convenient and organized way.

Suppose Java has no exceptions. If the method a calls the method b, who calls the c what call FileReader.read, what happens if there is an error in reading?

  1. The method c it has to stop, because it can not continue without the data read. It returns;
  2. The method b have to know that the method c failed; to that end, c has to return a special error code - interfering with its normal return value - and b have to test by this code using a if (for example);
  3. The method a have to know that the method b failed; etc.

Somewhere this mistake will have to be dealt with - if only in main (or in the Thread.run), to abort the program with error code. What the exceptions do is allow the execution flow to deviate [almost] directly to the exact point where error handling is possible, without the programmer having to do anything else. What’s more, they collect and store various information about the error, such as which methods were running and which line they were on, allowing them to generate a report that allows the programmer to more easily discover their cause.

When declaring an object, if the programmer predicts that a failure may occur in the execution of the method, he will launch an object of the type Exception. (right?)

Not necessarily. He can do this if the error is detected by his own logic, and this deviation is convenient for the caller. It may also not throw exceptions directly, but allow your code (i.e. the other functions that this method calls) to bid - declaring this in your signature if necessary (throws ExceçãoX, ExceçãoY). Or he can do something else, like return an error code, try to handle the exception himself, log in somewhere... It depends on the case.

In general, the "right thing" to do is to launch/allow an exception to be made - maybe unchecked (more about that later). Returning an error code complicates the calling form, and logging in the error makes it more difficult to customize the system (i.e. if you do not want that this error is logged in, and the method alone does, in its absence, this may hinder its use or require some "gambiarra" to circumvent/undo it). If you do not have good reasons to deviate from this, do not deviate: use exceptions even.

I wanted to understand how the capture and release of the exception works.

Returning to the example of methods a, b and c, let’s say a is prepared to treat the exception E, while b is not. As the methods are called, the execution contexts (i.e. local variables, current instruction, etc.) of the same are placed in the stack. Normally, b would have to run to the end before the control return to a, the same to c in relation to b. But if c finds this exceptional condition - and decides to launch E - happens the following:

  1. c creates an object instance E, passing the parameters you need;
  2. The execution flow of c is stopped where you are, i.e. your code does not finish running;
  3. If c has a block try/finally or try/catch/finally, and the exception was cast within the try, he runs the Finally;
  4. c is unstoppable. Normally, b would continue to run from where it left off, but that’s not what happens. The exception release process is not finished yet.
  5. If b has a block try/finally or try/catch/finally, and c was called inside the try, he runs the Finally;
  6. b is unstoppable. Normally, a would continue running from where it left off, but the exception release process is not yet finished.
  7. Like b was called inside a block try/catch or try/catch/finally, and E is present in one of the clauses catch, that block runs.
  8. Exception launch process finished. Block continuing code catch forward.

Why the RuntimeException and its subclasses are not verified by the compiler.

There are two types of exception: the checked (checked) and the unchecked (unchecked). Ideally - from the point of view of Java designers - no method should behave unexpectedly; either it should succeed, or it should fail in an orderly and consistent manner. As methods usually call other methods, each should be responsible for behaving well even in the presence of errors in the so-called methods. Thus, each method would need to be aware of the exceptions that its components can throw, and either treat or propagate them to the calling method. For this to be possible, the calling method has to be aware that this method can cast exceptions X, Y and Z, and prepare accordingly.

In theory it’s a beauty, but in practice it’s unfeasible. There are errors that can occur in any method, and it would be a waste to keep declaring them all the time. JVM memory can end, for example. Or in a division, the divisor could be zero. If we were to take into account all these possibilities, the signature of our methods would become gigantic! And to make matters worse, it’s very unlikely that the calling method will be able to recover from, say, a OutOfMemoryError - anything he tried to do would waste more memory and generate another OutOfMemoryError, turning a snowball...

That’s what the exceptions are for unchecked: for disband the methods of declaring that this exception is possible, but still allow some of them to try to treat it if they think they can handle it. A RuntimeException is the base class for all of them except for the Error - which in general denotes a more serious condition which can hardly be treated by any method.

Note: it is better to use exceptions checked (who inherits from Exception) or unchecked (who inherits from RuntimeException)? I can’t tell you. It’s a balance between the security of the code and its conciseness/expressiveness. try/catchis too much and its code is unreadable, try/catches of less and nobody knows more that errors can occur in a method. It is a situation similar to using static typing (with or without generic types) vs. Duck Typing vs. dynamic typing: you win on one side and lose on the other...

If the Try/catch block is only used to deal with exceptions or if there is other use purpose.

Theoretically you could [ab]use it to simulate a goto, but in general no, it is only to deal with exceptions same. It should be noted that in Java the handling of exceptions is relatively expensive, so it is often preferable to use "normal" control streams even [for not exceptional codes], although this complicates your code a little. Other languages (e.g., Python) already use them for more common situations - for example idiom (idiom) "do not check the parameters before calling the function, simply call it and if you are unsuccessful capture the exception". This should be avoided in Java (even because try/catches are not exactly concise in my opinion...).

Already the try/finally and the try/catch/finally, is also used to handle exceptions, even if not exactly to "treat" them. Consider this code:

try {
    String linha = leitor.readLine();
    int x = Integer.parseInt(linha);
}
catch(IOException ioe) { ... }
finally {
    leitor.close();
}

In that case, we want the reader to be closed no matter what happens: if the code succeeds, if it launches a IOException, or if he throws any other exception. The important thing is not to forget it open. For even if one NumberFormatException is launched in the try, and he didn’t even get into the catch, the finally will still perform (before the exception propagate to the calling method).

...and in the case of a multi-exceptional method?

As already stated, the code of try (or the entire method code, if the exception occurs outside a try) is interrupted when an exception occurs, jumping to a catch or a finally. If he falls in a catch, then it is considered that the exception treatment was done successfully, and the block code catch is treated as a normal code - and may even make another exception, with no relation to the original exception.

If he falls in a finally, on the other hand, we have a problem: the finally is not the "destination" of the exception, only a "stopping point". If it also produce an error, which should go to the calling method - the original or the new? The solution that Java gives to this impasse is the following: the new method is launched, but the exception leaves a reference to the original exception. It is said in this case that the exception B was "caused by" the exception A. One can access A through B.getCause(). In this case, it is important to note that the calling method needs to address B - if he only deals with A, execution will not enter the block catch.

And finally what is the class Throwable?

As already said, there are two types of "bugs" in Java: Errors and Exceptions. The class Throwable is the superclass of both, created to allow code to handle both simultaneously. "normal" programmers in general should not attempt to handle Error - since it is a serious flaw that will only be circumvented if you know what you are doing well. So there is no point in using catch Throwable - better just take Exception even (if it is a generic error-handling code) or, better yet, take only the exceptions you can actually handle (and propagate the rest).


Some references (in English):

  • A little broad on the question, but I tried to answer it as best I could. If you have any questions at any particular point, I suggest opening a new, more focused question where there is room for a more detailed answer.

  • 1

    Thank you! I really didn’t know that would be such an extensive response. I need to research some of the points you mentioned in your answer so I can understand you better. If I need help again, I will ask here, with the link of the new question, so that you can continue your answer. Once again I thank you for your attention :)

  • My new question I wish you could take a look!

  • An article I found very good about when to use checked or unchecked exceptions is this one: http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html

Browser other questions tagged

You are not signed in. Login or sign up in order to post.