Shadowing?

Este é um exemplo de “variable shadowing”?
se as duas variáveis fi também fossem static também seria “shadowing”, isto é, “esconder” variáveis é a mesma coisa tanto para estáticas como não-estáticas?

class A
{
   int fi = 10;
}

class B extends A
{
   int fi = 15;
   public static void main(String[] args)
   {
       B b = new B();
       b.fi = 20;
       System.out.println(b.fi);
       System.out.println(  (  (A) b  ).fi  );
   }
}

http://www.janeg.ca/scjp/declarations/scope.html
http://developer.java.sun.com/developer/TechTips/2000/tt1010.html#tip2
http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#39655

Shadowing (JLS §6.3.1)

Because of the way identifiers are looked up; shadowing declarations can occur
For example, a field declaration can be shadowed by a local variable declaration

class TestShadowing {
  static int x = 1;           // field variable
  
  public static void main(String[] args) {
      int x = 0;              // local variable
      System.out.println("x = " + x);
      System.out.println("TestShadowing.x = " + TestShadowing.x)
  }
}

Output:
x = 0
TestShadowing.x = 1

because the identifier x is used within a code block main() a search is made for a declaration of x within the body of main(). As one is found, int x = 0, the simple identifier name x is assumed to be within scope as a local variable
to access the field variable x, you must use its fully-qualified name TestShadowing.x
Note
it was not necessary to instantiate an instance of the TestShadowing object to access the static field variable. If x had been an instance variable it would have been necessary to create a new instance of TestShadowing and use it’s reference to access x

Hiding
Shadowing is not the same as hiding
hiding applies to members that would normally be inherited but are not because of a declaration of the same identifier in a subclass (JLS § 6.1.3)

class SuperA {
    int x = 10;
}

class SubA extends SuperA {
    int x = 20;           // hides x in superclass
}

a method can hide a method in the superclass by overriding it

static Methods cannot be overridden
a method cannot override a static method in the superclass; however, it can hide it by using the same declaration

class SuperA {
    static void method2() {
    }
}

class SubA extends SuperA() {
    void method2() {
        // declaration causes a compile-error
    }
    
    static void method2() {
        // compiles ok
    }
}

static methods are hidden vs overridden as the JLS states they “cannot be overridden” so the compiler never compares subclass method declarations to static superclass method declarations.
a static method in a subclass cannot hide an instance method in the superclass (JLS §8.4.6.2)

class SuperA {
    void method1() {
    }
}

class SubA extends SuperA() {

    static void method1() {
        // compile-error
    }
}

a hidden method can be accessed by using super(), casting to the superclass or using the methods fully qualified name (JLS §8.4.6.2)
((SuperA)y).method2(); // cast to access hidden method

instance variables can hide static and non-static variables in the superclass (JLS §8.4.6.1)

Obscuring (JLS §6.3.2)
there may be times when a simple name could be interpreted as a variable, a type or a package
based on the rules, a variable will be chosen before a type, and a type before a package
in such situations a declaration is said to be obscured
following naming conventions helps to avoid obscuring (see Naming conventions).[/b]

um exemplo, que também trata de polimorfismo, o código abaixo compila? se sim, qual a saída?

class Trebble{
    int i = 99;
}
class Base extends Trebble{
    int i =100;
}
public class Central extends Base{
    public static void main(String argv[]){
	Central c = new Central();
	c.wynyard();
    }
    public void wynyard(){
	Trebble t = new Central();
	Base b = (Base) t;
	System.out.println(b.i);
    }
	
}

Olá,
Existe uma regra simples para os casos de seleção de metodos e campos em situações de shadow e overhide.
Os campos são sempre selecionados considerando o tipo de sua referencia em tempo de COMPILAÇÃO, e claro, isto vale para static e non-static.
Os metodos são sempre selecionados considerando o tipo de sua referencia em tempo de EXECUÇÃO, salvo para os metodos static que não sofrem os efeitos do overhiding.
Portanto o codigo compila sem problemas e imprime 100 na saida.
Agora veja um exemplo que confirma esta regra :

 class A{
      String str = "Super";
      public String metodo(){ return "Super";}
      public static String outro(){ return "outro em Super";}
 }

 public class B extends A{
      String str = "Sub-class";
      public String metodo(){ return "Sub-class";}
      public static String outro(){ return "outro em Sub-class";}

      public static void main( String [] args ){
          A a = new B();
          System.out.println( a.metodo() );
          System.out.println( a.str );
          System.out.println( a.outro() );

      }
 }

a saida em ‘main’ é :
super
sub-class
outro em Super
Vale lembrar que alguns compiladores vão dar um aviso dizendo que
um metodo static está sendo acessado de uma forma non-static na linha 04 de ‘main’.
Para quem vem do C++ é soh lembrar que variáveis membro são selecionadas usando EARLY-BIND e funções membro são selecionadas usando LATE-BIND quando virtuais puras como é o caso de TODOS os metodos em Java, salvo os statics.

[]'s
Cláudio Gualberto.

ok, perfeito :!: