Metodos Statics Override ou não

Estou com uma duvida sobre metodos statics

Sendo que li no livro da kathy sierra que os metodos staticos podem ser redefinidos e não sobrescritos certo?

A maioria das questões que achei nos mocks forão a respeito do polimorfismo por exemplo

Mae e =new Filha();
e.metodo() // aki sai o metodo de Mae pq polimorfismo nao funciona para estaticos.

Mais entao me surgiu uma duvida quando eu estava fazendo ums testes
Vejão o codigo a abaixo a classe filha literalmente herda o metodo static:

[code]import static java.lang.System.*;
class Super {
static void p(){
out.print(“super”);
}
}

public class Teste extends Super{

public static void main(String[] args) {
    
 p();
}

}

[/code]

output “super”

O pessoal aki ate testou com a api de reflexão e conferiu que acontece a herança.

porem se eu forço subscrita que supostamente não poderia exitir e sim uma redefinição existir recebo um erro do compilador

[code]import static java.lang.System.*;
class Super {
static void p(){
out.print(“super”);
}
}

public class Teste extends Super{
private static void p(){
out.print(“super”);
}
public static void main(String[] args) {

 p();
}

}
[/code]

Recebo um erro: Teste cannot override p(); porque estou diminuindo a visibilidade.

Alguem pode me esclarecer sobre override e overload em staticos.

Obrigado.

olá.

Seu problema não é no método estático, e sim na redução de visibilidade do método…
e isso tanto faz para métodos estáticos ou não estáticos…

Veja você não pode fazer algo assim:


class A{
	static void fazAlgo1(){}
	void fazAlgo2(){}	   // metodo default
}

class B extends A{
	static void fazAlgo1(){}
	private void fazAlgo2(){} // não pode
}

public class C extends A{
	static void fazAlgo1(){}
	protected void fazAlgo(){}
}

veja que os métodos estáticos são sobrescritos normalmente. mas a sobrescrição do método fazAlgo1() na linha 8 gera um erro de compilação, porque não é possível a redução de visibilidade. também veja que na linha 13 eu faço uma sobrescrição para PROTECTED e não dá problema.

Então os níveis de visibilidade são:

public.
protected.
default.
private.

Eu, nunca posso reduzir a visibilidade de public. porém e nunca ampliar de private, pq private nunca é visivel, no caso só será a criação de um método qualquer na subclasse…

Espero ter sido claro

Disso eu sei amigo mais valeu a ajuda o caso é que no livro da kathy sierra estava escrito que metodos estaticos não são sobrescritos e sim redefinidos o que é uma inverdade com base nos testes.

[quote=Diabo Loiro]Estou com uma duvida sobre metodos statics

Sendo que li no livro da kathy sierra que os metodos staticos podem ser redefinidos e não sobrescritos certo?

A maioria das questões que achei nos mocks forão a respeito do polimorfismo por exemplo

Mae e =new Filha();
e.metodo() // aki sai o metodo de Mae pq polimorfismo nao funciona para estaticos.

Mais entao me surgiu uma duvida quando eu estava fazendo ums testes
Vejão o codigo a abaixo a classe filha literalmente herda o metodo static:

[code]import static java.lang.System.*;
class Super {
static void p(){
out.print(“super”);
}
}

public class Teste extends Super{

public static void main(String[] args) {
    
 p();
}

}

[/code]

output “super”

[/quote]

O que vc esperava ? Erro ?

Se p() é acessivel por this, this.p() pode ser chamado porque p() é package. Logo o que acontece não é herança mas sim acesso.
A classe pode acessar p() e por isso ele aparece via reflection.

Experimente redefenir p() em Test e veja o que acontece. Depois tente acessar o p() de super quando tem um p() definido em teste.

Static não se herda porque não existem objetos envolvidos. é tudo um conjunto de métodos globais. Herança é para objetos. Conceptualmente static não pode ser herdaddo. não faz sentido isso.
Mas pode ser redefenido. É por isso que vc pode declarar um método static e final. Isso significa que ele não poderá ser redefenido.

cara olhe o inicio do post eu “redefini” o metodo p () e recebi um erro de override. pois eu “redefini” como private de proposito isso que me indagou entendo esse conceito que voce disse de objetos realmente faz sentido mais se ele esta herdando o metodo e não deixa eu “redefinir” para private então é um override, se fosse o “metodo de cada classe” e se fosse uma redefiniçao o compilador não poderia reclamar de override para private em um metodo statico.

pode testar ai que voce vai ver.

sergiotaborda,

Eu entendi o seu conceitualmente e concordo, mas é realmente muito estranho o compilador dizer

sendo que o método não foi herdado…

Outro teste é se Super.p() for final static, você não consegue redefini-lo na subclasse…mas se ele não foi herdado, o final deveria afetar?

