Java: classe estática?

130

Eu tenho uma classe cheia de funções utilitárias. Instanciar uma instância dela não faz sentido semântico, mas ainda quero chamar seus métodos. Qual é a melhor maneira de lidar com isso? Classe estática? Resumo?

Nick Heiner
fonte
14
Você não pode fazer uma classe estática nível superior pelo caminho ...
Jon

Respostas:

163

Construtor privado e métodos estáticos em uma classe marcada como final.

David Robles
fonte
19
@matt b: Como David Robles aponta em sua resposta, você não precisa finalizar a classe ... ela não pode ser subclassificada porque uma subclasse não poderá invocar um construtor de superclasse porque é privado. No entanto ... não há mal em ser explícito. Mas jfyi :-).
Tom
93

De acordo com o grande livro "Java eficaz" :

Item 4: Aplicar a não instabilidade com um construtor privado

- Tentar impor a não instabilidade tornando uma classe abstrata não funciona.

- Um construtor padrão é gerado apenas se uma classe não contiver construtores explícitos; portanto, uma classe pode ser tornada não instável incluindo um construtor privado:

// Noninstantiable utility class
public class UtilityClass
{
    // Suppress default constructor for noninstantiability
    private UtilityClass() {
        throw new AssertionError();
    }
}

Como o construtor explícito é privado, é inacessível fora da classe. O AssertionError não é estritamente necessário, mas fornece seguro caso o construtor seja acidentalmente invocado de dentro da classe. Garante que a classe nunca será instanciada sob nenhuma circunstância. Esse idioma é levemente contra-intuitivo, pois o construtor é fornecido expressamente para que não possa ser chamado. Portanto, é aconselhável incluir um comentário, como mostrado acima.

Como efeito colateral, esse idioma também impede que a classe seja subclassificada. Todos os construtores devem chamar um construtor de superclasse, explícita ou implicitamente, e uma subclasse não teria nenhum construtor de superclasse acessível para invocar.

David Robles
fonte
1
Por que você escolheu AssertionErrorsobre outras alternativas como IllegalStateException, UnsupportedOperationException, etc?
Pacerier
@Pacerier Veja isso .
bcsb1001
@ bcsb1001, isso nos leva a isso .
Pacerier
21

Parece que você tem uma classe de utilitário semelhante ao java.lang.Math .
A abordagem lá é classe final com construtor privado e métodos estáticos.

Mas cuidado com o que isso faz com a testabilidade, recomendo a leitura deste artigo Os métodos estáticos são a morte da testabilidade

coroa
fonte
O que é java.lang.Math "morte para testabilidade"?
Pacerier
1
Pode ser interessante ver como ela é pontuada quando executada em code.google.com/p/testability-explorer
crowne
6

Só para nadar contra a corrente, os membros e as classes estáticas não participam do OO e, portanto, são maus. Não, não é mau, mas é sério, eu recomendaria uma classe regular com um padrão único para acesso. Dessa forma, se você precisar substituir o comportamento em qualquer caso no futuro, não será uma grande reformulação. OO é seu amigo :-)

Meu $ .02

Bennett Dill
fonte
17
Singletons também são considerados maus.
Dan Dyer
3
Você usa o construtor privado para impedir que alguém instanciar ou subclassificar a classe. Veja a resposta de David Robles: stackoverflow.com/questions/1844355/java-static-class/…
rob
5
Singleton não é mais mal do que a injeção de dependência :)
irreputable
12
OO tem seu lugar, mas há momentos em que simplesmente não é prático ou seria um desperdício de recursos - por exemplo, algo tão simples quanto Math.abs (). Não há razão para instanciar um objeto apenas para instanciar um objeto, quando uma chamada de método estático também lhe teria servido sem nenhuma sobrecarga de OO. ;)
Rob
2
@rob re OO, concordo, Math.Abs ​​provavelmente nunca precisa de uma instância. Quando ouço "eu tenho uma classe de utilitário", vejo Math.Avg (), onde agora você precisa adicionar suporte para uma média ponderada. Eu vejo um gerador de URL, param in, url out que precisa ser refatorado para oferecer suporte a href, ou somente url, etc. etc. Por esses motivos, ter a classe de utilitário baseada em OO pode pagar. Além disso, agora vou largar a tática defensiva OO padrão, testando! / me patos
Bennett Dill
3

comente os argumentos do "construtor privado": vamos lá, os desenvolvedores não são tão estúpidos; mas eles são preguiçosos. criar um objeto e chamar métodos estáticos? não vai acontecer.

não gaste muito tempo para garantir que sua classe não possa ser mal utilizada. tenha um pouco de fé para seus colegas. e sempre há uma maneira de abusar da classe, não importa como você a proteja. a única coisa que não pode ser mal empregada é completamente inútil.

irreputável
fonte
7
Alguém que tenha visto (no código de produção, e não apenas no código do aluno) object.staticMethod Acho que você superestima as habilidades do Joe Random Programmer! :-P
TofuBeer 04/12/2009
2
  • Classe final e construtor privado (bom, mas não essencial)
  • Métodos estáticos públicos
fastcodejava
fonte
1

Não faz sentido declarar a classe como static. Apenas declare seus métodos statice chame-os do nome da classe como normal, como a classe Math de Java .

Além disso, mesmo que não seja estritamente necessário tornar o construtor privado, é uma boa ideia fazê-lo. Marcar o construtor como privado impede que outras pessoas criem instâncias da sua classe e, em seguida, chame métodos estáticos a partir dessas instâncias. (Essas chamadas funcionam exatamente da mesma forma em Java, são apenas enganosas e prejudicam a legibilidade do seu código.)

Bill the Lizard
fonte
1
Além disso, não esqueça de criar um construtor privado.
Asaph
@ Asaph: concordou. Eu adicionei um pouco nisso à minha resposta. Obrigado.
Bill o Lagarto
Se você deseja métodos estáticos dentro de uma classe interna, a classe também deve ser estática.
Rui Marques