É vantagem usar static e final? [RESOLVIDO]

É vantagem eu sair colocando static e final em todos o métodos e atributos que aceitarem esses modificadores?
Eu tenho ganho de desempenho considerável utilizando muito algum desses dois?

não é vantagem, uma vez que você precise trabalhar com mais de uma instancia para cada objeto…

O static e final em conjunto deve ser usado apenas para constantes.

Dê sempre preferência ao projeto de suas classes e a um código claro, ao invés da performance. Classes bem projetadas podem ser facilmente otimizadas, enquanto as mal projetadas, não.

Quando for otimizar seu código, use um profiler para identificar os pontos com problema e otimize somente esses lugares. Deixe o código otimizado documentado, explicando o motivo da otimização e os ganhos com seu novo algoritmo, assim você não corre o risco de alguém desfazer o código da otimização por engano.

O compilador faz um trabalho muito bom com otimizações. Como já foi demonstrado com o C++, não é necessário dar dicas a ele com a palavra final e ele geralmente fará um trabalho muito melhor do que você nesse sentido. Do contrário do C++, o java é capaz de analisar o código em tempo de execução e fazer inline de métodos on the fly.

Para mais informações, dê uma lida nos artigos, do Brian Goetz:
Java theory and practice: Is that your final answer?
Java theory and practice: Urban performance legends

Você terá ganho significativo de performance escolhendo algoritmos eficientes e usando bem a API do java (que já tem algoritmos assim prontos). Por exemplo, se você ainda ordena uma lista com Bubble sort, ao invés de simplesmente chamar Collections.sort (que usa um QuickSort modificado), certamente terá aplicações de performance baixa.

Vale a pena dar uma olhada neste endereços:

static
:arrow:http://www.javapractices.com/Topic2.cjp
:arrow:http://www.javapractices.com/Topic195.cjp

final
:arrow:http://www.javapractices.com/Topic23.cjp

fw

Uma coisa que é interessante é usar “final” para parâmetros e variáveis locais inicializadas.
Isso normalmente evita alguns erros bobos de programação que ocorrem porque a gente sempre esquece que parâmetros são passados por valor, não por referência.

Exemplo: por que este código não funciona como desejado?

void swap (String s1, String s2) {
     String tmp = s1; 
     s1 = s2; 
     s2 = tmp;
}

Se você passar os parâmetros para “final”, vai ver por que é que não funciona:

void swap (final String s1, final String s2) {
     String tmp = s1; 
     s1 = s2;  // erro de compilação aqui
     s2 = tmp; // erro de compilação aqui
}

[quote=wellington7]É vantagem eu sair colocando static e final em todos o métodos e atributos que aceitarem esses modificadores?
Eu tenho ganho de desempenho considerável utilizando muito algum desses dois?[/quote]

cara existe uma grande diferença entre o static e o final, o static diz que q seu metodo pertence a class e q so pode ser chamado por outro metodo static… agora o final diz o seguinte… que seu metodo jamais vai subscrito em sua subclasse… um metodo final ele nao eh herdado uma class final ele nao eh herdado o metodo static tb nao eh herdado mais pode ser redefinido… em uma subclass…

class A{
final void met(){}
}
class B extends A{
//o metodo da class A nao eh herdado  pela class B
}

Vamos ver se entendi…
“final” não é bom para métodos, pois impede que o Java possa fazer sua própria otimização (que seria muito melhor do q a minha).
Mas “final” é muito bom para os atributos e variaveis locais, para impedir que se modifique o valor (quando não se desejar modificar esse valor…)

E o “static” (como estou usando) é muito legal pra atributos ou métodos que se quer acessar sem criar uma instancia da classe. Eu por exemplo estou criando desenhos em celulas da jTable, a classe Desenho tem todos os desenhos como static, eu acesso Desenho.fig1() e ele já desenha, de qualquer parte do programa.

Em outras palavras:
Static = Acesso global, sem necessidade de instancia.
Final = Contante. Na maioria, bom apenas para atributos locais.

Qualquer coisa me corrijam.

Valeu!

Como um adendo, se você quer seguir boas práticas de OOP deve marcar como final todos os métodos que não vai dar suporte. Ou seja: se sua classe não está preparada para trabalhar com uma versão polimórfica de um dado método faça-o final.

