Java: quando usar métodos estáticos

911

Gostaria de saber quando usar métodos estáticos? Digamos se eu tenho uma classe com alguns getters e setters, um método ou dois, e quero que esses métodos sejam invocáveis ​​apenas em um objeto de instância da classe. Isso significa que eu deveria usar um método estático?

por exemplo

Obj x = new Obj();
x.someMethod

ou

Obj.someMethod

(é este o caminho estático?)

Estou um pouco confuso!

KP65
fonte

Respostas:

1458

Uma regra prática: pergunte a si mesmo "Faz sentido chamar esse método, mesmo que nenhum objeto tenha sido construído ainda?" Nesse caso, deve ser definitivamente estático.

Portanto, em uma classe, Carvocê pode ter um método:

double convertMpgToKpl(double mpg)

... o que seria estático, porque é possível saber no que 35mpg se converte, mesmo que ninguém jamais tenha construído um Car. Mas este método (que define a eficiência de um particular Car):

void setMileage(double mpg)

... não pode ser estático, pois é inconcebível chamar o método antes que qualquer Cartenha sido construído.

(A propósito, o inverso nem sempre é verdadeiro: às vezes você pode ter um método que envolve dois Carobjetos e ainda assim querer que seja estático. Por exemplo:

Car theMoreEfficientOf( Car c1, Car c2 )

Embora isso possa ser convertido para uma versão não estática, alguns argumentam que, como não há uma opção "privilegiada", o que Caré mais importante, você não deve forçar um chamador a escolher um Carcomo o objeto que você chamará. método ativado. Essa situação é responsável por uma fração bastante pequena de todos os métodos estáticos.)

não-apenas-yeti
fonte
325
Alguns bons exemplos aqui. Eu acrescentaria, no entanto, que "estático" geralmente é valioso quando você sabe que algo não vai mudar entre instâncias. Se esse for o caso, eu realmente consideraria o "Princípio de responsabilidade única", que implica que uma classe deve ter uma responsabilidade e, portanto, apenas um motivo para mudar. Eu acho que devemos considerar mover a função "ConvertMpgToKpl (double mpg)" e métodos semelhantes para sua própria classe. O objetivo de um objeto de carro é permitir a instanciação de carros, não fornecer uma comparação entre eles. Aqueles devem ser externos à classe.
Zack Jannsen 13/08/2012
34
Eu acho que prefiro o método Car#isMoreEfficientThan(Car). Tem a vantagem de que carro que você devolve em um empate não é arbitrário. É óbvio pelo título do método o que é retornado em um empate.
Cruncher
5
Eu também tomaria cuidado ao criar um método estático que esteja usando algum recurso externo (sistema de arquivos, banco de dados etc.). Esse tipo de estática pode tornar horrível testar os métodos de consumo. Eu, pessoalmente, tento manter a estática no domínio da "utilidade".
Seth M.
7
De fato, deve ser implementado como um comparador .
Dogweather 03/02
3
@ B1KMusic Claro. O que quero dizer com "qual carro é devolvido em um empate" é "mapas verdadeiros para o carro chamado e mapas falsos para o carro passado". É sem ambiguidade.
Cruncher
538

Defina métodos estáticos apenas nos seguintes cenários:

  1. Se você estiver escrevendo classes de utilitário e elas não devem ser alteradas.
  2. Se o método não estiver usando nenhuma variável de instância.
  3. Se alguma operação não depende da criação da instância.
  4. Se houver algum código que possa ser facilmente compartilhado por todos os métodos da instância, extraia esse código em um método estático.
  5. Se você tiver certeza de que a definição do método nunca será alterada ou substituída. Como métodos estáticos não podem ser substituídos.
Mohd
fonte
45
bons pontos, mas são requisitos se você deseja tornar um método estático, não razões para fazê-lo.
Tetsuo
4
@ Ohm sobre o requisito 5: quando você pode ter 100% de certeza de que um método nunca será alterado ou substituído? Não há sempre fatores desconhecidos que você não pode levar em consideração no momento em que escreve seu método estático?
PixelPlex 31/08/2015
8
"Classes de utilidade" são muito difíceis de raciocinar, o ruim é que mais cedo ou mais tarde tudo começa a 'parecer' um utilitário (sim, estou me referindo ao pacote "util" que é inchado, intocável e mal testado), e seus casos de teste precisarão de mais trabalho (zombar de utilitários estáticos é DURO). Prefira objetos primeiro.
Sergio
2
@ Ohh esta resposta é exatamente o que estou procurando. Eu enfrentei muitos problemas usando métodos estáticos em multithreading. Você pode, por favor, elaborar os pontos 2 e 3 mais (com o exemplo 100 pontos positivos)
Prakash Pandey
Eu acho que uma "classe estática" deve ser inventada se você for usar variáveis ​​e métodos estáticos.
Robert Rocha
182

