Java gravel of the day: no block scoped variables

jdavidb on 2008-09-26T18:25:38

I can't make this work because the inner block declares a variable of the same name as one in the outer block. Apparently variables belong to the method or class in which they are declared, not to the block in which they are declared, so I therefore can't write a short little temporary block for debugging that happens to push a variable in the outer scope off into shadow just for a moment:

void methodName() {
  int i = 7;
  for (int j = 0; j < 10; j++) {
    int i = j * 2;
  }
}

Perl can do this. scheme can do this. C can do this. Why can't Java?


JS 1.7 Java?

Mr. Muskrat on 2008-09-26T19:11:15

JavaScript 1.7 has block scoped variables. I'm not sure what browsers besides FF 2 and newer support it though.

<html>
<head>
<title>Block Scoped Variables</title>
<script type="application/javascript;version=1.7">

function methodName() {
    let (i = 7) {
        document.writeln('start: i is ' + i + '<br>');
        for( var j = 0; j < 10; j++ ) {
            let (i = j * 2) {
                document.writeln('loop: i is ' + i + '<br>');
            }
        }
        document.writeln('end: i is ' + i + '<br>');
    }
}
</script>
</head>
<body>
<p>Testing block scoped variables in JS</p>
<script type="application/javascript;version=1.7">methodName();</script>
</body>
</htm l>

Output:

Testing block scoped variables in JS
start: i is 7
loop: i is 0
loop: i is 2
loop: i is 4
loop: i is 6
loop: i is 8
loop: i is 10
loop: i is 12
loop: i is 14
loop: i is 16
loop: i is 18
end: i is 7

Re:JS 1.7 Java?

Mr. Muskrat on 2008-09-26T19:12:16

Dang it. My subject was supposed to be "JS 1.7 > Java?"

Re:JS 1.7 Java?

malte on 2008-09-27T13:31:55

In JS there is also always the ugly bastard (function () { var iHaveMyOwnScope = '...' })().

Re:JS 1.7 Java?

Mr. Muskrat on 2008-09-27T15:12:18

I had forgotten about that syntax (for very good reason, it's so ugly).

You're talking about Java and not Javascript?

merlyn on 2008-09-26T21:47:00

According to the first hit I got for "java block local variables", it looks like the variable declared in your "for" statement is actually outside the scope of that local block, but otherwise, the scope of a local variable inside a block is in fact inside the block and may temporarily obscure outer variables.

Now in JavaScript, the rules are different, but I presume you're smart enough not to say "Java" when you mean "JavaScript".

Re:You're talking about Java and not Javascript?

Mr. Muskrat on 2008-09-27T15:21:32

Considering he does Java programming most of the time now, I doubt he'd mistakenly call JavaScript Java.

I haven't written any Java since about 1998 and I try not to read it too often as it usually makes my head hurt. ;)

But if I'm reading this right, it looks like the for loop would need to be enclosed inside another block for it to work like J. David is expecting...

void methodName() {
  int i = 7;
  {
    for (int j = 0; j < 10; j++) {
      int i = j * 2;
    }
  }
}

Re:You're talking about Java and not Javascript?

jdavidb on 2008-09-29T14:29:31

Apparently my example has confused nearly everyone I've asked about this. Yes, I meant Java. The for loop actually has nothing to do with it. Let me say it in Perl, and drop the for:

sub my_routine
{
  my($i) = @_;
  {
    my $i = 18;  # different $i from the other one
  }
}

Of course, you can argue all day that declaring a variable in an inner block that shadows a variable in an outer block like this is a bad idea. It probably is. :) But the question for me is: did Java designers actually sit down and intend to prevent this, or were they just wimpy language designers who couldn't figure out how to do something that's perfectly possible for Perl, C, Scheme, and even PL/SQL?

The scenario that's going on here is I'm dealing with somebody else's 4000-line method, I was wanting to insert a little block somewhere for debugging purposes, and I wanted to declare my own temporary local variables for that block without having to worry about what other variables had been declared by Somebody Else in said monstrously-long method. It was a temporary annoyance, easily fixable reading the compiler's gripes and using a different variable name. But it spawned this larger question for me as to why Java chose to be this way.

Feature

ChrisDolan on 2008-09-28T03:10:50

Reusing a variable name in the same method is a TERRIBLE idea and is a beartrap waiting for some future maintenance programmer. Why would you want to do that?

This sounds like a great opportunity for a Perl::Critic policy.

Re:Feature

ChrisDolan on 2008-09-28T04:54:03

OK, done. There is now a P::C policy for this:

http://perlcritic.tigris.org/source/browse/perlcritic/trunk/Perl-Critic/lib/Perl /Critic/Policy/Variables/ProhibitReusedVarNames.pm

Comments welcome.

Re:Feature

Ovid on 2008-09-30T17:54:32

Comments welcome.

How does "++" grab you? :)