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.

Alguna duda o algo qué decir? Deja tu comentario. Saludox.

26 comentarios:

  1. Anónimo dijo...:

    Gracias por tu explicacion del comienzo, es decir del momento en que indicas las razones de cuando ocuparlo... vi muchas páginas donde intentaban explicar con ejemplos horribles. De hecho muchos copy paste en varias páginas. Leyendo tu aclaración quede perfecto.

    Gracias nuevamente

  1. Anónimo dijo...:

    Podrias explicar que sucede con las variables definidas dentro de un método estatico, tambien son estaticas? o estas si son dependendientes e la instancia de la clase y al modificarlas en una no se modifican en las otras instancias...de antemano muchas gracias.

  1. Anónimo dijo...:

    Para un aprendiz: excelente, me aclaró lo que no tenía claro. Gracias por tu ayuda

  1. Anónimo dijo...:

    Muy Bien explicado y con unos ejemplos muy claros.

    Mil gracias!

  1. crian dijo...:

    Excelente Comentario por fin entendí muchas gracias hasta copie la explicación en un lugar especial para tenerla jaja...

  1. Anónimo dijo...:

    gracias por el comentario excelente explicación.

  1. Diego dijo...:

    Muy bien explicado, los ejemplos sencillos son los que mejor enseñan. Muy bueno Luis.

  1. Anónimo dijo...:

    gracias por traducir el scjp :)

  1. Jenny - PC dijo...:

    ahora la pregunta clave.. una clase estatica consume mas memoria que una clave no estatica???

  1. Anónimo dijo...:

    Que buena explicación. He encontrado pocas como ésta. Muchas gracias.

  1. Anónimo dijo...:

    Excelente explicación! (Y)

  1. Anónimo dijo...:

    cual es la diferencia entre redefinir y sobre escribir? o merjo dicho, como se redefine.

    Muy buena explicación, estuve buscando mucho en la red y no encotré nada bueno, hasta ahora.

  1. Anónimo dijo...:

    Solo quería decirte que da gusto buscar información y encontrar explicaciones como esta, un 10 :)

  1. Anónimo dijo...:

    Gracias. Esto me sirve como claro ejemplo en su uso en herencias para contar cada instancia hecha en el constructor de cada hijo :D

  1. Anónimo dijo...:

    Muy bueno!! También me quedé con la interrogante sobre la diferencia entre sobre-escribir y re-definir :/

    Si pudieras hacer un post al respecto, sería muy agradecido :D

    Saludos desde Panamá :)

  1. Luis Navarro dijo...:

    Qué tal,

    Aquí un más información al respecto:
    Sobreescritura de métodos en Java

    Saludos

  1. Anónimo dijo...:

    Excelente explicación 10 puntos.

  1. Anónimo dijo...:

    Gracias muy bien explicado

  1. Anónimo dijo...:

    si, muy bien explicado. Gracias.

  1. One dijo...:

    muy buena explicación

  1. Anónimo dijo...:

    Gracias.

  1. Anónimo dijo...:

    Gracias es un buen aporte y práctico. Entendí sobre el uso de static en java.

  1. Javier dijo...:

    Gracias exelente explicacion, tenia problemas al cargar los niveles de mi juego de diferentes niveles y ahora pude seguir, gracias a tu explicacion :).

  1. Isaias Benitez dijo...:

    Muchas gracias por el aporte es muy útil la verdad, pero me surgió una duda cual es la diferencia entre sobreescrito y redefinido ??? es que no me queda claro

  1. Anónimo dijo...:

    Gracias.... muy sencilla y practica la explicación.

  1. Anónimo dijo...:

    Redefinir y Sobrescribir es lo mismo. La diferencia está en Redefinir y Sobrecargar.

Publicar un comentario

Este es un espacio abierto, puedes escribir lo que gustes respetando los siguientes puntos:

1.- Lo que escribas esté relacionado con el post, si gustas contactarme puedes hacerlo aqui.

2.- Todo es cuestionable, aunque ten en cuenta que existen formas de hacerlo, evita las agresiones y revisa tu lenguaje antes de publicar un comentario.

3.- Siempre hay tres verdades: tu verdad, mi verdad y la verdad, por lo que opiniones diferentes no necesariamente son equivocadas.

4.- Los comentarios son una forma de discusión abierta, por lo que al publicar uno, implícitamente entras a una discusión, con todo lo que esto representa.

5. Me reservo el derecho de eliminar comentarios que no respeten las condiciones mencionadas anteriormente.

Toma en cuenta que puedes utilizar emoticones en tu comentario, para ver una lista de los disponibles da clic en este enlace.

 
Monillo007 © 2010 | Designed by Trucks, Manual Bookmarking | Elegant Themes