A única coisa que me fez pensar que o método realmente não foi herdado é: se você definir o método na classe Teste, ele não da warning pedindo annotation @Override, mas daí também não tenho certeza se esse warning é provido pelo eclipse ou pelo compilador…

Será que o compilador não leva com ele esses conceitos? Conceitualmente a gente não deve fazer isso, mas não tem quem nos impeça?

quando eu disse para redefenir eu quiz (obviamente) dizer "redefenir do jeito certo’. Redefina com o mesmo nivel de visibilidade e ou mais.

Isso é sobrescrever entao >.< se fosse redefinir não deveria ter nada a ver em colocar um modificador private? quais são as regras pra redefinição acho que nen existem portanto se seguir a regra do override funciona.

mais obrigado por dar sua opnião se alguem tiver alguma outra explicação diferente dessas ja expostas será bem vinda.

A questão é a seguinte: métodos estáticos são herdados ou não?

uma coisa muito estranha:

Eu peguei o Class da classe Filha e dei um getMethods(). Na lista veio o p, como se ele pertencesse a classe filha.

[code]package javaapplication8;

import java.lang.reflect.Method;
import static java.lang.System.*;
import java.util.logging.Level;
import java.util.logging.Logger;

class Super {
public static void p(){out.print(“super”);}

void a(){}

}

public class Main extends Super{

public static void main(String[] args) {
    try {
        Class c = Class.forName("javaapplication8.Main");
        Method[] ms = c.getMethods();
        for(Method m : ms) {
            System.out.println(m.getName());
        }
    }  catch (IllegalArgumentException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    }  catch (SecurityException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    } catch (ClassNotFoundException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    }


}

}[/code]

Resultado:

[quote]main
p
hashCode
getClass
wait
wait
wait
equals
notify
notifyAll
toString
[/quote]

[quote=leandrodelsole]sergiotaborda,

Eu entendi o seu conceitualmente e concordo, mas é realmente muito estranho o compilador dizer

sendo que o método não foi herdado…

[/quote]

Tb é muito estranho que NullPointerException exista quando em java não ha ponteiros…
Isso não significa nada.

final é uma palavra com muitos usos e não está atrelada ao conceito de herança e sim ao conceito de alteração.Uma coisa final não pode ser alterada. Este é o conceito. se o método é estático e final ele não pode ser redefinido (alterado).

Redefinir não é herdar.

O compilador não está errado. O que está errado é pensar em herança de coisas estáticas. Vcs estão confundindo herança com acesso. A classe filha acessa qualquer método definido no seu escopo. métodos no escopo são os de instancia e os de classe.
Se ela é filha, os métodos no escopo da classe mãe que não sejam private estão tb estão disponiveis para acesso. Isto inclui os métodos estáticos da mae, claro.
Agora vc declara um método estático com a mesma assinatura que o da mãe na classe filha. O que vc está fazendo ?
Vc está fazendo uma redefinição de escopo. A classe filha agora acessa esse método e não o da mae. O método da mãe foi sombreado ( shawdowed). Este fenómeno não tem a haver com herança.

Para sem bem claro, toda a herança é uma redefinição de escopo, mas nem toda a redefinição de escopo é herança. O exemplo é o sombreamento.

é o mesmo fenómeno que acontece quando vc tem um atributo nome e um método com um argumento nome. O argumento sobreia o atributo e por isso vc precisa do this para se referir ao atributo com o mesmo nome mas no escopo mais amplo. O detalhes é que o método sendo estático vc não consegue acessar o escopo da classe mae (não existe um this ou um super).

Shawdoing pode ser perigoso para métodos estáticos já que eles são parte da estrutura da classe. Por isso o java oferece a opção de impedir a redefenição (impede o sombreamento) através do uso de final.

Isto é util por exemplo para fabricas abstratas. A fabrica abstrata precisa ser herdada, mas o método de fábrica não pode ser redefenido já que toda a logica está ali.

Portanto,coisas estáticas (métodos e atributos) não são herdadas , porque é um contra-senso, apenas coisas de instância são herdadas. Mas elas são acessíveis independentemente de herança. membros de classes podem ser sombreados, atributos ou métodos inclusive os estáticos. Isso é normalmente perigoso. Por isso , para métodos, é possível usar o final para evitar isso.

Entendi seu ponto de vista mais sinceramente não deu pra ter 100% de certeza por causa da mensagem do compilador, no caso de nullpointer que tu disse esta claro que é quando uma referencia aponta para null >.< e ja vi o post onde voces discutem isso, mais vou tentar perguntar para o proprio James Gosling no sun tech days se tiver uma oportunidade.

Obs: se alguem tiver outro ponto de vista favor postar para podermos comparar obrigado.

Quanto ao conceito de herança vs coisas static eu acho que não tenho problema. A parte que herança é sobre objetos e o contexto estático não faz parte do objeto (mas sim da classe) está bem clara para mim. O que eu gostaria de saber (a título de curiosidade) é o seguinte:

