Uso de directiva static en Java

keyword-static-java

keyword-static-java


En esta entrada sobre uso de directiva static en Java, vamos a explorar y ver como usar de manera correcta y cuando hacer uso de la palabra static en Java através de ejemplos.

Vamos a ver como aplicarla a variables, metodos, clases anidadas y bloques de código (block).

¿Cómo funciona la directiva static?

En Java el uso de static indica que en lugar de pertenecer a una instancia del tipo que se acaba de declarar pertenece a un tipo en si mismo. Es decir, solo se creará una instancia de ese miembro estático el cual será compartida por todas las instancias de la clase.

El uso de static hará uso de la memoria una vez en el área de la clase justo cuando se hace la carga de esa clase. Es indiferente el número de veces que la clase se inicialize, siempre habrá una y solo una copia del campo definido con static.

Desde el punto de vista de la memoria y la JVM, las variables de tipo static se guardan en un pool de la JVM que es llamado Metaspace.

Por ejemplo un caso de uso en el uso de static es en el patrón singleton, cuando únicamente queremos crear una instancia.

Uso de static en Java | Uso de directiva static en Java
Uso de static en Java

Uso de static en campos

El uso de static en un campo hará que ese campo se instancie una única vez al cargar la clase, y esta variable mantendrá su valor, el cual será compartido entre todos los elementos que accedan a ella, mientrás dure la ejecución.

Un claro uso de definición de un campo static es para hacer uso de un contador, el cual será incrementado por cualquiera que pueda acceder a ese campo.

Vamos a ver un ejemplo en el que incrementamos el número de productos que tenemos.

@Getter
@Setter
public class ProductsCounter {

    private Long productId;

    private LocalDate date;
    
    public static int productsNumber;
    
    public Cart(Long userId, LocalDate date) {
        productsNumber++;
        this.productId = userId;
        this.date = date;
    }

}

Con el anterior fragmento de código lo que hemos conseguido es que cada vez que se llame a ProductsCounter, el contador de productsNumber será incrementado. Da igual el número de veces que se le llame, siempre será incrementado en una unidad.

Si realizamos un test para ver su funcionamiento, podemos comprobar como la variable se incrementa independientemente de cuantas veces se cree la clase.

@Test
public void whenProductsCounterIsInitializedThenProductsNumberIsIncremented() {
    new ProductsCounter(1L, LocalDate.now());
    new ProductsCounter(19L, LocalDate.now());
    new ProductsCounter(11L, LocalDate.now());
    new ProductsCounter(219L, LocalDate.now());
 
    assertEquals(4, ProductsCounter.productsNumber);
}

Un buen uso de static en campos es cuando queremos que una variable sea compartida entre objetos y que su valor sea independiente a cualquier objeto.

Uso de static en Clases de Java

Cuando hacemos uso de static en clases se definirá como static class. Una clase static solo puede ser usada en una inner class, es decir, en una clase interna de otra. Esta clase podrá ser accedida sin instanciar la clase externa, usando únicamente otros miembros static.

Una clase static anidada no tiene acceso a las variables de instancia a ni a los métodos de la clase externa.

Hay que tener en cuenta que cuando hablamos de clases internas unas de otras, podemos tener inner class y static inner class. La única diferencia es que una será static y la otra no.

Vamos a ver un ejemplo para entenderlo mejor. Anteriormente hablamos de que un uso de static es para implementar el patrón singleton, veamoslo:

public final class Singleton {
    private static Singleton SINGLETON_INSTANCE;
    
    private Singleton() {        
    }
    
    public static Singleton getSingletonInstance() {
        if(SINGLETON_INSTANCE == null) {
            SINGLETON_INSTANCE = new Singleton();
        }
        
        return SINGLETON_INSTANCE;
    }
    // getters and setters
}

Razones de uso de static class en Java:

  • Agrupar clases que serán usadas en un lugar para aumentar la encapsulación.
  • Podemos mejorar el heap y el stack de memoria si declaramos las clases anidadas como estáticas siempre y cuando no requiera ningún acceso a los miembros de la clase que la encierra, así, además no se acoplará a la clase externa.

Uso de static en Métodos de Java

El uso de static en un método es generalmente usado para operaciones que no dependen de la creación de una instancia.

Por lo general los métodos que vayan acompañados de la palabra static serán por lo general, métodos de utilidad o helper para clases, por ejemplo contadores o cargar alguna configuración con propiedades.

Ejemplos de métodos static pueden ser CollectionsUtils de Spring, StringUtils de Apache, la librería Math de la JDK etc…

Vamos a ver un ejemplo de método static haciendo una carga de propiedades:

private static Properties loadProperties(String fileName) throws IOException {
        FileInputStream fis = null;
        Properties prop = null;
        try {
            fis = new FileInputStream(fileName);
            prop = new Properties();
            prop.load(fis);
        } catch(FileNotFoundException fnfe) {
            fnfe.printStackTrace();
        } catch(IOException ioe) {
            ioe.printStackTrace();
        } finally {
            fis.close();
        }
        return prop;
    }

El ejemplo anterior cargará una serie de propiedades de un nombre de fichero y podrá ser independiente de la creación de cualquier clase.

  • Algunas consideraciones a tener en cuenta de los métodos static es que se resuelven en tiempo de compilación y no pueden ser sobreescritos.
  • Los métodos estáticos no pueden hacer uso de this.
  • No pueden ser abstractos.

Uso de static en Block

Un block en Java (grupo de una o más sentencias entre llaves), puede ir acompañado de static para realizar inicialización de variables static.

Vamos a ver un ejemplo de uso en el que cargamos un LinkedList de frutas:

public class DataLoad {
    public static List<String> fruits= new LinkedList<>();

    static {
        fruits.add("Apple");
        fruits.add("Orange");
        fruits.add("Banana");
    }

}

El uso de blocks para inicializar variables es común cuando queremos inicializar varias o tiene lógica adicional a la inicialización o cuando al inicializar queremos hacer manejo de excepciones.

En el caso en el que queramos tener varios blocks anidados no hay ningún problema, siempre y cuando se abran y se cierren correctamente.

Conclusión

El uso de directiva static en Java, y entender su correcto funcionamiento y cuando se debe de aplicar es imprescindible para desarrollar nuestras aplicaciones. Su correcta aplicación nos puede ayudar a mejorar la legilibilidad de nuestras aplicaciones así como su optimización y rendimiento.

Si necesitas más información puedes escribirnos un comentario o un correo electrónico a refactorizando.web@gmail.com o también nos puedes contactar por nuestras redes sociales Facebook o twitter y te ayudaremos encantados!


Deja una respuesta

Tu dirección de correo electrónico no será publicada.