Close() method in Try and catch blocks is necessary?

Asked

Viewed 354 times

4

I am studying Java with database and after seeing a little more about this method close() and this protected block, I was a little confused, because in some codes and articles I see that was not used the close() in the blocks Try/catch for they are "self-sclose" or something like.

I also know that it is very important to use this method to save execution resources. Ultimately, if I use the close() inside the block I will be committing ambiguity of functionalities since the block is in charge of closing the connection? Or am I doing the right thing?

  • 2
  • Did any of the answers solve your question? Do you think you can accept one of them? Check out the [tour] how to do this, if you haven’t already. You would help the community by identifying what was the best solution for you. You can accept only one of them. But you can vote on any question or answer you find useful on the entire site.

3 answers

6

First you need to know if all the code is correct. When it comes to this kind of thing I see a lot of things wrong.

Second, you need to see the context, because you might not want to close, so you shouldn’t use.

It is common in many cases to use the close() in a try-catch as much as outside of it. In fact people use try-catch where they shouldn’t and there’s a good chance they’re using it wrong there. And if you really need it, you should probably use a try with Resources, and there is no need to use the close() because it will be called automatically and in the right way.

If you’re gonna use a try-catch then the close() should be used in the finally which is where the try with Resources places internally.

Generally whenever you use a class called closeable, that is, that it has a method close() (actually only when it’s part of the interface AutoCloseable) should use the try with Resources. Except in cases where the idea is not to close at that location.

A very big part of memory problems is not using this way.

Put a close() where he will be called is not a big problem, only it will be of no use. Precisely because one can do wrong the try with Resources it is necessary for it to check first if it is already closed which makes the code slower, although it makes very little difference. But it is ambiguous.

See more on documentation.

4

The safest way to use the close() is indirectly, with the Try-with-Resources. The Try-with-Resources was introduced in Java 7 which was released in 2011. So if you’re seeing older articles, they won’t talk about this feature and will show the old-fashioned management.

An example of the use of Try-with-Resources that’s the one:

try (Connection con = getConnection()) {
    // Faz algo com a conexão.
}

The compiler will put on its own a blcoo finally implicit to close the object con and already treat all special cases of exceptions in the block try and exceptions being launched by the method close(). If you put blocks catch or a block finally explicit, the compiler will know how to combine everything harmoniously. See more details in the question "How Try-with-Resources works?".

Call the close() inside a block that already uses the Try-with-Resources, although possible, it does not usually make much sense, but it would also hardly cause any harmful effect, except if you try to use the closed resource as if it were still open, obviously.

If you can’t use the Try-with-Resources for some reason, prefer to do what the compiler would do if you used: Call the close() inside the block finally. For example:

Connection con = null;
try {
    con = getConnection();
    // ... faz um monte de coisas.
} catch (SQLException e) {
    // Faz algo para tratar a exceção, relançar ou encapsular e lançar outra exceção.
} finally {
    try {
        if (con != null) con.close();
    } catch (SQLException e) {
        // Faz algo para tratar a exceção, relançar ou encapsular e lançar outra exceção.
    }
}

If you are dealing with a case where the resource should remain open after the execution of the method, then in general there are two alternatives:

  1. Return the object that represents the resource that was left open so that the method that called you worry about closing.

  2. Store the object in some class instance attribute and make this class implement AutoCloseable. The method close() of that class then delegates to the close() open resource. This resource should preferably be opened in the constructor.

Example of case 1:

// Deixa o recurso aberto e o retorna.
public InputStream abrirArquivo() {
    return new FileInputStream(new File("teste.txt"));
}

// Usa o recurso aberto pelo outro método.
public class utilizaArquivo() {
    try (InputStream x = abrirArquivo()) {
        // ...
    }
}

Example of case 2:

public class ChamadaTelefonica implements AutoCloseable {
    private final String destino;
    private final InputStream entrada;
    private final OutputStream saida;

    public ChamadaTelefonica(String destino) {
        this.destino = destino;
        this.entrada = ...;
        this.saida = ...;
    }

    // Um monte de métodos legais aqui que operar os atributos entrada e saída.

    @Override
    public void close() throws IOException {
        try {
            entrada.close();
        } finally {
            saida.close();
        }
    }
}

1

You don’t need to use the close() to close a connection when it is managed by another system. It is common in large projects for connections to be managed by servidor de aplicação, or by a framework JPA, in this case it is not necessary to open or close connections, just pick up and use.

If you are doing everything manually, open connection, run query, commit, etç, it is necessary and fundamental to close the connections, otherwise you can exceed the database limit. This limit depends on the type of bank and configuration you are using.

Browser other questions tagged

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