Toda vez que uma classe vai ser usada, ela é carregada por algum classloader, que cria uma instância de Class referente aquela classe, certo? Essa instancia de Class contém toda a definição da estrutura da classe em questão (métodos, campos, anotações, etc).

O que acontece por baixo dos panos quando você declara uma classe herdando de outra? E o contexto estático de uma classe, ele é gerenciado por quem? Pelo classloader que a carregou?

[quote=Diabo Loiro]Entendi seu ponto de vista mais sinceramente não deu pra ter 100% de certeza por causa da mensagem do compilador, no caso de nullpointer que tu disse esta claro que é quando uma referencia aponta para null >.< e ja vi o post onde voces discutem isso, mais vou tentar perguntar para o proprio James Gosling no sun tech days se tiver uma oportunidade.

Obs: se alguem tiver outro ponto de vista favor postar para podermos comparar obrigado.[/quote]
O que é persceptivel ao compilador não é regra para Orientação a Objetos, todavia se você assumir que o compilador é o cara certo pra responder por suas decisões por ações preemptivas você vai desconhecer o que é deterministico ao codigo para sua implementação.A prova de Certificação é ligado a fenômeno de efeitos da JVM e essa regra é contraditória em situações que envolve conceitos até mesmo interpretados pela UML e suas anotações.

[quote=Link_pg]Quanto ao conceito de herança vs coisas static eu acho que não tenho problema. A parte que herança é sobre objetos e o contexto estático não faz parte do objeto (mas sim da classe) está bem clara para mim. O que eu gostaria de saber (a título de curiosidade) é o seguinte:

Toda vez que uma classe vai ser usada, ela é carregada por algum classloader, que cria uma instância de Class referente aquela classe, certo? Essa instancia de Class contém toda a definição da estrutura da classe em questão (métodos, campos, anotações, etc).
[/quote]

sim. Mas não é toda a vez que a classe é usada. Ela é carregada apenas da primeira vez que é usada.

[quote]
O que acontece por baixo dos panos quando você declara uma classe herdando de outra? E o contexto estático de uma classe, ele é gerenciado por quem? Pelo classloader que a carregou?[/quote]

É a JVM que verifica isso. O conceito que a JVM segue é o de escopos (scope). Ela gerencia a visibilidade de escopos. É apenas isso.

[quote=sergiotaborda][quote=leandrodelsole]sergiotaborda,

Eu entendi o seu conceitualmente e concordo, mas é realmente muito estranho o compilador dizer

sendo que o método não foi herdado…

[/quote]

Tb é muito estranho que NullPointerException exista quando em java não ha ponteiros…
Isso não significa nada.

final é uma palavra com muitos usos e não está atrelada ao conceito de herança e sim ao conceito de alteração.Uma coisa final não pode ser alterada. Este é o conceito. se o método é estático e final ele não pode ser redefinido (alterado).

Redefinir não é herdar.

O compilador não está errado. O que está errado é pensar em herança de coisas estáticas. Vcs estão confundindo herança com acesso. A classe filha acessa qualquer método definido no seu escopo. métodos no escopo são os de instancia e os de classe.
Se ela é filha, os métodos no escopo da classe mãe que não sejam private estão tb estão disponiveis para acesso. Isto inclui os métodos estáticos da mae, claro.
Agora vc declara um método estático com a mesma assinatura que o da mãe na classe filha. O que vc está fazendo ?
Vc está fazendo uma redefinição de escopo. A classe filha agora acessa esse método e não o da mae. O método da mãe foi sombreado ( shawdowed). Este fenómeno não tem a haver com herança.

Para sem bem claro, toda a herança é uma redefinição de escopo, mas nem toda a redefinição de escopo é herança. O exemplo é o sombreamento.

é o mesmo fenómeno que acontece quando vc tem um atributo nome e um método com um argumento nome. O argumento sobreia o atributo e por isso vc precisa do this para se referir ao atributo com o mesmo nome mas no escopo mais amplo. O detalhes é que o método sendo estático vc não consegue acessar o escopo da classe mae (não existe um this ou um super).

Shawdoing pode ser perigoso para métodos estáticos já que eles são parte da estrutura da classe. Por isso o java oferece a opção de impedir a redefenição (impede o sombreamento) através do uso de final.

Isto é util por exemplo para fabricas abstratas. A fabrica abstrata precisa ser herdada, mas o método de fábrica não pode ser redefenido já que toda a logica está ali.

Portanto,coisas estáticas (métodos e atributos) não são herdadas , porque é um contra-senso, apenas coisas de instância são herdadas. Mas elas são acessíveis independentemente de herança. membros de classes podem ser sombreados, atributos ou métodos inclusive os estáticos. Isso é normalmente perigoso. Por isso , para métodos, é possível usar o final para evitar isso.

[/quote]

Uma Referência não deixa de ser um ponteiro.

to sentindo cheiro de flame…