Existem alguns motivos válidos para usar métodos estáticos:

  • Desempenho : se você deseja que algum código seja executado e não instancia um objeto extra para fazê-lo, coloque-o em um método estático. A JVM também pode otimizar muito os métodos estáticos (acho que já li James Gosling declarando que você não precisa de instruções personalizadas na JVM, pois os métodos estáticos serão tão rápidos, mas não conseguem encontrar a fonte - portanto pode ser completamente falso). Sim, é micro-otimização e provavelmente desnecessário. E nós programadores nunca fazemos coisas desnecessárias só porque são legais, certo?

  • Praticidade : em vez de ligar new Util().method(arg), ligar Util.method(arg)ou method(arg)com importações estáticas. Mais fácil, mais curto.

  • Adicionando métodos : você realmente queria que a classe String tivesse um removeSpecialChars()método de instância, mas não existe (e não deveria, pois os caracteres especiais do seu projeto podem ser diferentes dos do outro) e não pode ser adicionado (desde Java é um pouco sensato), então você cria uma classe de utilitário e chama em removeSpecialChars(s)vez de s.removeSpecialChars(). Doce.

  • Pureza : tomando algumas precauções, seu método estático será uma função pura , ou seja, a única coisa de que depende são seus parâmetros. Entrada de dados, saída de dados. Isso é mais fácil de ler e depurar, pois você não precisa se preocupar com peculiaridades de herança. Você também pode fazer isso com métodos de instância, mas o compilador o ajudará um pouco mais com métodos estáticos (não permitindo referências a atributos de instância, substituindo métodos etc.).

Você também precisará criar um método estático se quiser criar um singleton, mas ... não. Quero dizer, pense duas vezes.

Agora, mais importante, por que você não gostaria de criar um método estático? Basicamente, o polimorfismo sai da janela . Você não poderá substituir o método nem declará-lo em uma interface (pré-Java 8) . É preciso muita flexibilidade do seu design. Além disso, se precisar de estado , você terá muitos bugs de concorrência e / ou gargalos, se não for cuidadoso.

tetsuo
fonte
1
Muitas boas razões listadas aqui sobre quando estática podem ser úteis. Mais um que eu posso pensar é que os testes de escrita de unidade para tais métodos é simplesmente simples
nilesh
@tetsuo Obrigado! Sua explicação é muito clara e os motivos apresentados são muito lógicos e fazem muito sentido.
Deniss M. #
3
E nós programadores nunca fazemos coisas desnecessárias só porque são legais, certo? +1
Scaramouche
Dito isto um método estático torna-se uma função chamada completo stackoverflow.com/questions/155609/...
Ivanzinho
Concordo com desempenho e praticidade, mas não com pureza. O método estático pode modificar membros estáticos da classe (que podem ser privados). Isso pode ser útil. Por exemplo, você pode ter um método como "estático sincronizado int assignateID () {return idNext ++;}". De fato, um método estático pode ser tão puro ou impuro quanto um método não estático em termos de efeitos colaterais.
Adam Gawne-Cain 6/09/19
42

Depois de ler os artigos de Misko, acredito que os métodos estáticos são ruins do ponto de vista de teste. Você deve ter fábricas (talvez usando uma ferramenta de injeção de dependência como o Guice ).

como posso garantir que tenho apenas algo

só tenho uma de alguma coisa O problema de "como garantir que só tenho uma de alguma coisa" é bem contornado. Você instancia apenas um único ApplicationFactory no seu principal e, como resultado, apenas instancia uma única instância de todos os seus singletons.

O problema básico dos métodos estáticos é que eles são código processual

O problema básico dos métodos estáticos é que eles são código processual. Não tenho idéia de como testar o código processual de unidade. O teste de unidade pressupõe que eu possa instanciar um pedaço do meu aplicativo isoladamente. Durante a instanciação, conecto as dependências com zombarias / amistosos que substituem as dependências reais. Com a programação procedural, não há nada para "conectar", pois não há objetos, o código e os dados são separados.

