Lá vai:
Há mais motivos para se usar static do que ter ou não performance. Então não estou apoiando o uso de static para performance.
Métodos estáticos e finais são tratados pela JVM como Inline. Sempre que puderem usem static e/ou final (final com algumas considerações).
Um cache interno vai para um estado mono mórfico em primeira convocação, e permanece nesse estado, desde que o tipo de receptor exato (não um subtipo) é repetido a cada momento.
Um cache interno vai para um “megamorphic state” se um segundo tipo de receptor é encontrado.
Chamadas Megamorphic de construção utilizam codificações ocultas vtable e rentáveis, corrigidas em pelo JVM e o compilador não precisará gerenciá-las.
http://wikis.sun.com/display/HotSpotInternals/PerformanceTechniques .
Então, static em métodos não afeta a performance, isso não quer dizer que vamos sair por ai definindo tudo como static.
Além disso; Construtores públicos em Java tornam mais difícil para os desenvolvedores decidirem qual construtor chamar, porque não comunicam intenção.
Por exemplo:
//Vamos ao mais usual, o que eu não gosto de fazer.
persistencia.insert(new NomeObjeto(descricao, grupo));
persistencia.update(new NomeObjeto(descricao, grupo)); //Aqui foi usado o construtor errado. Na verdade, nem é costume criar esses construtores, na maioria das vezes usam set depois de usar new.
No exemplo do update o objeto não possui o código necessário usado para atualizar com DAO e esse é um estado para insert!! Imagine quando vc possuir N contrutores, ficará dificil saber qual usar para que uma operação seja bem sucedida. “Quando se deve enviar zero para o código?”, “Quando se deve enviar null para o contrutor?”.
Todo mundo que usa “new MulherObjeto()” sem um método de Criação usa configuradores setAlgumaCoisa() quase uma centena de vezes em um único sistema para configurar esse mesmo objeto. Nisso mora a perda de tempo mascarada.
Car ferrari = new Ferrari(); //Ferrari é uma classe concreta, mas não em sua intenção de código e em sua criação caiu em uso para a abstração, pois apenas é do tipo Ferrari de Car até que seja configurado.
//Agora ela vira uma Ferrari concreta recebendo características.
ferrari.setCor(Ferrari.ColorRed);
ferrari.setModel(Ferrari.MODEL_2009);
ferrai.setMaxVelocy(ferrari.testMotor())
ferrari.runWhenPossible();
Car ferrari = new Ferrari(Ferrari.COLOR_RED, Ferrari.MODEL_2009);
//Como ficaria a Classe Ferrari usando construtor com fields.
public Ferrari (int color, int model) {
this.setColor(color);
this.setModel(model);
this.setMaxVelocy(testMotor());
}
Então algum desavisado faria assim: Car ferrari = new Ferrari().runWhenPossible(); //vai dar merda , PORQUE o carro não foi configurado como deveria…
Problemas:
Toda vez que uma Ferrari for criada, ela terá que ser configurada; e por quem não entende nada de Ferrari. ;).
Redundância de código.
Dá muitas possibilidades de criação, o que não é bom para um carro; por exemplo: a velocidade máxima pode ser configurada com 10km, o modelo pode receber uma cor que não existe para aquele ano, e certamente será necessária a criação de uma regra que lançará uma exceção quando alguém configurar errado. Para quem adora complexidades e exceções isso pode parecer mais eficiente com os prazos; mas não para mim!
//Agora vamos a mais performática, fácil, mais rápida para desenvolvimento, mais coesa, mais tudo…
Ferrari.getModel2009Red().runWhenPossible(); //Not problem, it's OK!
//Como ficaria a Classe Ferrari.
private Ferrari (fint color, final int model) {
this.color = color;
this.model = model;
this.maxVelocy = testMotor());
}
public static Ferrari getModel2009Red() { //Resume a intenção de obter um Model Red 2009, economiza TEMPO no desenvolvimento.
return new Ferrari(Ferrari.COLOR_RED, Ferrari.MODEL_2009, ... mais);
}
//sem métodos configuradores para setColor(), setModel(), setMaxVelocy(), o que reduz e muito o acoplamento, entre outros.
O JVM pode ainda compilar NATIVAMENTE por causa da quantidade de chamadas, não precisará gerenciar, e no nome do método será expresso a intenção de negócio.
Um erro comum é afirmar que métodos de Factory só podem ser aplicados com Singleton, ou são Singleton. Isso é um engano. O padrão que eu descrevi acima pode ser chamado de: “Static Factory Method”, ou simplesmente: Método de Criação. Isso porque ainda não fornece acoplamento fraco como um Factory Method genuíno ou Abstract para famílias de objetos relacionados.
Agora vamos falar do uso modificador final, com intenção de desempenho.
“é exagero”, “é lenda urbana”, “é otimização prematura” um dos principais evangelistas da Sun Brian Goetz afirma! http://www.ibm.com/developerworks/java/library/j-jtp1029.html
Mas será que ele levou em consideração a documentação da Sun?
Lá vai:
At run time, a machine-code generator or optimizer can “inline” the body of a final method, replacing an invocation of the method with the code in its body. Ou seja, a chamada do método é substituída pelo corpo ou retorno do método. http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html no índice 8.4.3.3.
Tudo bem, concordo que é um exagero, otimização prematura, mas não é lenda, é oficial da Sun:
In the past, programmers often inserted the “final” keyword for exactly this reason. Or to better facilitate inlining and increase execution speed, they would combine many smaller methods into one larger method. But in many ways, such techniques defeat the entire facility of modularization and reusability built into the programming language.
Unlike traditional virtual machines, the Java HotSpot VM is able to inline the class without the “final” keyword: http://java.sun.com/developer/technicalArticles/Networking/HotSpot/inlining.html
Conclusões: Diretamente do departamento de obscuridade do Fábio, tirem as suas conclusões.
James Gosling é o criador do Java, Brian é Evangelista.
Abraços,
Fábio Henrique.
Novo Internet Explorer 8: traduza com apenas um clique. Baixe agora, é grátis!