De forma bem simplificada, se um método não depende de nenhuma informação de uma instância, então ele pode ser estático. Uma regra geral seria: "Faz sentido chamar este método, mesmo se eu não tiver criado nenhuma instância?" - se a resposta for "sim", provavelmente o método deveria ser estático.
Um exemplo são os métodos da classe java.lang.Math
, que basicamente servem para fazer operações matemáticas. Por exemplo, para arredondar um número para baixo vc usa Math.floor(numero)
. Faz sentido eu precisar criar uma instância de Math
para fazer tal cálculo? Imagine se eu precisasse fazer Math m = new Math()
para só depois chamar m.floor(numero)
. Neste caso não é necessário, porque a operação floor
não precisa de nenhum estado associado à uma hipotética instância de Math
(aliás, eu nem consigo criar uma instância, já que o construtor da classe é privado - isso foi proposital, justamente para indicar que não é para ninguém ficar criando instâncias desnecessárias).
Um outro exemplo é quando você quer controlar a forma como as instâncias são criadas, e em vez de criar vários construtores, cria factory methods (como já citado pelo Maniero), que por sua vez delegam para o construtor. Um exemplo disso é a classe java.time.LocalDate
, que possui vários métodos estáticos para criar datas de diferentes maneiras (now
para criar a cada atual, of(ano, mes, dia)
para uma data específica, etc). Internamente todos esses métodos validam os dados e repassam para o construtor da classe, que é privado (ou seja, a única forma de criar instâncias é usando os métodos estáticos). Assim, cada método cuida da sua parte específica (now
chama o relógio do sistema e extrai o dia, mês e ano; of
só precisa validar os valores do dia, mês e ano, etc) e no final eles usam o construtor para criar a instância.