0

While preparing for sitting the Java exams i just came across this snippet

class Person {
  static class Male {
    static String Desc = "Male"; 
  }
  static Gender Male = new Gender(); 
  }

class Gender {
  String Desc = "Gender"; 
}

public static void main(String[] args) 
{
  System.out.println(Person.Male.Desc); // returns: Gender
}

}

used to depict the precedence of local variables over class members.

the overlapping scope(s) is obvious to me. but why would we call Desc a local variable here? Is it because it is not known by any method (be it static or non-static) / class related to Person. - Just as any "ordinary" method-variable with limited i.e. local scope?

the snippet is meant to confuse. so i ask to make sure i understood the notion beyond it.

Andrew Tobey
  • 915
  • 3
  • 10
  • 27
  • 'Precedence ' is the wrong term here. It already has another meaning. – user207421 Aug 14 '14 at 23:28
  • gotcha. haven't thought abt it this way, yet. but if we look at it once more from the author's perspective: wouldnt it be eventually a matter of precedence given that no matter what access modifiers we add the situation stays the same! - at least inside Person – Andrew Tobey Aug 14 '14 at 23:34
  • 1
    No. Access modifiers don't have anything to do with it, and it still isn't precedence. The explanation is that the name of the class Male is Person$Male, not Person.Male. There is no precedence or preference or choosing going on here at all. – user207421 Aug 14 '14 at 23:39
  • I see. The answer to the snippet was "...when a (local) variable and a class member are both in the same scope and have the same name, the variable takes precedence, in the same way that they take precedence over package names" (Java Practice Questions). – Andrew Tobey Aug 14 '14 at 23:45
  • so a$b is used to reference a class b nested in a, so a correct reference would be Person$Male.Desc? - – Andrew Tobey Aug 14 '14 at 23:47
  • 1
    The snippet given isn't correct. The answer to the question is that the situation isn't ambiguous and doesn't require a choice. No precedence, no shadowing. If you wanted the result "Male" you would have to write Person$Male.Desc. – user207421 Aug 14 '14 at 23:51

4 Answers4

0

First of all your example does not even compile.

I'm assuming you meant:

public class Person {

    static class Male {
        static String Desc = "Male"; 
    }

    static class Gender {
      String Desc = "Gender"; 
    }

    static Gender Male = new Gender(); 

    public static void main(String[] args) 
    {
      System.out.println(Person.Male.Desc); // returns: Gender
    }
}

The overlap is in Male not in Desc. If you remove (or comment out static Gender Male = ...) then the output is "Male". Person.Male refers to the static member variable Male not the static inner class Male. In this sense the variable has precedence over the class.

If @EJP would pipe in and explain how to use Person$Male to reference the class instead of the variable and the correct name for this "precedence" it would be greatly appreciated.

Eli Algranti
  • 8,707
  • 2
  • 42
  • 50
0

Here's a way to access Person$Male using reflection:

public class Person
{
    static class Male
    {
        static String Desc = "Male";
    }

    static class Gender
    {
        String Desc = "Gender";
    }

    static Gender Male = new Gender();

    public static void main(String[] args)
    {
        System.out.println(Person.Male.Desc); // returns: Gender
        try
        {
            Person.Male male = (Person.Male) Class.forName("Person$Male").newInstance();
            System.out.println(male.Desc); // returns: Male
        }
        catch (InstantiationException e)
        {
            e.printStackTrace();
        }
        catch (IllegalAccessException e)
        {
            e.printStackTrace();
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
    }
}
fipple
  • 360
  • 1
  • 5
0

Its somewhere correct to say the precedence of local over the static variable, As You can see in this code . Before declaring a local variable at line 2 snap method gets teeth=1 (the copy of class level teeth variable) but After declaring the local variable at line 2 it pick up the local variable instead of the static teeth. Yes it can be referred as shadowing where the higher level scope variable got hidden.

public class StaticVariable {
static int teeth;
public StaticVariable(){
    teeth++;
}
public void snap( int teeth){
    System.out.println(teeth+"");
    teeth--;
}
public static void main(String[] args){

    new StaticVariable().snap(teeth);//Line 1  teeth--> 1
    int teeth=3;//Line 2
    new StaticVariable().snap(teeth);//Line 3. teeth--> 3

}
-1

It's called "Shadowing". See tutorial: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html