Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Cloud/Virtualization forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

scope of local variables

 
Vinod Venkatasubramanian
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am curious as to why one of the following works while the other does not:
The following compiles fine:

Note that 's' and 'x' have be redefined in the outer scope.
The following throws a compile-time error ("s is already defined in main(java.lang.String[])"):

Can anyone explain why ?
[ edited to add and preserve formatting using the [code] and [/code] UBB tags -ds ]
[ October 20, 2003: Message edited by: Dirk Schreckmann ]
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Because in the second example, s is already defined, whereas in the first it isn't (it is only defined in the inner block), so it seems to me. Don't you agree?
 
Vinod Venkatasubramanian
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Iam not sure. As far as the compiler is concerned, there are only 2 scopes - the outer and inner one - I dont think there is a line-by-line parse which makes one scenario work and not the other.
A similar piece on C++ would work fine, wherever we put the definition in the outer scope. But in C++ you also have the scope resoultion operator (: to decide which one to refer to... not so in Java.
Putting what you said in other words - in the 2nd scenario, when the 's' is redefined in the inner scope, the one in the outer scope is still "in-scope". But this is not the case in the 1st scenario - by the time we reach the 's' in the outer scope, the one in the inner scope is already "out-of-scope". This seems to make sense...
Lets see if someone has any other view on it.
Thanks anyway !
[ October 19, 2003: Message edited by: Vinod Venkatasubramanian ]
 
Derek Baker
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That's totally contrary to what I thought about scopes.
I'd be interested to hear any input anyone has.
 
Wayne L Johnson
Ranch Hand
Posts: 399
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
From the "Java Language Specification",

If a declaration of an identifier as a local variable of the same method, constructor, or initializer block appears within the scope of a parameter or local variable of the same name, a compile-time error occurs.
Thus the following example does not compile:
class Test {
public static void main(String[] args) {
int i;
for (int i = 0; i < 10; i++)
System.out.println(i);
}
}

So a local variable in a method can "shadow" an instance variable [as in your first example], but a local variable can NOT "shadow" another local variable [as in your second example]. Why? Because that's what the language designer chose.
If you want to do more research, look at Java Language Specification.
[ October 20, 2003: Message edited by: Wayne L Johnson ]
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Wayne L Johnson:
So a local variable in a method can "shadow" an instance variable [as in your first example]

The first example also has two local variables - notice the unusual, but legal, use of a block at the start of the method.
 
Wayne L Johnson
Ranch Hand
Posts: 399
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ilja is correct ... I didn't look at the indentation carefully enough. The use of CODE tags would have helped, but mea culpa.
Java requires that you declare a local variable before it is referenced, whether it be at the beginning of a method or further down.
In the first example the String "s" is initially declared within a local block, so when when the block ends it goes out of scope. So there is no "s" in scope when the second declaration comes along, making it legal.
In the second example the String "s" is declared at the beginning of the method, so its scope is the entire method. As I stated [poorly] in my previous reply, you can not shadow a local variable, so even though the second declaration is within a local block, it is in violation of the Java language specification.
Better explanation, I hope.
 
Herb Schildt
Author
Ranch Hand
Posts: 253
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I agree with Wayne's second post. In the first example, s is declared inside a block that ends before the second s is declared. Thus, as Wayne states, the first s goes out-of-scope before the second s is declared. Thus, no conflicts.
However, in the second example, the first s preceeds the block. Because an inner scope incorporates all of the names currently declared by an enclosing scope, the attempt to create an s locale to the block fails because of the name conflict with the pre-exsting s.
 
Vinod Venkatasubramanian
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks everyone for pitching in !!!
Wayne, what you said seems to make sense... I was suspecting something similar (as in my second post) but could not put it in proper words.
I went throught the JLS and now its much clearer...
Coming from a C++ background (where both scenarios would work), guess I was expecting something else.
If you wonder WHY they made the specification like this, it might have to do with the fact that in Java, objects are not DESTROYED once they are out-of-scope.. they are only garbage collected. Whereas in C++, the 's' in the inner scope is destroyed once it has no meaning (ie, once that scope is exited)
Thanks again ! Appreciate your contributions a lot.
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Vinod Venkatasubramanian:
If you wonder WHY they made the specification like this, it might have to do with the fact that in Java, objects are not DESTROYED once they are out-of-scope.. they are only garbage collected. Whereas in C++, the 's' in the inner scope is destroyed once it has no meaning (ie, once that scope is exited)

I don't think this decision has any technical reason - it should have been easy to implement the C++ way.
I guess the true reason is that shadowing local variables (especially when done accidentally) can lead to nasty bugs and maintenance burdens, so they prevented it by not allowing to do it.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic