miércoles, 3 de junio de 2009

Declaracion de metodo constructor y destructor

Declaración de un método constructor

Cuando se declara una clase en Java, se pueden declarar uno o más constructores opcionales que realizan la inicialización cuando se instancia (se crea una ocurrencia) un objeto de dicha clase.

Utilizando el código de la sección anterior, cuando se crea una nueva instancia de MiClase, se crean (instancias) todos los métodos y variables, y se llama al constructor de la clase:

    MiClase mc;
    mc = new MiClase();

La palabra clave new se usa para crear una instancia de la clase. Antes de ser instanciada con new no consume memoria, simplemente es una declaración de tipo. Después de ser instanciado un nuevo objeto mc, el valor de i en el objeto mc será igual a 10. Se puede referenciar la variable (de instancia) i con el nombre del objeto:

    mc.i++; // incrementa la instancia de i de mc

Al tener mc todas las variables y métodos de MiClase, se puede usar la primera sintaxis para llamar al método Suma_a_i() utilizando el nuevo nombre de clase mc:

    mc.Suma_a_i( 10 );

y ahora la variable mc.i vale 21.

Luego, en Java, cuando se instancia un objeto, siempre se hace una llamada directa al constructor como argumento del operador new. Este operador se encarga de que el sistema proporcione memoria para contener al objeto que se va a crear.

En C++, los objetos pueden instanciarse de diferentes formas, pero en Java solamente se pueden instanciar en la pila de memoria, es decir, solamente se pueden instanciar utilizando el operador new para poder solicitar memoria al sistema en tiempo de ejecución y utilizar el constructor para instanciar el objeto en esa zona de memoria. Si al intentar instanciar un objeto, la Máquina Virtual Java (JVM) no puede localizar la memoria que necesita ese objeto, bien inmediatamente o haciendo ejecutarse al reciclador de memoria, el sistema lanzará un OutOfMemoryError.

Tanto en Java como en C++, si no se proporciona explícitamente un constructor, el sistema proporciona uno por defecto que inicializará automáticamente todas las variables miembro a cero o su equivalente, en Java. En C++, el constructor de defecto no realiza ningún tipo de inicialización.

Se puede pensar en el constructor de defecto en Java como un método que tiene el mismo nombre que la clase y una lista de argumentos vacía. Y en C++, el constructor de defecto sería como la llamada cuando se instancia un objeto sin parámetros

    MiClase objeto;

En ambos lenguajes, si se proporciona uno o más constructores, el constructor de defecto no se proporciona automáticamente y si fuese necesaria su utilización, tendría que proporcionarlo explícitamente el programa.

Las dos sentencias siguientes muestran cómo se utiliza el constructor en Java para declarar, instanciar y, opcionalmente, inicializar un objeto:

    MiClase miObjeto = new MiClase();
    MiClase miObjeto = new MiClase( 1,2,3 );

Las dos sentencias devuelven una referencia al nuevo objeto que es almacenada en la variable miObjeto. También se puede invocar al constructor sin asignar la referencia a una variable. Esto es útil cuando un método requiere un objeto de un tipo determinado como argumento, ya que se puede incluir una llamada al constructor de este objeto en la llamada al método:

    miMetodo( new MiConstructor( 1,2,3 ) );

Aquí se instancia e inicializa un objeto y se pasa a la función. Para que el programa compile adecuadamente, debe existir una versión de la función que espere recibir un objeto de ese tipo como parámetro.

Tanto en Java como en C++, cuando un método o una función comienza su ejecución, todos los parámetros se crean como variables locales automáticas. En este caso, el objeto es instanciado en conjunción con la llamada a la función que será utilizada para inicializar esas variables locales cuando comience la ejecución y luego serán guardadas. Como son automáticas, cuando el método concluye su ejecución, se destruirá (en C++) o será marcado para su destrucción (en Java).

class MiClase {
    int varInstancia;
      
    // Este es el constructor parametrizado
    MiClase( int dato ) {
        // rellenamos la variable de instancia con los datos
        // que se pasan al constructor
        varInstancia = dato;
        }
      
    void verVarInstancia() {
        System.out.println( "El Objeto contiene " + varInstancia );
        }
    }

Declaración de destructores o (Garbagge Collector)

Java no utiliza destructores (al contrario que C++) ya que tiene una forma de recoger automáticamente todos los objetos que se salen del alcance. No obstante proporciona un método que, cuando se especifique en el código de la clase, el reciclador de memoria (garbage collector) llamará:

    // Cierra el canal cuando este objeto es reciclado
    protected void finalize() {
        close();
        }

Cada objeto tiene el método finalize(), que es heredado de la clase Object. Si se necesitase realizar alguna limpieza asociada con la memoria, se puede sobreescribir el método finalize() y colocar en él el código que sea necesario.

Los programadores C++ deben tener en cuenta que el método finalize() no es un destructor. En C++, si existe un destructor, éste será invocado siempre que el objeto se salga de ámbito o vaya a ser destruido. En Java, aunque el método finalize() siempre se invocará antes de que el reciclador de memoria libere la zona de memoria ocupada por el objeto, no hay garantía alguna de que el reciclador de memoria reclame la memoria de un determinado objeto, es decir, no hay garantía de que el método finalize() sea invocado.

La regla de oro a seguir es que no se debe poner ningún código que deba ser ejecutado en el método finalize(). Por ejemplo, si se necesita concluir la comunicación con un servidor cuando ya no se va a usar un objeto, no debe ponerse el código de desconexión en el método finalize(), porque puede que nunca se llamado. Luego, en Java, es responsabilidad del programador escribir métodos para realizar limpieza que no involucre a la memoria ocupada por el objeto y ejecutarlos en el instante preciso. El método finalize() y el reciclador de memoria son útiles para liberar la memoria de la pila y debería restringirse su uso solamente a eso, y no depender de ellos para realizar ningún otro tipo de limpieza.

2 comentarios: