Since your question covers only the memory aspect of the program, it can be answered without any doubt that, from that point of view, it is best to create an object, use it and then release it - something that in java we know in advance that we can do it only indirectly - either by assigning null
to the reference of the object or by letting its references go out of context.
To give an example, in the hypothetical case of a connection, we could use a local variable, to which we do not have to assign null
at the end, it will leave context when the method is finished and, with that, the < em> garbage collector will take care of it at the time; something in the line of:
public Cliente buscarCliente(int id)
{
Conexion conn;
localConn = new Conexion();
CLiente result = realmenteBuscarAlCliente(localConn, id);
return result;
//acá, al terminar el método, la variable localConn sale de
//contexto y eventualmente será destruida, liberando la memoria que ocupa.
}
Alternatively, assign null
explicitly, for example in the middle of a very slow method or to a member of the class that you know will not be used later.
public void notificarClientes()
{
Conexion conn;
localConn = new Conexion();
ListaCLientes clientes = buscarClientes(localConn);
//de acá en adelante no se utilizará más la conexión.
localConn = null;
//acá comenzamos a enviar emails, cosa que ya no tiene nada que ver
//con la base de datos y es potencialmente tardado
for (Cliente cliente : clientes) {
notificarCliente(cliente);
}
}
But,
Not everything is memory
-
Resources
There are specific cases where the reference to an object may be making use of other system resources that are also scarce, not just memory. We talk about handles to system resources, such as files, processes, database connections, etc.
In cases like this, the usual practice is to implement the release of these resources in the release()
method, which is invoked when the object in question will no longer be used.
Going back to the previous example, it might look something like:
public Cliente buscarcliente(int id)
{
Conexion conn;
localConn = new Conexion();
try {
CLiente result = realmenteBuscarAlCliente(localConn, id);
return result;
} finally {
//nos aseguramos de liberar los recursos.
localConn.release();
}
//acá, al terminar el método, la variable localConn sale de
//contexto y eventualmente será destruida, liberando la memoria que ocupa.
}
-
Time-consuming operations
Time is money. In computer science, as in life, we often exchange one thing for another. There are many times when the scarcest and most expensive resource is time. Generally the memory is cheap in comparison with the time (whenever we do not speak of micro-devices).
In this line of thought, establishing a connection to a database is a good example of a process that is sometimes costly in time compared to its size in memory. I say this very carefully, because there are cases where the license of concurrent access to the database can be more expensive than all the previous ones, so do not take it as a truth written in stone, you always have to evaluate it.
Following this line of thought, it may be more effective for an application to establish the connection, and once established, keep it that way and re-use it to do many operations, before disconnecting from the database. In fact, in real life, many applications -especially application servers- maintain multiple connections established to the database in what is known as a Connection pool .
Another classic example in which objects that are held for a long time before being released are created Thread pool (in English)
No recipes
For this there is not a recipe that works for everything. Nor is there anything that is absolutely the best , it will always depend on the requirements, the use that is given to the applications and the design that they have.