Digamos que eu tenha uma classe projetada para ser instanciada. Eu tenho vários métodos "auxiliares" particulares dentro da classe que não requerem acesso a nenhum membro da classe e operam apenas em seus argumentos, retornando um resultado.
public class Example {
private Something member;
public double compute() {
double total = 0;
total += computeOne(member);
total += computeMore(member);
return total;
}
private double computeOne(Something arg) { ... }
private double computeMore(Something arg) {... }
}
Existe algum motivo específico para especificar computeOne
e computeMore
como métodos estáticos - ou algum motivo específico para não?
É certamente mais fácil deixá-los como não estáticos, mesmo que eles possam certamente ser estáticos sem causar problemas.
java
static
methods
static-methods
avalys
fonte
fonte
Respostas:
Eu prefiro que tais métodos auxiliares sejam
private static
; o que deixará claro ao leitor que eles não modificarão o estado do objeto. Meu IDE também mostrará chamadas para métodos estáticos em itálico, portanto, saberei que o método é estático sem procurar a assinatura.fonte
protected static
que os tornam testáveis com muita facilidade em uma classe de teste no mesmo pacote.static
(se quisermos apenas para testar).Isso pode resultar em bytecode um pouco menor, já que os métodos estáticos não terão acesso
this
. Não acho que isso faça diferença na velocidade (e, se o fizesse, provavelmente seria pequeno demais para fazer a diferença no geral).Eu os tornaria estáticos, pois geralmente faço isso, se possível. Mas sou só eu.
EDIT: Esta resposta está ficando com voto negativo, possivelmente por causa da afirmação infundada sobre o tamanho do bytecode. Então, eu realmente vou fazer um teste.
Bytecode (recuperado com
javap -c -private TestBytecodeSize
):A invocação do método estático requer dois bytecodes (byteops?):
iconst_0
(Para o argumento) einvokestatic
.A invocação do método não estático requer três:
aload_1
(para oTestBytecodeSize
objeto, suponho),iconst_0
(para o argumento) einvokespecial
. (Observe que, se esses não fossem métodos particulares, teria sido eminvokevirtual
vez deinvokespecial
; consulte JLS §7.7 Invocando métodos .)Agora, como eu disse, não espero que haja grande diferença no desempenho entre esses dois, além do fato de
invokestatic
exigir menos um bytecode.invokestatic
einvokespecial
ambos devem ser um pouco mais rápidos queinvokevirtual
, uma vez que ambos usam ligação estática em vez de dinâmica, mas não faço ideia se um deles é mais rápido que o outro. Também não consigo encontrar boas referências. O mais próximo que posso encontrar é este artigo do JavaWorld de 1997 , que basicamente reafirma o que eu acabei de dizer:Mas muitas coisas mudaram desde 1997.
Então, em conclusão ... acho que ainda estou mantendo o que disse antes. A velocidade não deve ser o motivo para escolher um sobre o outro, pois seria na melhor das hipóteses uma micro-otimização.
fonte
Minha preferência pessoal seria declará-los estáticos, pois é uma bandeira clara que eles são apátridas.
fonte
A resposta é ... depende.
Se member é uma variável de instância específica para o objeto com o qual você está lidando, por que passá-la como parâmetro?
Por exemplo:
fonte
Um motivo pelo qual você pode querer declarar métodos auxiliares estáticos é se precisar chamá-los no construtor da classe "before"
this
ousuper
. Por exemplo:Este é um exemplo um pouco artificial, mas claramente
recoverInt
não pode ser um método de instância nesse caso.fonte
Eu realmente não consigo pensar em vantagens claras para o método estático privado. Dito isto, também não há vantagens específicas em torná-los não estáticos. É principalmente uma questão de apresentação: você pode torná-los estáticos para sublinhar claramente o fato de que eles não estão alterando um objeto.
Para o método com privilégios de acesso diferentes, acho que existem dois argumentos principais:
Além disso, a diferença é bem pequena, e duvido muito que o extra desse ponteiro passado para o método de instância faça uma diferença significativa.
fonte
A resposta correta é:
qualquer método que não obtenha nenhuma informação de um campo e não coloque nenhuma informação em um campo não precisa ser um método de instância. Qualquer método que não use ou altere nenhum campo em sua classe ou objeto também pode ser um método estático.
fonte
Sim.
Mantendo-os como métodos de instância, você se permite fornecer uma implementação diferente posteriormente.
Pode parecer bobagem (e, na verdade, seria se esses métodos fossem usados apenas por você em um programa de 50 linhas), mas em aplicativos maiores ou em bibliotecas usadas por outra pessoa, você pode optar por escolher uma implementação melhor, mas não deseja quebrar o código existente.
Então você cria uma subclasse e retorna isso nas novas versões e, como os métodos foram declarados como métodos de instância, você apenas deixou o polimorfismo fazer seu trabalho.
Além disso, você pode se beneficiar ao tornar o construtor privado e fornecer um método estático de fábrica pelo mesmo motivo.
Portanto, minha recomendação é mantê-los como métodos de instância e evitar estática, se possível.
Aproveite o dinamismo que a linguagem oferece.
Veja aqui um vídeo relacionado: Como criar uma boa API e por que ela é importante
Embora não esteja diretamente relacionado à discussão do método "static vs instance", ele aborda alguns pontos interessantes no design da API.
fonte
Uma questão sobre ter métodos estáticos é que ele pode dificultar o uso do objeto em testes de unidade . O Mockito não pode criar simulações para métodos estáticos e você não pode criar uma implementação de subclasse do método.
fonte
Se o método for basicamente apenas uma sub-rotina que nunca usará previsivelmente as informações de estado, declare-as estáticas.
Isso permite que ele seja usado em outros métodos estáticos ou na inicialização de classes, ou seja:
fonte
A questão estática / não estática se resume a "precisarei realmente usar um objeto dessa classe"?
Então, você está passando o objeto entre diferentes métodos? O objeto contém informações úteis fora do contexto dos métodos estáticos? Existe alguma razão para não definir métodos nos dois sentidos, se você os usar nos dois sentidos?
Se você está nesse dilema, parece-me que você tem todos os dados necessários para o método flutuando no seu código fora do objeto. É isso que voce quer? Seria mais fácil sempre coletar sempre esses dados em um objeto a cada vez? Você pode ser ambivalente em se comprometer com um único modelo. Se você puder fazer tudo de uma maneira, escolha estática ou não estática e siga em frente.
fonte
Minha preferência em casos como esses é fazer
computeOne
ecomputeMore
métodos estáticos. O motivo: encapsulamento. Quanto menos código tiver acesso à implementação da sua classe, melhor.No exemplo que você fornece, você declara que
computeOne
ecomputeMore
não deve acessar os internos da turma; portanto, por que dar a oportunidade aos mantenedores da turma se intrometerem com os internals?fonte
Gostaria de esclarecer algumas coisas que outros pôsteres disseram como informações erradas.
Primeiro, como os métodos são privados, mesmo se você os declarar estáticos, não poderá acessá-los fora desta classe. Em segundo lugar, eles são privados, portanto você não pode substituir na subclasse, portanto, estático ou não estático, não faz diferença. Em terceiro lugar, um método privado não estático pode ser chamado de um construtor da classe também, não precisa ser estático.
Agora, vamos à sua pergunta se um método auxiliar privado deve ser definido como estático ou não estático. Eu irei com a resposta de Steve, pois marcar um método privado estático mostra que esse método é sem estado, pois também sigo essa regra quando codifico.
fonte
Pela experiência, eu afirmaria que esses métodos privados tendem a ser bastante universais e reutilizáveis.
Penso que a primeira coisa a fazer é perguntar se o método pode ser útil fora do contexto de classe atual. Nesse caso, eu faria exatamente o que Todos sugere e extrairia esse método como estático para algumas classes de utilitários, nas quais alguém espere verificar antes de implementar um novo método, fazendo exatamente a mesma coisa.
Tais métodos particulares de uso geral são fonte de grande parte da duplicação de código no projeto, porque cada desenvolvedor os reinventa independentemente no local em que precisa usá-lo. Portanto, a centralização de tais métodos é um caminho a percorrer.
fonte
Mais especificamente para o exemplo que você deu, parece que o objetivo de definir esses métodos é mais para clareza de código quando você está lendo do que para funcionalidade (eles são definidos como privados). Nesse caso, usar a estática realmente não faz nada para você, pois o objetivo da estática é expor a funcionalidade da classe.
fonte
Uma razão é que, sendo tudo igual, as chamadas de método estático devem ser mais rápidas. Os métodos estáticos não podem ser virtuais e não levam uma referência implícita.
fonte
Como muitas pessoas disseram, faça como estática ! Aqui está a regra geral que sigo: Se você acha que o método é apenas uma função matemática, ou seja, sem estado, não envolve nenhuma variável de instância (=> sem cores azuis vars [no eclipse] no método) e o resultado de o método será o mesmo para o número 'n' de chamadas (com os mesmos parâmetros, é claro), depois marque esse método como STATIC.
E se você acha que esse método será útil para outra classe, mova-o para uma classe Util, caso contrário, coloque o método como privado na classe de amostra. (minimizando a acessibilidade)
fonte
Fora do tópico: eu manteria os métodos auxiliares em uma classe autônoma de utilitário / auxiliar, apenas com métodos estáticos.
O problema de ter métodos auxiliares no ponto de uso (leia 'mesma classe') é que alguém abaixo da linha pode simplesmente optar por postar seus próprios métodos auxiliares não relacionados no mesmo local
fonte
A vantagem dos métodos estáticos privados é que eles podem ser reutilizados posteriormente, se você precisar reinicializar a variável de classe.
fonte
Sem o modificador estático, você não pode descobrir que o método é sem estado sem análise adicional, que pode ser feita facilmente quando você (re) escreve o método.
O modificador "estático" pode fornecer idéias sobre refatoração, além de outras coisas que outros podem achar inúteis. Por exemplo, movendo o método para alguma classe Utility ou convertendo-o em um método membro.
fonte
Eu os declararia estáticos para sinalizá-los como apátridas.
O Java não possui um mecanismo melhor para operações menores que não são exportadas, então acho que a estática privada é aceitável.
fonte