Eu tenho brincado com modificadores com método estático e me deparei com um comportamento estranho.
Como sabemos, métodos estáticos não podem ser substituídos, pois estão associados à classe e não à instância.
Então, se eu tenho o trecho abaixo, ele compila bem
//Snippet 1 - Compiles fine
public class A {
static void ts() {
}
}
class B extends A {
static void ts() {
}
}
Mas se eu incluir o modificador final do método estático na classe A, a compilação falhará ts () em B e não poderá substituir ts () em A; O método substituído é final estático .
Por que isso está acontecendo quando o método estático não pode ser substituído?
Respostas:
Métodos estáticos não podem ser substituídos, mas podem ser ocultados. O
ts()
método de B não substitui (não está sujeito a polimorfismo) ots()
de A, mas o oculta. Se você chamarts()
B (NOTA.ts()
ouB.ts()
... justts()
), o de B será chamado e não A. Como isso não está sujeito ao polimorfismo, a chamadats()
em A nunca será redirecionada para a de B.A palavra
final
- chave impedirá que o método seja oculto. Portanto, eles não podem ser ocultados e uma tentativa de fazer isso resultará em um erro do compilador.Espero que isto ajude.
fonte
A#ts
está sendo herdado e já existe um métodoB
, simplesmente ter dois métodos com a mesma assinatura e um modificador diferente (final
) não funcionaria como sobrecargas. . Eu gostaria de poder pensar em uma mensagem simples para isso, porémisso não é exatamente verdade. O código de exemplo realmente significa que o método ts em B oculta o método ts em A. Portanto, não é exatamente anulado. Em Javaranch, há uma boa explicação.
fonte
Os métodos estáticos pertencem à classe, não à instância.
A.ts()
eB.ts()
sempre serão métodos separados.O verdadeiro problema é que o Java permite chamar métodos estáticos em um objeto de instância. Métodos estáticos com a mesma assinatura da classe pai são ocultos quando chamados de uma instância da subclasse. No entanto, você não pode substituir / ocultar os métodos finais .
Você pensaria que a mensagem de erro usaria a palavra oculta em vez de substituída ...
fonte
Você pode encontrar-se na posição de pensar em finalizar um método estático, considerando o seguinte:
Tendo as seguintes classes:
Agora, a maneira 'correta' de chamar esses métodos seria
o que resultaria,
AB
mas você também poderia chamar os métodos nas instâncias:o que resultaria
AB
também.Agora considere o seguinte:
isso seria impresso
A
. Isso pode surpreendê-lo, pois você está realmente tendo um objeto de classeB
. Mas como você está chamando a partir de uma referência do tipoA
, ele chamaráA.ts()
. Você pode imprimirB
com o seguinte código:Nos dois casos, o objeto que você possui é realmente da classe
B
. Mas, dependendo do ponteiro que aponta para o objeto, você chamará o método deA
ou deB
.Agora, digamos que você é o desenvolvedor da classe
A
e deseja permitir a subclassificação. Mas você realmente deseja um métodots()
, sempre que chamado, mesmo de uma subclasse, que é o que você deseja que ele faça e que não seja oculto por uma versão da subclasse. Então você pode fazer issofinal
e impedir que ele fique oculto na subclasse. E você pode ter certeza de que o código a seguir chamará o método da sua classeA
:Ok, admitidamente, isso é de alguma forma construído, mas pode fazer sentido para alguns casos.
Você não deve chamar métodos estáticos nas instâncias, mas diretamente nas classes - então você não terá esse problema. Também o IntelliJ IDEA, por exemplo, mostrará um aviso, se você chamar um método estático em uma instância e também se você finalizar um método estático.
fonte
O método ts () em B não substitui o método ts () em A; simplesmente é outro método. A classe B não vê o método ts () em A, pois é estático; portanto, pode declarar seu próprio método chamado ts ().
No entanto, se o método for final, o compilador perceberá que existe um método ts () em A que não deve ser substituído em B.
fonte
Eu acho que o erro de compilação foi bastante enganador aqui. Não deveria ter dito "o método substituído é final estático.", Mas deveria ter dito "o método substituído é final.". O modificador estático é irrelevante aqui.
fonte
Um método estático não pode ser substituído em Java, diferentemente dos métodos não estáticos. Mas eles são herdados como membros de dados estáticos e não estáticos. É por isso que um método não estático com o mesmo nome não pode ser criado na classe pai
A
final
palavra-chave garante que o corpo do método específico seja executado sempre que uma chamada para o método. Agora, se um método estático for criado na classe filho com o mesmo nome e for feita uma chamada para o método, o método na subclasse será executado, o que não deve ser o caso se final for prefixado antes do nome do método estático na classe pai . Portanto, a palavra-chave final restringe a criação do método com o mesmo nome na classe filho.fonte