Ao denotar um método de classe com um modificador
final
, queremos dizer que nenhuma classe derivada é capaz de substituir esse método alterando sua implementação interna. Ou seja, estamos falando da versão final do método. A classe como um todo também pode ser marcada como final
.
final class NoExtending {
// …
}
Uma classe marcada como final
não pode ser herdada e todos os seus métodos adquirem indiretamente a propriedade final
. Usar o recurso a final
em declarações de classes e métodos pode aumentar o nível de segurança do código. Se uma classe estiver equipada com um modificador final
, ninguém poderá estender a classe e provavelmente quebrar seu contrato no processo. Se um sinal final
denota um método, você pode confiar plenamente em sua implementação interna em todas as situações, sem medo de “falsificação”. É apropriado usar final
, por exemplo, na declaração de um método que exija a verificação da senha digitada pelo usuário para garantir a execução exata do que o método originalmente pretendia. Um possível invasor não será capaz de alterar a implementação original de tal método “colocando” no programa uma versão substituída dele, que, digamos, sempre retorna o valor verdadeiro, indicando o registro bem-sucedido do usuário, independentemente de qual senha ele realmente entrou. Você tem o direito, se a situação específica permitir, de ir além e declarar final
toda a turma como uma turma; o método ValidatePassword
adquirirá a mesma propriedade indiretamente. O uso de um modificador final
em uma declaração de método ou classe impõe sérias restrições à possibilidade de uso e desenvolvimento posterior do código. O uso de final
um método em uma declaração é um indicador seguro de que a implementação do método é independente e completamente completa. Outros programadores que desejam utilizar sua classe, expandindo suas funções para atender às suas próprias necessidades, ficarão limitados na escolha dos meios para atingir seu objetivo ou completamente privados deles. Ao marcar final
uma classe como um todo, você desabilitará sua capacidade de ser herdada e provavelmente reduzirá significativamente sua utilidade para outras pessoas. Quando você estiver prestes a usar o modificador final
, certifique-se de que VOCÊ está pronto para tais sacrifícios e se vale a pena fazê-los. Em muitos casos, para atingir um nível suficiente de segurança de código, não é necessário designar toda a classe como final
- é bem possível preservar a extensibilidade da classe marcando final
apenas seus elementos estruturais "críticos" com um modificador. Neste caso, você deixará intactas as funções principais da classe e ao mesmo tempo permitirá sua herança com adição de novos membros, mas sem redefinir os “antigos”. É claro que os campos acessados pelo código dos métodos final
devem por sua vez ser designados como final
, private
caso contrário qualquer classe derivada poderá alterar seu conteúdo, afetando o comportamento dos métodos correspondentes. Outro efeito do uso de um modificador final
está relacionado à simplificação do problema de otimização de código resolvido pelo compilador. Isto é o que acontece quando um método que não está marcado como é chamadofinal
, o sistema de tempo de execução determina a classe real do objeto, associa a chamada ao código mais apropriado do grupo de métodos sobrecarregados e transfere o controle para esse código. Mas se, por exemplo, o método getName
no exemplo de classe Attr
discutido anteriormente tivesse sido designado como final
, a operação de chamá-lo poderia ter sido visivelmente simplificada. No caso mais trivial, como o que diz respeito ao getName
, o compilador pode simplesmente substituir a chamada do método pelo seu código corporal. Esse mecanismo é chamado de inlining de código. Ao usar a versão embutida do método, getName
as duas expressões a seguir são executadas exatamente da mesma forma:
system.out.println("id = " + rose.name);
system.out.println("id = " + rose.getName());
Embora as expressões acima sejam equivalentes, a segunda ainda tem uma vantagem, pois o método getName
permite atribuir ao campo de nome uma propriedade somente leitura e ao código da classe ter um certo grau de abstração, o que permite alterar mais livremente o implementação de classe. O mesmo esquema de otimização pode ser aplicado pelo compilador aos métodos private
e statiс
, pois eles também não permitem substituição. Usar um modificador final
em declarações de classe também torna algumas operações de verificação de tipo mais eficientes. Neste caso, muitas dessas operações podem ser realizadas já na fase de compilação e, portanto, possíveis erros são detectados muito mais cedo. Se o compilador encontrar uma referência a uma classe no texto fonte final
, pode ter "certeza" de que o objeto correspondente é do tipo especificado. O compilador é capaz de determinar imediatamente o lugar ocupado por uma classe na hierarquia geral de classes e verificar se ela é usada corretamente ou não. Se o modificador final
não for aplicado, as verificações correspondentes serão realizadas apenas na fase de execução do programa. Exercício 3.4. É aconselhável incluir o modificador final nas declarações dos métodos (e em caso afirmativo, quais) das classes de veículos e veículos de passageiros ? Link para a fonte original: http://src-code.net/metody-i-klassy-final-java
GO TO FULL VERSION