Modificadores static y final en JAVA

Además de los modificadores de acceso, en java también existen otros modificadores que también se pueden aplicar sobre la definición de métodos y atributos, estos son static y final.


Un atributo de una clase se puede modificar con la palabra reservada static para indicar que este atributo no pertenece a las instancias de la clase si no a la propia clase, esto quiere decir que si tenemos varias instancias de una misma clase, cada una de ellas no tendrán una copia propia de ese atributo, si no que todas estas instancias compartirán una misma copia del atributo, a los atributos definidos como static, se les suele llamar atributos de la clase.

De esta manera, para acceder a un atributo static, no necesitamos crear una instancia de la clase, ya que podemos acceder a ellos mediante el nombre de la clase:
public class Mates {
    //Atributo de la clase Mates static
    public static float pi = 3.14f;
    //Podemos acceder a el mediante el nombre de la clase
    public static void main(String[] args) {
        System.out.println(Mates.pi);
    }
}
De la misma manera podemos utilizar la palabra static en la definición de los métodos haciendo que estos sean métodos de la clase, y de la misma manera que con los atributos, podemos llamar a estos métodos mediante el nombre de la clase. Debemos crear estos métodos con unas condiciones, estos métodos estáticos solo pueden acceder a atributos estáticos o llamar a otros métodos estáticos.
public class Persona {
    //Atributo estatico de la clase
    private static int nPersonas;
    //Cada instancia incrementa este atributo
    public Persona() {
        nPersonas++;
    }
    //Metodo estatico que retorna un atributo estatico
    public static int getNPersonas() {
        return nPersonas;
    }
    //MAIN
    public static void main(String[] args) {
        //Se crean instancias
        Persona p1 = new Persona();
        Persona p2 = new Persona();
        Persona p3 = new Persona();
        //Accedemos al metodo estatico para ver el numero
        //de instancias de tipo Persona creadas
        System.out.println(Persona.getNPersonas());
    }
}
Como vemos, el ejemplo anterior utiliza los métodos y atributos estáticos o de la clase para implementar un contador de instancias, que es uno de los múltiples usos que tiene el uso del modificador static.

Pensando por un momento, si el atributo nPersonas no fuese estático, cada objeto (p1, p2 o p3) tendría su propio atributo nPersonas que se inicializaría por defecto con el valor 0 y su propio constructor incrementaría este valor en 1, de este modo tendríamos que nPersonas cuenta con un valor de 1 en cada una de las instancias de Persona p1, p2 o p3.

Cuando necesitamos que el valor de un atributo no cambie durante el transcurso de nuestro programa, debemos utilizar el modificador final en su definición de la siguiente manera:
public final float pi = 3.14f;
En este ejemplo utilizamos el modificador final para almacenar el valor de la constante matemática pi, ya que su valor nunca va a cambiar, si por error intentásemos modificar el valor de un atributo definido como final, el compilador nos notificaría un error.

Además, muchas veces los modificadores static y final se utilizan en conjunto para definir constantes como puedes ver en el siguiente ejemplo:
public class Constantes {
     //Constantes publicas
     public static final float PI = 3.141592f;
     public static final float E = 2.728281f;
     //MAIN
     public static void main(String[] args) {
          System.out.println("PI = " + Constantes.PI);
          System.out.println("E = " + Constantes.E);
     }
}
Definiendo un atributo como public, static y final, obtenemos una constante que podrá ser accedida desde cualquier clase (public), el acceso se podrá realizar sin tener que instanciar la clase mediante el nombre de la clase (static) y su valor no podrá ser modificado en ningún momento (final).

El modificador final también se puede utilizar sobre un método o una clase, pero esto lo explicaremos cuando hablemos sobre el bonito tema de la herencia.