Alfred
fonte
20
Não entendo a parte de não poder testar o código processual da unidade. Você não apenas configura casos de teste que mapeiam a entrada correta para corrigir a saída usando o método estático junto com a classe como sua "unidade"?
TJB
2
Você poderia fazer isso para testar essas funções. Mas ao usar esses métodos estáticos em outras classes que você deseja testar, acredito que você não pode falsificá-los (zombes / amistosos) ou qualquer coisa, porque você não pode instanciar uma classe.
Alfred
4
@ Alfred: Dê uma olhada no PowerMock, que tem a capacidade de zombar de métodos estáticos. Usando o PowerMock, existem alguns cenários, se houver, em que você encontra dependências de métodos que não podem ser ridicularizadas.
Carles Sala
7
Você pode testar estática de teste de unidade usando o PowerMock, mas em breve descobrirá que o espaço da Permgen está acabado (feito isso, a camiseta) e ainda é desagradável. A menos que você SAIBA (com base em pelo menos uma década de sua própria experiência em idiomas OO verdadeiros, não migrando de C), NÃO O FAÇA. Sério, o pior código que eu já vi veio do uso de estática de um desenvolvedor incorporado e, na maioria dos casos, ficamos presos a ele para sempre, e a adição de mais códigos nos trancou ainda mais no monolito modificável. Acoplamento frouxo: não, testável: apenas modificável: NUNCA. Evitar!
User1016765 de
14
Eu posso entender a dificuldade de testar métodos estáticos que dependem do estado estático. Mas quando você está testando métodos estáticos sem estado como Math.abs()ou Arrays.sort(), mesmo métodos nos quais você pode passar todas as dependências , não vejo como isso impediria o teste de unidade. Eu diria que uma regra simples é: se você tiver algum motivo para zombar da lógica processual, não a coloque em um método estático. Eu nunca tive um motivo para zombar Arrays.sort()ou Math.abs().
218 Andy Andy
36

Um staticmétodo é um tipo de método que não precisa que nenhum objeto seja inicializado para ser chamado. Você notou que staticé usado na mainfunção em Java? A execução do programa começa a partir daí sem a criação de um objeto.

Considere o seguinte exemplo:

 class Languages 
 {
     public static void main(String[] args) 
     {
         display();
     }

     static void display() 
     {
         System.out.println("Java is my favorite programming language.");
     }
  }
Zishan
fonte
melhor resposta, na verdade
Yahya
20

Métodos estáticos em java pertencem à classe (não uma instância dela). Eles não usam variáveis ​​de instância e geralmente recebem informações dos parâmetros, executam ações e retornam algum resultado. Os métodos de instâncias estão associados a objetos e, como o nome indica, podem usar variáveis ​​de instância.

Kevin Sylvestre
fonte
12

Não, métodos estáticos não estão associados a uma instância; eles pertencem à classe. Métodos estáticos são seu segundo exemplo; Os métodos de instância são os primeiros.

duffymo
fonte
1
Você deve usar métodos estáticos se não precisar de manipulações de estado do objeto.
MastAvalons
11

Se você aplicar uma palavra-chave estática a qualquer método, ela será conhecida como método estático.

  1. Um método estático pertence à classe e não ao objeto de uma classe.
  2. Um método estático chamado sem a necessidade de criar uma instância de uma classe.
  3. O método static pode acessar o membro de dados estáticos e pode alterar o valor dele.
  4. Um método estático pode ser acessado apenas usando o nome de um nome estático de ponto de classe. . . exemplo: Student9.change ();
  5. Se você deseja usar campos não estáticos de uma classe, deve usar um método não estático.

// Programa de alteração da propriedade comum de todos os objetos (campo estático).

class Student9{  
 int rollno;  
 String name;  
 static String college = "ITS";  

 static void change(){  
 college = "BBDIT";  
 }  

 Student9(int r, String n){  
 rollno = r;  
 name = n;  
 }  

 void display (){System.out.println(rollno+" "+name+" "+college);}  

public static void main(String args[]){  
Student9.change();  

Student9 s1 = new Student9 (111,"Indian");  
Student9 s2 = new Student9 (222,"American");  
Student9 s3 = new Student9 (333,"China");  

s1.display();  
s2.display();  
s3.display();  
}  }

