// this code demonstrates various scope concepts

public class Scope
{
  public static int a = 55;             // scope of instance variables is
                                        // restricted to its class

  public static void main(String[] args)
  {
    ClassA x = new ClassA();
    ClassB y = new ClassB();

    System.out.println("In ClassA: " + x.a);
    System.out.println("In ClassB: " + y.a);

   // scope of a local variable is restricted to its block
    {
      int i = 5;
      System.out.println("i=" + i);
    }
    {
      double i = 2.5;          // redeclaration of i: it's legal
      System.out.println("i=" + i);
    }

   // scopes of local vars with the same name must be disjoint
/*
    {                         // this won't compile since the blocks overlap
      int i = 5;
      {
        int i = 10;
      }
    }
*/

   // shadowing a class/instance variable by a local variable
    {
      int a = 66;             // local var a shadows a class var with the
                              // same name
      System.out.println("a=" + a);   // prints "a=66"
      System.out.println("Scope.a=" + Scope.a); // prints "a=55"
    }     
    System.out.println("a=" + a); // prints "a=55"
    x.test1();                // demo of shadowing a class var by a local one
    x.test2(20);              // demo of shadowing a class var by parameters
    x.test3(20);
  }
}

class ClassA
{
  public static int a = 5;

  // local variables shadow the class/instance variable with the same name
  public void test1()
  {
    int a = 10;
    System.out.println("a=" + a);  // prints "a=10"
    System.out.println("this.a=" + this.a); // prints "a=5"
  }

  // method parameters shadow the class/instance variable with the same name
  public void test2(int a)
  {
    //int a = 10;                  // no local vars matching a parameter name
    System.out.println("a=" + a);   // prints the parameter a
    System.out.println("this.a=" + this.a); // prints "a=5"
  }

  // accessing shadowed static class variables from static methods
  public static void test3(int a)
  {
    //int a = 10;                  // no local vars matching a parameter name
    System.out.println("a=" + a);   // prints the parameter a
//    System.out.println("this.a=" + this.a); // does not compile !!!
    System.out.println("ClassA.a=" + ClassA.a); // prints "a=5"
  }
}

// the var a in this class is different from the var a in class ClassA
class ClassB
{
  public int a = 10;
}

