What is try .. finally used for without the catch clause?

5

I maintain an inherited system, and I have seen in many parts a block similar to the following:

try {
  // aqui codigo

} finally {
  // mas codigo aqui
}

My question is: What is the function of making a try .. finally , without the block catch ?

    
asked by rnrneverdies 12.02.2016 в 18:30
source

7 answers

9

Contracts are a common concept in the design and analysis of algorithm correction. The concept is that the functions, methods or other units of our programs must have:

  • Preconditions: Conditions that callers must provide in advance for the method to produce correct results;
  • Postconditions: Conditions that (given preconditions) the method promises will be given when you return;
  • Invariant: Conditions that the method promises will not affect-will be true or false on return if and only if they were on entry.

In this framework, the try { ... } finally { ... } is a useful construct so that our code can guarantee postconditions even when exceptions are given within the block of try { ... } or in any method invoked within this block. Since the commands within the finally { ... } block are always going to be executed, exception or not, it is common to put there code that guarantees the postconditions.

The examples of "cleaning" that others have given fall within this framework. The idea is that in these examples:

  • A resource such as a file or a connection to a database is used;
  • There is a postcondition that forces the example code to guarantee that the resource will be closed no matter what happens in its use.
  • This was the most common use of finally in old Java versions. In Java 7 a new construct was introduced, called "try with resources," which replaces the try { ... } finally { ... } in its most common uses:

    try (OutputStream out = ...) {
        // usar el OutputStream 'out'
    } // postcondición: 'out' ha sido cerrado
    

    Another kind of example is with the thread synchronization tools ("threads"). In the package java.util.concurrent.locks there are several classes of locks ("locks") that are normally used with try {...} finally {...} :

    Lock l = ...;
    l.lock();
    try {
        // Entre los hilos que comparten la cerradura 'l', sólo uno
        // puede entrar en este bloque a la vez.
    } finally {
        l.unlock();
    }  // postcondición: la cerradura está abierta
    

    But the concept of postconditions should be emphasized again. After all, the try { ... } finally { ... } is not specifically a "cleaning" mechanism but rather a general tool to facilitate the composition of correct programs. So it has other uses, even if they are much less common than these two.

    It is possible to add another type of examples. A frequent cause of programming errors is the early return ("early return") of a function or method. The typical cases are something like this:

    public LoQueSea miMétodo(Desto algo, Coso queSéYo) {
        // muchas lineas...
    
        if (noSéQué()) {
            return new LoQueSea(algo);  // salida temprana
        } 
    
        // muchas más lineas...
    
        cosaQueSiempreTieneQuePasar(queSéYo);
        return new LoQueSea(algo.con(queSéYo));
    }
    

    Assuming that it is always necessary to call the cosaQueSiempreTieneQuePasar() method, this example has an error: when noSéQué() returns with true we leave early and forget to call cosaQueSiempreTieneQuePasar() . A solution in many cases is the following:

    public LoQueSea miMétodo(Desto algo, Coso queSéYo) {
        try {
            // muchas lineas...
    
            if (noSéQué()) {
                return new LoQueSea(algo);  // salida temprana
            } 
    
            // muchas más lineas...
            return new LoQueSea(algo.con(queSéYo));
        } finally {
            // Este bloque se ejecuta siempre, aun si hay 
            // salida temprana.
            cosaQueSiempreTieneQuePasar(queSéYo);
        }
    }
    

    And here it should be noted that, although many answers have mentioned exceptions as the reason for the try {...} finally {...} , this example shows that we can run into problems even if there are no exceptions. Other examples are possible with break and continue in repeating structures as for (...) {...} .

    Or rather, the exceptions, the return early, the break and the continue have something in common-early exit from a block of code-and the finally is a common solution for problems that cause all of these.

        
    answered by 12.02.2016 / 23:45
    source
    3

    Apparently it is not such a bad practice since the finally is always going to be executed can be used to clean. I found a couple of examples in the network:

    Example 1

    public void yourMethod() throws YourException {
        try {
            db.store(mydata);
        } finally {
            db.cleanup();
        }
    } 
    

    Example 2

    OutputStream os = null;
    OutputStreamWriter wos = null;
    try { 
       os = new FileOutputStream(...);
       wos = new OutputStreamWriter(os);
       // ......
    
       wos.flush();
       os.flush();
    finally {
       IOUtils.closeQuietly(wos);
       IOUtils.closeQuietly(os);
    }
    

    Here a user says that in the following example the catch would not know what to do with the error so it would be better to add a cleaning routine.

    InputStream in = null;
    try {
        in = new FileInputStream("file.txt");
        // Hacer algo que lance una excepción
    } finally {
        if (in != null) {
             try {
                 in.close();
             } catch (IOException e) {
             // Nothing we can do.
             }
        }
    }
    
        
    answered by 12.02.2016 в 18:45
    2

    The catch block is used only to catch an exception that appears during code execution. Since there is no block catch , the exception will jump and will be handled by the client of the method where this block of code is located. If there is no handling of this exception, then the exception will jump to the highest level that it can reach. If the highest level is the method public static void main(String[] args) of the application and it is not handled there, then the application will show the exception that has been thrown and will "end".

    It should be noted that the block finally always runs, whether the exception has been thrown to the highest level of the application. There are cases where finally is not executed but are external to this response. You can see them here

    Use try-finally when your code does not need to handle the exception because there is already another level where it will be handled. For example, in a web application where you have some X component that decorates the components that execute the requests and X already has a way of working with the default exceptions, which will automatically log them in and display a "nice" message to the user ( I do not know which error message is really nice). An example of this example (worth the redundancy) is the case of Spring MVC where you can use @ControllerAdvice to handle exceptions at a general level. This way, if your code throws an exception it will not be handled by him but the class decorated with this annotation.

    It is not a bad practice, it is a matter of order.

        
    answered by 12.02.2016 в 18:47
    1

    As mentioned by other people, try with finally serves to clean up in the event of an exception, without caching that exception.

    As of Java 7 you have try with resources , even blocks that only include try can already exist:

    try (OutputStream s = getOutputStream()) {
        //usar s
    }
    

    The finally remains because the stream is going to close, ending the block.

        
    answered by 12.02.2016 в 19:49
    0

    It could be used in processes that if they fail, it is not necessary to be informed, nor to alert the user. but it is a bad practice, minimum should record a log of exceptions in the catch

        
    answered by 12.02.2016 в 18:32
    0

    The complete clause is: Try, Catch and Finally. It is possible that they did not use the error capture block because it was not necessary to make some kind of notification ... However, you should add it to, in the future, better identify why and where the problem is occurring.

        
    answered by 12.02.2016 в 18:44
    0
    • To close resources (eg open files) without interrupting the flow of exceptions when they occur.
    • To put in that block a code that we always want to run, regardless of whether exceptions are thrown or not, eg: System.out.println("Salgo de la funcion Clase1.pepito()");
    answered by 30.11.2016 в 17:48