O / P: 111 BBDIT indiano 222 BBDIT americano 333 China BBDIT

IndianProgrammer1234
fonte
10

Os métodos estáticos não estão associados a uma instância, portanto, eles não podem acessar nenhum campo não estático na classe.

Você usaria um método estático se o método não usar nenhum campo (ou apenas campos estáticos) de uma classe.

Se qualquer campo não estático de uma classe for usado, você deverá usar um método não estático.

Carsten
fonte
1
Resposta clara, curta e simples.
1928 Josi Josi
8

Os métodos estáticos devem ser chamados na classe, os métodos de instância devem ser chamados nas instâncias da classe. Mas o que isso significa na realidade? Aqui está um exemplo útil:

Uma classe de carro pode ter um método de instância chamado Accelerate (). Você só pode acelerar um carro, se o carro realmente existir (foi construído) e, portanto, esse seria um método de instância.

Uma classe de carro também pode ter um método de contagem chamado GetCarCount (). Isso retornaria o número total de carros criados (ou construídos). Se nenhum carro foi construído, esse método retornaria 0, mas ainda assim poderia ser chamado e, portanto, teria que ser um método estático.

Charlie Seligman
fonte
6

Na verdade, usamos propriedades e métodos estáticos em uma classe, quando queremos usar alguma parte do nosso programa que deve existir lá até que o programa esteja em execução. E sabemos que, para manipular propriedades estáticas, precisamos de métodos estáticos, pois eles não fazem parte da variável de instância. E sem métodos estáticos, manipular propriedades estáticas é demorado.

Sagar
fonte
Manter um estado em variáveis ​​estáticas é uma coisa ruim a ser feita por várias razões - como segurança com vários threads, depuração, encapsulamento de dados etc. etc Métodos estáticos são bons se forem funções puras (trabalhar apenas com parâmetros, sem alterá-los). Um bom exemplo seria uma classe de utilidade, por exemplo, cálculos matemáticos.
Vladimir Demirev 7/11
5

Use um método estático quando desejar acessar o método sem uma instância da classe.

Jamey
fonte
29
Isso não fornece nenhuma justificativa para o design de um programa.
precisa saber é o seguinte
4

Estático: Obj.someMethod

Use staticquando desejar fornecer acesso no nível de classe a um método, ou seja, onde o método deve ser chamado sem uma instância da classe.

Finbarr
fonte
4

Os métodos estáticos não precisam ser invocados no objeto e é quando você o utiliza. Exemplo: seu Main () é estático e você não cria um objeto para chamá-lo.

Vaishak Suresh
fonte
1
Yay! Olhe para onde eu vim enquanto pesquisava perguntas sobre Java noobie! É um mundo pequeno :-)
Deepak
1
@Deepak pequeno mundo, na verdade :)
Vaishak Suresh
4

Métodos e variáveis ​​estáticas são uma versão controlada das funções e variáveis ​​'Globais' em Java. Em que métodos podem ser acessados ​​como classname.methodName()ou classInstanceName.methodName(), ou seja, métodos e variáveis ​​estáticos podem ser acessados ​​usando o nome da classe, bem como instâncias da classe.

A classe não pode ser declarada como estática (porque não faz sentido. Se uma classe é declarada pública, pode ser acessada de qualquer lugar), as classes internas podem ser declaradas estáticas.

Manju Yadav
fonte
3

Métodos estáticos podem ser usados ​​se

  • Não se deseja executar uma ação em uma instância (métodos utilitários)

    Como mencionado em algumas das respostas acima neste post, converter milhas em quilômetros ou calcular a temperatura de Fahrenheit em Celsius e vice-versa. Com esses exemplos usando o método estático, não é necessário instanciar um objeto novo inteiro na memória heap. Considere abaixo

    1. new ABCClass(double farenheit).convertFarenheitToCelcium() 
    2. ABCClass.convertFarenheitToCelcium(double farenheit)

    o primeiro cria uma nova presença de classe para cada método invocado, Desempenho, Prático . Exemplos são a classe StringUtils da biblioteca Math e Apache-Commons abaixo:

    Math.random()
    Math.sqrt(double)
    Math.min(int, int)
    StringUtils.isEmpty(String)
    StringUtils.isBlank(String)
  • Alguém quer usar como uma função simples. As entradas são explicitamente transmitidas e obtêm os dados do resultado como valor de retorno. Herança, a instanciação do objeto não entra em cena. Conciso, legível .

