domingo, 1 de noviembre de 2015

VARIABLES Y MÉTODOS ESTÁTICOS EN JAVA


El modificador 'static' tiene un profundo impacto en el comportamiento de una variable o método por ello es que normalmente se trata a este modificador completamente separado de los demás. Para entender la forma en que un miembro estático (static) trabaja, veremos primeramente una razón para la cual utilizarlo.

Imaginemos que se cuenta con una clase de utilidad que tiene un método que siempre se ejecuta de la misma manera, por decir un ejemplo, un método que siempre devuelve un valor aleatorio. No importa qué instancia de la clase esté llamando a éste método, siempre se comportará de la misma manera. En otras palabras, el comportamiento del método es independiente de la instancia de la clase o, lo que es lo mismo, del estado actual del objeto.

Imaginemos otro escenario. Supongamos que se desea realizar un conteo de todas las instancias que se tienen de una clase en particular, ¿dónde debería de almacenarse dicha variable? no funcionará el mantenerla como una variable de instancia dentro de la clase a la cual se quiere realizar el conteo ya que al momento de instanciarla el contador se inicializará a su valor por defecto (como sucede con todas las variables de instancia), entonces, ¿cómo haremos para realizar este conteo?


Para resolver un poco la situación planteada anteriormente pongamos en claro que las variables y los métodos marcados con el modificador 'static', es decir, variables y métodos estáticos pertenecen a la clase, no a una instancia de dicha clase en particular. De hecho, se pueden utilizar componentes estáticos sin tener una instancia de la clase. Pero en caso de que existan instancias de dicha clase, el componente estático de la misma será compartido por todas aquellas instancias existentes en un momento dado; solo existe una copia.

El código a continuación declara y utiliza una variable para nuestro contador estático:

class MiClase{

  //declaramos e inicializamos la variable estática
  static int contador = 0;

  public MiClase(){
    //Se modifica el valor en el constructor
    contador += 1;
  }

  public static void main (String[] args){

    new MiClase();
    new MiClase();
    new MiClase();
    System.out.println("El número de clases son: "+contador);

  }

}


En el código anterior, la variable estática 'contador' es inicializada en cero cuando MiClase es cargada por primera vez en la JVM, antes de que cualquier instancia sea creada. Cada vez que una nueva instancia de la clase se crea se manda a llamar al constructor de la clase y el contador aumenta en uno. Cuando el código se ejecuta ya fueron creadas 3 instancias de la clase y el resultado es el siguiente:

El número de clases son: 3

Ahora imaginemos lo que puede suceder si 'contador' fuera una variable de instancia, en otras palabras, no estática:

class MiClase{

  //declaramos e inicializamos la variable de instancia
  int contador = 0;

  public MiClase(){
    //Se modifica el valor en el constructor
    contador += 1;
  }

  public static void main (String[] args){

    new MiClase();
    new MiClase();
    new MiClase();
    System.out.println("El número de clases son: "+contador);

  }

}


Cuando el código anterior se intenta ejecutar sigue creando las mismas 3 instancias de la clase dentro de main() pero el resultado es un error de compilador. Ya no pensamos siquiera en que corra sino en que por lo menos se pueda compilar. Cuando lo intentamos nos aparece un error como el siguiente:

MiClase.java: 11: non-static variable contador cannot be referenced from static context
  System.out.println("El número de clases son: "+contador);
                                                                        ^
  1 error

La JVM no sabe de qué objeto de MiClase estás tratando de imprimir su variable 'contador’. El problema principal es que el método main() en sí es estático y no está corriendo sobre un objeto en particular de la clase sino directamente en la clase. Un método estático no puede acceder a ningún componente (método o variable) no estático. Pensemos de la siguiente manera: estático (static) = clase, no-estático = instancia.

Acceder a métodos y variables estáticas::

De manera que no se necesita tener una instancia de la clase para invocar a un método o acceder a una variable estática, entonces, ¿cómo se invoca o se usa un componente estático? ¿cuál es la sintáxis?. La respuesta es simple, para acceder a un componente estático de una clase solamente basta con utilizar el operador punto (.) después del nombre de la clase y posteriormente hacer referencia al método o variable estática. P. ej:

class MiClase{

  static int contador = 0;

  public MiClase(){
    contador += 1;
  }
}

class ProbarMiClase{
  public static void main(String[] args){
    new MiClase();
    new MiClase();
    new MiClase();
    System.out.printl("Contador: "+MiClase.contador);
  }
}


De igual manera se puede acceder a un componente estático de una clase por medio de un objeto de dicha clase, pero recordemos que dicho valor no dependerá de la instancia y todos los métodos o variables arrojarán el mismo resultado independientemente de qué objeto lo esté invocando o accediendo.

MiClase mc = new MiClase();
int clases = mc.contador;


Por último, tengamos en cuenta que los métodos estáticos no pueden ser sobreescritos. Esto no significa que no puedan ser 'redefinidos' dentro de una clase, pero redefinir no es lo mismo que sobreescribir.