Comentarios

  1. hola muy bueno el articulo , pero mi duda es en esta parte del codigo.

    public Persona() {
    nPersonas++;
    }
    porque a ese metodo no se le coloca un modificador como void y solo se coloca
    public Persona()

    gracias

    ResponderEliminar
    Respuestas
    1. No lleva ningún tipo de modificador porque es un Constructor.

      Eliminar
    2. Porque es un constructor y los constructores no tienen tipo de retorno. Esta bien declarado. Eso es lo que puedo argumentar. Saludos desde Mexico

      Eliminar
    3. Se utiliza para llevar un control sobre cuantas instancias de esa clase han sido creadas

      Eliminar
  2. ammmm es el constructor de la clase

    ResponderEliminar
    Respuestas
    1. Efectivamente, recuerda que si un método empieza por mayúscula, este es el constructor, que es un método muy especial.

      Eliminar
  3. Muy buen artículo, deja clarísimo el uso de los modificadores static y final. Tenía algunas lagunas respecto a estos modificadores. Muchas gracias :-)

    ResponderEliminar
  4. No necesariamente debe comenzar por mayúscula para ser el constructor, como erróneamente dice Alejandro Santiago. Solo debe tener el nombre de la clase que está construyendo y ningún modificador, salvo el de acceso que debe ser public, al igual que la clase en su definición.

    ResponderEliminar
    Respuestas
    1. Cierto no es necesario, pero por convención se usa notación capital para el nombre de las clases, para gente que está aprendiendo es mucho mejor que lo aprenda así para evitar posibles confusiones.

      Por cierto el modificador de acceso del constructor NO necesariamente debe ser public, parece raro, pero así es, estudia patrones de diseño y lo verás por ti mismo.

      Un saludo.

      Eliminar
  5. Muy interesante e informativo! Muchas gracias por el artículo!

    ResponderEliminar
  6. Porque no es necesario inicializar la variable estatica nPersonas con un valor inicial (Por ejemplo: nPersonas=0)???

    ResponderEliminar
    Respuestas
    1. Todos los tributos de clase se inicializan en sus valores por defecto aunque no sean utilizados sin que nosotros tengamos que hacer nada. De modo que los atributos numericos se inicializan en 0 y los objetos en null.

      Espero que te sea de ayuda, saludos.

      Eliminar
    2. Gracias por la respuesta, ahora si todo me queda mucho mas claro.

      Eliminar
  7. Saludos, un blog muy interesante e informativo. Tengo una pregunta, es sobre un cuestionario y les agradecería si me pudieran despejar la duda a propósito del modificador de acceso static, no he encontrado información específica al respecto.

    Es una manera de sobrecargar el método:

    public static void incrementa( int num ) { numero += num; }

    Respuesta

    public static void incrementa( float num ) { num += numero; }

    public static void incrementa( double num ) { numero += num; }

    public static void incrementa( String num ) { numero += num; }

    public static void incrementa( double num ) { num += numero; }

    Según lo que comprendo todas serían válidas en un método con otro identificador. Quedo al pendiente y en todo caso, muchas gracias y disculpen la molestia.

    ResponderEliminar
    Respuestas
    1. El método inicial se encarga de sumarle el parámetro num al atributo static numero (este debe de estar definido en la clase que contenga el método). Sabiendo esto, podemos descartar la opción primera y cuarta dado que estos modifican el propio parámetro que es una variable local de modo que no hacen realmente nada.

      Y dado que la tercera opción contiene un fallo en compilación (ya que no puedes sumar el parámetro num de tipo String a un valor numérico), solo nos queda la segunda opción que es la correcta.

      Saludos

      Eliminar
  8. Claro, la primera y la última están realizando un proceso pero no es coherente con el contexto, con el String tenía la duda porque estuve haciendo en mis primeros trabajos una calculadora y colocaba cosas del tipo:
    a = t1.getText();
    t1.setText(a+=b);
    y funcionaba para que se agregaran dígitos al TextField aunque aparecían mensajes en la consola mientras pinchaba los botones, sin embargo, comprobé y claro, es un error de sintaxis. La respuesta fue calificada como correcta y entiendo la razón, muchas gracias.

    ResponderEliminar
  9. Que buenos ejemplos me ayudaron a entender los metodos estaticos y las variables, haber si un dia podrias hace un ejemplo como estos pero para los metodo ABSTRACTOS ya que en ningun lado los explican de manera simple. gracias

    ResponderEliminar
    Respuestas
    1. Se me ocurre pensar que para aprender a programar no está mal escribir bien. Así que "haber si un dia..." lo escribes "a ver si un día..."

      Gracias.

      Eliminar
  10. Muchas gracias por la explicación! Por fin lo entiendo. Un abrazo

    ResponderEliminar
  11. Muchas gracias, mas claro no puede estar, es la explicaci'on que buscaba

    ResponderEliminar

Publicar un comentario

Si tenéis alguna duda o sugerencia, no dudéis en comentar. ;)

Entradas populares de este blog

Autocompletado de codigo en Sublime Text

Compilar y ejecutar JAVA desde Notepad++

Compilar y ejecutar JAVA desde Sublime Text