NOTA : Poucas pessoas argumentam contra a testabilidade de métodos estáticos, mas eles também podem ser testados! Com o jMockit, é possível zombar de métodos estáticos. Testabilidade . Exemplo abaixo:

new MockUp<ClassName>() {
    @Mock
    public int doSomething(Input input1, Input input2){
        return returnValue;
    }
};
Amit Kaneria
fonte
3

Métodos estáticos são os métodos em Java que podem ser chamados sem criar um objeto de classe. É pertencer à classe.

Usamos o método estático quando não precisamos ser chamados pelo método instance.

rashedcs
fonte
2

Gostaria de saber quando usar métodos estáticos?

  1. Um uso comum para staticmétodos é acessar staticcampos.
  2. Mas você pode ter staticmétodos, sem referenciar staticvariáveis. Métodos auxiliares sem referenciar staticvariável podem ser encontrados em algumas classes java como java.lang.Math

    public static int min(int a, int b) {
        return (a <= b) ? a : b;
    }
  3. No outro caso de uso, posso pensar nesses métodos combinados com o synchronizedmétodo é a implementação do bloqueio no nível de classe no ambiente multiencadeado.

Digamos se eu tenho uma classe com alguns getters e setters, um método ou dois, e quero que esses métodos sejam invocáveis ​​apenas em um objeto de instância da classe. Isso significa que eu deveria usar um método estático?

Se você precisar acessar o método em um objeto de instância da classe, seu método deverá ser não estático.

A página de documentação do Oracle fornece mais detalhes.

Nem todas as combinações de variáveis ​​e métodos de instância e classe são permitidas:

  1. Os métodos de instância podem acessar variáveis ​​de instância e métodos de instância diretamente.
  2. Os métodos de instância podem acessar variáveis ​​de classe e métodos de classe diretamente.
  3. Os métodos de classe podem acessar variáveis ​​e métodos de classe diretamente.
  4. Os métodos de classe não podem acessar variáveis ​​de instância ou métodos de instância diretamente - eles devem usar uma referência de objeto. Além disso, os métodos de classe não podem usar a palavra-chave this, pois não há instância para isso se referir.
Ravindra babu
fonte
Não podemos acessar campos estáticos através de métodos regulares? Então isso A common use for static methods is to access static fields.não é um argumento.
parsecer
2

Um método estático tem dois objetivos principais:

  1. Para métodos utilitários ou auxiliares que não exigem nenhum estado de objeto. Como não há necessidade de acessar variáveis ​​de instância, ter métodos estáticos elimina a necessidade de o chamador instanciar o objeto apenas para chamar o método.
  2. Para o estado que é compartilhado por todas as instâncias da classe, como um contador. Toda instância deve compartilhar o mesmo estado. Os métodos que apenas usam esse estado devem ser estáticos também.
hemanto
fonte
1

No eclipse, você pode ativar um aviso que ajuda a detectar possíveis métodos estáticos. (Acima da linha destacada há outra que eu esqueci de destacar)

configuração de eclipse

ave4496
fonte
0

Sempre que você não desejar criar um objeto para chamar um método no seu código, apenas declare esse método como estático. Como o método estático não precisa de uma instância para ser chamada, mas a captura aqui nem todos os métodos estáticos são chamados pela JVM automaticamente. Esse privilégio é usufruído apenas pelo método main () "public static void main [String ... args]" em java porque, em tempo de execução, esse é o método Signature public "static" void main [] procurado pela JVM como um ponto de entrada para inicia a execução do código.

Exemplo:

public class Demo
{
   public static void main(String... args) 
   {
      Demo d = new Demo();

      System.out.println("This static method is executed by JVM");

     //Now to call the static method Displ() you can use the below methods:
           Displ(); //By method name itself    
      Demo.Displ(); //By using class name//Recommended
         d.Displ(); //By using instance //Not recommended
   }

   public static void Displ()
   {
      System.out.println("This static method needs to be called explicitly");
   }
} 

Saída: - Este método estático é executado pela JVM Este método estático precisa ser chamado explicitamente Este método estático precisa ser chamado explicitamente Este método estático precisa ser chamado explicitamente

Amrit
fonte