Métodos static sobrescritos

Olá pessoal. Sei que métodos static são implicitamente final. Sendo assim, resolvi fazer um pequeno teste. Criei uma classe Animal com um método static e estendi um classe Lobo criando um outro método static com a mesma assinatura do anterior.
O que está acontecendo ao executar o código abaixo? Se o método static não pode ser sobrescrito por que o compilador não dá nenhuma mensagem de erro?

[code]class Animal {

public static void soma (){
	System.out.println("Metodo original");
}

}[/code]

[code]class Lobo extends Animal {

public static void soma(){
	System.out.println("Metodo sobrescrito!");
}

public static void main(String[] args){
	Lobo.soma();
	
}

}[/code]

Se eu comentar o método da classe Lobo, o outro é executado (classe Animal). Isso não quer dizer que o método foi sobrescrito (caso eu não comente o método da classe Lobo)?

http://www.guj.com.br/posts/list/64524.java

http://www.guj.com.br/java.tutorial.artigo.121.1.guj

Bem, na verdade, os métodos estaticos podem ser sobrescritos sim, afinal eles não foran finalizados.

É essa a idéia da palavra final, fazer com que:

  • um método não seja sobrescrito;
  • um atributo não tenha o conteúdo alterado (seja constante)
  • uma classe não possa ser extendida.

O fato de ser ou não estatico define apenas se existe ou não a necessidade de criação de instancia da classe para poder utilizá-lo.

:wink:

O que ocorre é que você não está instanciando um Lobo para acessar seus atributos de super classe e afins, você está chamando diretamente o método soma() carregado pela VM(por ser estático) da classe Lobo.

Galera, o sergiotaborda explica abaixo o que está acontecendo. Obrigado a todos.

[quote] Vou tentar deixar as coisas mais claras.
Temos 3 conceitos em jogo aqui: Acessibilidade , Shawdoing (sombreamento ) e Herança.

O que é shadowing ?
Shadowing (sombreamento) é um tipo de polimorfismo estático e é possível graças ao conceito de escopo.
É tomar em consideração que a acessibilidade de um artefato (método, variável, classe, etc) depende de um escopo. Por isso eu posso definir nomes iguais para coisas diferentes. Elas são diferentes, se têm um nome diferente (uma identidade diferente) ou se têm um escopo diferente.


 
 class X {
 
   int m =1 ; 
 
 
   public int getN(){
           int m = 2;
         return m;
   } 
 } 

O resultado de invocar x.getN() é 2. Porquê ? Por causa do sobreamento.
Ao definir m dentro do método , estou definido o simbolo m num escopro mais próximo do método do que aquele que que é definido na classe. (estou ponto o m da classe à sobra do m do método. )

Isto ilustra bem que shawdoing nada tem a haver, diretamente, com herança. Também não tem nada a haver com sobrecarga nem sobrescrita.
Contudo, o sobreamento é o que me permite definir dois atributos com nome igual em classes da mesma hierarquia. Assim

 class A {
 
   int n=3;
 
   public int getN(){
         return n;
   }
 }
 
 class B {
 
   int n=4;
 
   public int getN(){
         return n;
   }
 }
 
 class C {
 
   int n=5;
 
   public int getN(){
         return super.n;
   }
 }
 

Quando eu invocar b.getN() o resultado será 4, Mas quando invocar c.getN() será 3. Isto pode ser um problema se não se tomar atenção.

Então, como o Java sabe o que tem que invocar quando encontra um simbolo de um artefato (n , no caso) ? Ele procura por esse simbolo no escopo mais próximo. Se não encontrar ele vai procurar nos escopo mais afastados até que encontre o simbolo. Quando encontrar ele executa esse simbolo nesse escopo. Se nunca encontrar lança um erro.
Os escopos licitos podem ser modificados com os modificadores de acessibilidade (public, protected, private)

Repare que isto só tem a haver com herança de forma indireta já que herdar é uma forma de criar um escopo diferente. A herança não se aplica para artefatos estáticos mas a regra de invocação sim.

Então o que é herança ?
Herança não tem só a haver com acessibilidade mas tb com reaproveitamento. As propriedades e os comportamentos são reaproveitados, herdados. Mas são os mesmos ? Não.
Herdar significa estender o escopo do filho até à classe pai. Assim , tudo o que for procurado no filho e não for achado, será procurado no pai.
Até aqui nada de especial. Tanto métodos estáticos como não estáticos segue esta regra de procura. A diferença está na outra metade da herança (e por isso se chama herança) O pai pode, explicitamente, delegar para o filho a responsabilidade de implementar um comportamento.
Isto significa que o filho é obrigado a ter o simbolo definido no seu escopo e não pode usar o do pai. Isto se consegue em Java com o modificador abstract.

É esta segunda parte da herança que não está disponivel para coisas estáticas e é por isso que coisas estáticas não são herdadas.
São acessiveis, sim. Porque a acessibilidade funciona de baixo para cima, mas não são herdaveis. A herança funciona de cima para baixo.

Então, o codigo que vc escreveu é completamente compreensivel face a estas regras. E face a estas regras vc não pode dizer que metodos estáticos são heradados pelas classes filhas. O que vc deve dizer é que a classe filha tem acesso aos métodos estáticos do pai , se eles não tiverem sido redefenidos.

Redefinição de métodos estáticos é a mesma coisa que sobrescrita de métodos ? Não.
Porquê ? Porque sobrescrever significa , claro, escrever sobre. Ou seja, quando eu sobrescrevo o método original ainda existe. Eu ainda tenho acesso a ele. É como ter um texto no papel e sobrescrever algumas palavras e outras não. O texto oiriginal ainda está lá.
Como eu sei ? Porque eu posso invocar super.metodo()
Redefenir é simplesmente deitar fora o original e escrever outro. A diferença ? Não dá mais para chamar super.metodo()

Esta é a diferença: Métodos estáticos são redefinidos pelas classes filhas, não sobrescritos nem sobrecarregados. Sobrecarga é, ainda, outra coisa.

Então que fique claro:

  1. Métodos estáticos não são herdáveis nem sobrescritos. A prova é que não posso chamar super.metodo().
  2. Métodos estáticos são acessíveis por subclasses, da mesma forma que qualquer outro artefato. Isto não tem nada a ver com herança e sim com acessibilidade e polimorfismo estático.
    2.1) Se um filho redefine um métodos estático do pai, ele está escondendo o acesso ao método pai. A isto se chama sobreamento ( Shadowing)
    2.2) Shawdoing é um conceito de polimorfismo estático que não tem nada a ver com herança.
  3. Herança é uma forma de estender o escopo da classe a uma outra classe dita superior (dai(?) a lógica palavra extends para definir herança e não inherits )
  4. Sobrescrever, sobrecarregar e redefinir são 3 operações diferentes que se podem fazer a um método, sendo que a redefinição só acontece para métodos estáticos e as sobrescrita para métodos herdados.

Não é uma questão de nomes, é uma questão de conceitos. Espero que isto tenha ajudado a esclarecer as coisas.