Creio que não entendi bem o exemplo, o que exatamente ele deveria realizar que não está realizando?

Abusar de Static nunca é uma boa prática em OO… Tem que se usada nos casos específicos, pois se todos os métodos e classes tivessem static seria como programar em procedural!!

tenha pro regra o seguinte, o único método estático da aplicação é o public static void main

para ter qualquer outro método static tu precisa de um ótimo motivo :smiley:

[quote=Rafael Nunes]
Creio que não entendi bem o exemplo, o que exatamente ele deveria realizar que não está realizando?[/quote]

O código do Thingol deveria trocar o valor dois dois Strings, mas ele não faz isso. Isso porque a função receberá 2 referências para as strings, mas elas são simplesmente cópias das referências originais.

Assim, alterar o valor dentro da função não refletirá em nada fora da função.

Em resumo da ópera:

Use static e final apenas quando isso se refletir ou reforçar uma decisão de projeto, nunca por motivos como performance.

Os modificadores static e final foram criados com um motivo específico e é esse motivo que deve ser levado em conta no momento de utiliza-los.

Pra que?

Para que você não tenha que dar suporte a ele.

A parte de uma classde que pode ser sobrescrita numa subclasse é parte integrante da interface da classe e deve ter seu contrato de sobrescrita especificado exatamente como o contrato de uso de metodos normais.

[quote=ViniGodoy]
O código do Thingol deveria trocar o valor dois dois Strings, mas ele não faz isso. Isso porque a função receberá 2 referências para as strings, mas elas são simplesmente cópias das referências originais.

Assim, alterar o valor dentro da função não refletirá em nada fora da função.[/quote]

Na verdade isso só vai funcionar porque Strings são imutáveis, e mesmo objetos sendo passados como cópia da referência, uma Sting modificada dentro de um método vai funcionar como se a passagem fosse de um tipo primitivo, não refletindo fora do método pois Strings são imutáveis.
Porém com outros tipos de objeto, as mudanças através da referência do parâmetro, vão refletir no objeto fora do método.
Por exemplo:

public static void main(String[] args) {
		Pessoa p = new Pessoa();
		p.setNome("Rafael");
		trocaNome(p);
		System.out.println(p.getNome());

	}

	public static void trocaNome(Pessoa p){
		StringBuilder s = new StringBuilder(p.getNome());
		p.setNome(s.reverse().toString());
	}

Neste caso será impresso ‘leafaR’. Mesmo modificando o valor do objeto dentro do método, a mudança se refletirá no objeto Pessoa que foi criado antes do método.

[quote=urubatan]tenha pro regra o seguinte, o único método estático da aplicação é o public static void main

para ter qualquer outro método static tu precisa de um ótimo motivo :D[/quote]

Bem, eu uso qnd quero ter acesso global a algum método de uma classe sem necessidade de instanciar a classe…
Com por exemplo os desenhos que faço na celula da jTable, apenas chamo

Desenho.fig1();
Desenho.fig2();
Desenho.fig3();

já que todas as figuras da classe Desenho sao “static final”.

E quanto ao “final” estou começando a usar mais nos parametros que passo tb, para garantir que serao os mesmos parametros até o final do método (vai q eu esqueço e sobrescrevo algo… ja aconteceu…rs)

:slight_smile:

Pra que?[/quote]
Como usar cinto de segurança… Ninguém pretende bater no próximo poste que encontrar. Mas nunca se sabe, “o inferno são os outros”.

E sobre eu utilizar final em todos os parametros que passo e que não pretendo modificar, há alguma perda de desempenho?

A maior parte dos meus métodos eu passo parâmetros sem a intenção de modificá-los, neste caso é sempre vantagem receber os parâmetros como no código a seguir?

metodo(final tipo PARAMETRO) // Maiúsculo já que é constante.. :)

[quote=pcalcado]Para que você não tenha que dar suporte a ele.

A parte de uma classde que pode ser sobrescrita numa subclasse é parte integrante da interface da classe e deve ter seu contrato de sobrescrita especificado exatamente como o contrato de uso de metodos normais.[/quote]

Realmente estou a anos-luz desse cara em OO … eu até acho q entendi + ou - o q ele quis dizer, agora assimilar perfeitamente e trazer isso pro meu dia a dia ainda é um objetivo a se conquistar … rsrs