Em Java existe uma diferença de desempenho entre fazendo referência a um campo através getter contra através de uma variável?

StackOverflow https://stackoverflow.com/questions/1195849

Pergunta

Existe alguma diferença entre fazendo

Field field = something.getSomethingElse().getField();
if (field == 0) {
//do something    
}
somelist.add(field);

contra

if (something.getSomethingElse().getField() == 0) {
//do something    
}
somelist.add(something.getSomethingElse().getField());

referências fazer para o campo através de getters incorrer em uma penalidade de desempenho ou é o mesmo que fazer referência a uma variável atribuída? Eu entendo que a variável é apenas uma referência para o espaço de memória, de modo que o getter deve ser apenas uma outra maneira para chegar a esse espaço de memória.

Note que esta é uma questão acadêmica (escola de apenas curioso) em vez de uma prática.

Foi útil?

Solução

Assumindo que getSomethingElse() é definido como

public SomethingElse getSomethingElse() {
    return this.somethingElse;
}

diferença de desempenho será mínima (ou zero se ele vai ficar embutido). No entanto, na vida real você não pode ter sempre a certeza de que é o caso - pode haver algum processamento acontecendo nos bastidores (não necessariamente no próprio objeto, mas, digamos, via proxy AOP). Então, salvando o resultado na variável para o acesso de repetição pode ser uma boa idéia.

Outras dicas

É um prejuízo desprezível. Não se preocupe com ele muito ou você vai ser vítima de otimização prematura. Se sua aplicação é lenta, esta não é a razão pela qual.

Há uma diferença em que as variáveis ??que acessam através de getters resulta em uma chamada de método. A JVM pode concebivelmente ser capaz de otimizar a chamada de método afastado sob algumas circunstâncias, mas é uma chamada de método.

Dito isto, se o maior gargalo ou problema de desempenho em seu código é a sobrecarga de métodos de acesso, eu diria que você não tem muito com que se preocupar.

Há uma penalidade de desempenho (que pode ser tão pequena que é insignificante) No entanto, a JVM pode in-line este e todos os telefonemas para melhorar o desempenho.

Seria melhor se você deixá-lo o segundo caminho.

Não, se você tem um bom JVM, como HotSpot da Sun. Ele vai em linha e compilação (para código nativo) os getters.

Usando getters é geralmente uma prática muito boa, como uma medida defensiva, e escondendo informações gerais.

Um ponto a nota, se utilizando Java para escrever aplicativos do Android é aqui: http://developer.android.com/training/articles/perf-tips .html # GettersSetters

Em línguas nativas, como C ++ é uma prática comum para getters de uso (i = getCount ()) em vez de aceder o campo directamente (i = mCount). Esta é um excelente hábito para C ++ e é frequentemente praticada no outro objeto linguagens orientadas como C # e Java, porque o compilador pode normalmente inline acesso, e se você precisa para restringir ou acesso de campo debug você pode adicionar o código em qualquer altura.

No entanto, esta é uma má idéia no Android. virtuais método chamadas são caro, muito mais do que pesquisas de campo de instância. É razoável seguir as práticas comuns de programação orientada a objetos e ter getters e setters na interface pública, mas dentro de uma classe que você deve sempre acessar campos diretamente.

Sem um JIT, o acesso de campo direto é de cerca de 3x mais rápido do que chamar uma getter trivial. Com o JIT (onde o acesso de campo direto é tão barato quanto acesso a um local), acesso de campo direto é de cerca de 7x mais rápido do que invocando um getter trivial.

Note que se você estiver usando ProGuard, você pode ter o melhor de ambos mundos, porque ProGuard inline podem acessores para você.

Se o método é um getter simples, sem processamento envolvido não é um problema. Se envolve extensa cálculo, uma propriedade não faria o que você quer de qualquer maneira.

A única vez que eu me preocuparia com alguma diferença está em um loop com um grande número de iterações (muitos milhares). Mesmo assim, este é, provavelmente, apenas um problema se você estiver usando aspectos para tecer processamento extra (por exemplo, exploração madeireira), isso pode envolver a criação de milhares de objetos extras (por exemplo joinpoints e parâmetro autoboxing) e questões GC resultantes.

Eu não me preocuparia com a diferença de desempenho. Você seria melhor não pensar nisso e, em vez gastar o tempo no perfil de seu código em um cenário realista. Você provavelmente vai achar que as partes lentas do seu programa não estão onde você pensa que são.

Este post fala sobre o CLI VM em vez do JVM, mas cada um é capaz de fazer coisas semelhantes, então eu acredito que é relevante.

Eu estou lidando com este problema específico de uma maneira especial para minha JIT. Note-se que a descrição aqui é conceitual e os implementos de código lo de uma forma um pouco diferente por motivos de desempenho. Quando eu carregar um assembly, eu faço uma nota no descritor método se ele simplesmente retorna um campo de membro. Quando eu JIT outros métodos mais tarde, eu substituir todas as instruções call a esses métodos no código byte com uma instrução ldfld antes de passá-lo para o gerador de código nativo. Desta forma, eu posso:

  1. Save tempo no JIT (ldfld leva menos tempo do processador para JIT do que call).
  2. propriedades inline mesmo na base compilador .
  3. Em geral garantia de que usando o padrão propriedades públicas / privadas campos não terão uma penalidade de qualquer tipo de desempenho quando o depurador é separado. (Quando um depurador é anexado não posso inline acessores.)

Eu não tenho nenhuma dúvida de que os grandes nomes em tecnologias VM já estão implementando algo similar a (e provavelmente melhor do que) isso em seus produtos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top