1

I was wondering why referencing "w" after obj = w; will throw an error. Aren't you just creating another pointer to that w instance by saying obj = w? I.e. why is it different to saying something like String s = "hi"; String w = s; Thank you!

public class Casting {
   public static void main(String[] args) {
      // casting doesn't change the object
      Object obj;
      { 
          Stopwatch w = new Stopwatch();
          obj = w;
      }
      System.out.println(obj); // this line does work
      System.out.println(w); //this line does not work 
   }
}
rb612
  • 4,453
  • 2
  • 19
  • 49
  • 5
    `w` is out of context, it only has context within the `{...}` block – MadProgrammer May 04 '15 at 03:17
  • So we never learned about this whole `Object obj;` thing - what exactly is going on in those lines of code? We've only learned about a method/class declaration being followed by a set of curly braces - never an object. Like I'd get it if `Object obj;` was replaced with a method declaration, but this is an...object declaration? – rb612 May 04 '15 at 03:18
  • 1
    See [this](http://stackoverflow.com/questions/241088/java-what-do-curly-braces-mean-by-themselves). – user1803551 May 04 '15 at 03:23
  • Ah, this gives me a much better understanding, thank you! So for scope purposes, we have these empty curly braces. Inside these empty curly braces, you can access `obj` though. I thought it limited scope, and the `Object obj;` is outside of the scope. Why is it still included in scope? – rb612 May 04 '15 at 03:25
  • Because `obj` is declared before the scope change, you can still access it, but because `w` is declared within the `{...}` scope, once you leave it, it is no longer accessiable – MadProgrammer May 04 '15 at 03:32

4 Answers4

4

There's nothing like quoting the JLS first thing in the morning.

JLS 6.3. Scope of a Declaration:

The scope of a local variable declaration in a block (§14.4) is the rest of the block in which the declaration appears, starting with its own initializer and including any further declarators to the right in the local variable declaration statement.

and

JLS 14.2. Blocks:

A block is a sequence of statements, local class declarations, and local variable declaration statements within braces.

What does it mean in your case? The local varialbe w is declared in the block

{ 
    Stopwatch w = new Stopwatch();
    obj = w;
}

("its own initializer" is the first line in the block) and so its scope is the rest of that that block. The reference to it,

System.out.println(w); 

is outside of the block and so w will not be able to resolve to a variable.

What about the local variable obj then? It was declared in the block

public static void main(String[] args) {
  
    Object obj;
    { 
        Stopwatch w = new Stopwatch();
        obj = w;
    }
    System.out.println(obj);
    System.out.println(w);
}

which in this case is a method block. The call

System.out.println(obj);

is inside the block, so obj can be referenced successfully.

Community
  • 1
  • 1
user1803551
  • 11,914
  • 5
  • 39
  • 63
  • I'm curious, any chance you have a example of the proper use of a block like this? I have never run across this in Java before... – Dan Ciborowski - MSFT May 04 '15 at 03:38
  • @DanCiborowski-MSFT It is indeed not a common site in most code segments, but there are many uses for code blocks. I will try to get back to you with an example. – user1803551 May 04 '15 at 03:48
  • @Dan, the most typical use case is the `case` (sorry for the pun) clause of a `switch` statement, as in `switch (value) {... case MAGIC: {MyMagic magic = new MyMagic(); magic.castSpell(); break;}` - this way you restrict its visibility to that `case`. Another example is a huge constructor that creates many temporary variables before assigning them to final fields. – Sergei Tachenov May 04 '15 at 05:52
  • @SergeyTachenov Dan is asking, as far as I understand, about a block as in the above question - unrelated to constructs or declarations. – user1803551 May 04 '15 at 23:10
  • @DanCiborowski-MSFT [JLS 6.4](https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.4) has uses to scoping with some simple examples. – user1803551 May 04 '15 at 23:25
1

This is the problem with the scope.The scope of

{ 
      Stopwatch w = new Stopwatch();
      obj = w;
  }

here the w scope is within brackets obly and this variable is not accessible outside.So here there is no problem of assignment but the problem is related to scope and can be solved easily by

public class Casting {    public static void main(String[] args) {
  // casting doesn't change the object
   String w;
  Object obj;
  { 
      w = new String();
      obj = w;
  }
  System.out.println(obj); // this line does work
  System.out.println(w); //this line now working     } }
user3762901
  • 149
  • 1
  • 1
  • 5
0

Variable w is declared inside the block, thus out of the block it does not exist. This problem has nothing to do with casting. Remove braces and it will work:

public class Casting {
   public static void main(String[] args) {
      // casting doesn't change the object
      Object obj;
      Stopwatch w = new Stopwatch();
      obj = w;
      System.out.println(obj);
      System.out.println(w);
   }
}
Tagir Valeev
  • 87,515
  • 18
  • 194
  • 305
  • Okay awesome. Thank you. So then what does `Object obj;` followed by the set of braces do exactly? – rb612 May 04 '15 at 03:21
  • 2
    `Object obj;` just declares a variable `obj` of type `Object` and the statement ends here. After that comes a block statement which is independent from the previous declaration. The block statement has its own scope, which means that variables declared in block will not be visible outside it. – Tagir Valeev May 04 '15 at 03:23
0

As it metioned in other answers, removing the braces will work. Also you do as below if you want to keep the brackes. Actually in java , variables has scope, one variable can be used in scope where it is declared. Like if you declare some variable in "if" block or "try" block, it can be used in that scope only. This helps in effective garbage collection. And always it best to define variable in minimum needed scope However, if you are creating some object somewhere but you want to use it after that section (block), then declare (variable not necessary creating object) it outside the block.

public class Casting {
public static void main(String[] args) {
  // casting doesn't change the object
   Object obj;
  Stopwatch w ;
  { 
      w = new Stopwatch();
      obj = w;
  }
  System.out.println(obj); // this line does work
  System.out.println(w); //this line does not work 
  }
}
Panther
  • 3,124
  • 9
  • 25
  • 47
  • Thank you for your response. So now both println statements will work because you created the objects outside of the braces? – rb612 May 04 '15 at 03:28
  • 1
    Both println will work because I have declared both variable outside the braces. There is difference in creating object and declaring variable. Object will be created in braces where we have new keyword. However,that object will not be garbage collected till end of main method. As that variable w holding the object is declared outside the braces – Panther May 04 '15 at 03:59