10 de maio de 2019

JAVA 8: Entendo uso de métodos static em Classes utilitárias e aplicando em Interfaces!

Métodos static em Interfaces do Java 8 simplificam e reduzem seu código, além de poderem aumentar sua produtividade. Aprenda agora e aumente a qualidade do seu código!

Métodos static em classes utilitárias

É comum a necessidade de criar métodos static para que possam ser chamados sem a necessidade de criar um novo objeto. A própria JDK possui várias classes que contém somente métodos static, por exemplo: java.lang.Math, java.util.Collections, java.util.Arrays, java.util.stream.Streams.

E a JDK deixa claro que não quer que você crie instâncias dessas classes. Veja os construtores retirados diretamente do código fonte da JDK:

 // Suppresses default constructor, ensuring non-instantiability.
 private Collections() {
 }
 // Suppresses default constructor, ensuring non-instantiability.
 private Arrays() {}
/**
 * Don't let anyone instantiate this class.
 */
private Math() {}
private Streams() {
    throw new Error("no instances");
}

Além disso, inúmeras bibliotecas disponibilizam classes utilitárias que também contém apenas métodos static, como aquelas dos projetos Apache Commons.

O problema com classes utilitárias

Esse tipo de classe normalmente é chamada de utilitária, por isso a terminação *Util em muitas delas, principalmente nas da Apache. Essas classes basicamente não seguem o padrão de Orientação à Objetos (OO), pois contém apenas código estruturado.
Aliás, se fosse possível no Java, esses métodos nem estariam dentro de uma classe.

Quando utilizar classes utilitárias?

O fato de não seguir os conceitos da OO não é necessariamente algo ruim. Porém, imagine a seguinte situação: você possui uma classe Pessoa e quer fazer um método utilitário static. O que você acha que faz mais sentido: criar uma classe PessoaUtil com esse método, ou criá-lo na própria classe Pessoa? Eu advogo pela segunda opção. Ou seja, só vejo sentido em criar uma classe utilitária quando:

  • Você não é o dono da classe original, ou não consegue modificá-la; ou
  • Você possui uma estrutura de interfaces e esse método utilitário serve para todas elas. Este é o caso da classe java.util.Collections.

Quer dizer, eu defendia isso até o Java 8. Agora, no segundo caso, a própria interface pode ter métodos static.


Métodos static em Interfaces do Java 8

A partir do Java 8, é possível criar métodos static na própria interface:

  interface Corredor {
    static double calculeVelocidade(double tempo, double distancia) {
      return distancia/tempo;
    }
  }

Ou seja, nesse caso, é possível chamar o método da Interface sem instanciar um novo objeto:

    double velocidade = Corredor.calculeVelocidade(5.0, 10.0);
    System.out.println(velocidade);

Sendo assim, mesmo que você tenha uma estrutura de interfaces, você poderia criar seus métodos static dentro da interface apropriada.

Claro, existem exceções à regra, e talvez ainda há casos parecidos em que faça sentido criar uma classe utilitária. A questão é que agora você tem uma nova opção a considerar.

Métodos static em Interfaces NÃO fazem parte da API

É muito importante lembrar que os métodos criados como static não fazem parte da API da Interface. Ou seja, eles realmente são elementos da Interface. Assim como métodos static de uma classe são elementos da classe.

Por isso, o código abaixo não compila, por conta das linhas 3 e 7.

  public static void main(String[] args) {
    // NÃO COMPILA - a classe Pessoa não possui o método calculeVelocidade
    double velocidade = Pessoa.calculeVelocidade(5.0, 10.0);
    System.out.println(velocidade);
    
    // NÃO COMPILA - o objeto instância de Pessoa não possui o método calculeVelocidade
    double velocidade2 = new Pessoa().calculeVelocidade(5.0, 10.0);
    System.out.println(velocidade2);
  }
  
  interface Corredor {
    static double calculeVelocidade(double tempo, double distancia) {
      return distancia/tempo;
    }
  }
  
  class Pessoa implements Corredor {}

Ou seja, não é possível chamar o método static da interface diretamente em classes que implementam aquela interface.

Métodos static em Interfaces são public e NÃO são abstract

Por definição, até o Java 8, todos os métodos de uma interface eram public e abstract, mesmo que você não declarasse-os assim. Veja no exemplo abaixo:

  interface Corredor {
    public abstract void correr();
    void correrRapido(); // também é public e abstract
  }

Os métodos static continuam sendo obrigatoriamente public, porém não são abstract. E faz todo sentido, afinal eles contém uma implementação.

Parabéns! Agora você conhece melhor as interfaces do Java 8! Você pode utilizar esse conhecimento para entregar no prazo soluções de alta qualidade.

E você? Já utiliza métodos static em Interfaces? Já teve que dar manutenção em algum código assim? Lembra de situações em que você poderia ter se beneficiado dessa nova opção? Deixe um comentário!


Veja também o vídeo no YouTube!

JAVA 8: Utilize métodos STATIC em INTERFACES e simplifique seu código!

Share