11
$\begingroup$

One of the problems that my students will stumble upon every year is trying to create or initialize variables within an if/else block. Why, oh why, can't they perform an operation like this?

if (someBooleanCondition){
    int x = 7;
} else {
    int x = 0;
}
System.out.println(x);

After all, they reason that x has been created and initialized no matter what. This year, I discovered a nice way of explaining why this operation does not work. I will be posting my answer below, and I am also curious to see if others have different explanations that they use with their students (or corrections to mine).

$\endgroup$
5
  • 1
    $\begingroup$ [I have not tried this.] When showing how variables work, using the box metaphor, burn the box(and its content) at the end of its block. (you may want to do this out-side.) $\endgroup$ Commented May 31, 2017 at 7:40
  • 2
    $\begingroup$ Suggested better title “How to illustrate scope problem when creating variables inside if statements.” — with current title my first thought was “Yes you can”. $\endgroup$ Commented May 31, 2017 at 7:42
  • $\begingroup$ Its certainly a scope problem, and there's no problem with initialising (except for only initialising in one path). $\endgroup$ Commented May 31, 2017 at 9:45
  • $\begingroup$ That's a much better title. Thanks, @richard. $\endgroup$
    – Ben I.
    Commented May 31, 2017 at 10:29
  • $\begingroup$ Scope of variables, and distinction between declaration and initialization. Anyway students stumble every year, because they are learning. $\endgroup$ Commented Sep 22, 2019 at 8:49

7 Answers 7

8
$\begingroup$

I like to use an analogy from Finding Nemo. I tell them their programming language has the same problem Dory has - short-term memory loss. When a variable is declared within a block, Java will forget about the variable (just like Dory) after reaching the end of the the block. So a block declares the "scope" of Dory's short term memory.

I've been concerned that students would think that the variables assigned in a block would lose their value after the block has ended, but I've never run into that problem for some reason.

What's interesting about your example is that it won't even compile without the print statement! Java doesn't allow you to have a single declaration statement in an if or loop.

$\endgroup$
3
  • 1
    $\begingroup$ I don't get what you mean in the 2nd paragraph. Do you mean that the variable still exist but have a value of undefined? $\endgroup$ Commented May 31, 2017 at 7:32
  • 1
    $\begingroup$ I like it. I don't understand it, since I have no context for Dory (never watched Finding Nemo). That's part of the problem, finding context that matches what the students know. $\endgroup$ Commented Jun 1, 2017 at 3:55
  • $\begingroup$ Here's a scene from the movie that you could show for reference: youtube.com/watch?v=tESffhWs8l0 $\endgroup$ Commented Jun 1, 2017 at 18:24
6
$\begingroup$

I explain this with a saying:

What happens in the block stays in the block

Now, this isn't exactly how it works, but the idea is that the students remember that what they create in a block, is accessible only inside the block.

So:

if(shouldGoIntoBlock){
    int x=10;//created in the block
    System.out.println("printed from if body: "+ x);
else{
    int x=-7;//created in the block
    System.out.println("printed from else body: "+ x);
}
System.out.println("printed outside of blocks: "+x);

And they see in eclipse that the last print errors in compile time. That shows them that what's created in the block stays in the block.

Next, I show them that there will also be an error if we define x before the if-else block, but the last line won't error. So they see that order of creation matters. Afterwards, I show them that creating x after the if-else block and before the last print, then there are no errors.

The vast majority of the students understand the idea this way.

They don't learn the stack segment of the computer at that time, but they see that order matters, and that makes learning about the stack easier for them when they learn it later in the year.

$\endgroup$
5
$\begingroup$

I teach my students a bit about the stack as part of the very first lesson of the year. As a result, they are aware coming in that primitive variables are stored next to one another in the stack during runtime, and that the names of the primitive variables that we use in our code are removed by the compiler, and replaced with memory locations. They are also aware by this time that the stack is populated in the order in which variables are declared. Thus, I show them the following code, and ask a simple question:

if (someBooleanCondition){
    int v = 18;
    int x = 7;
} else {
    int x = 0;
    int v = o;
}

If we now wanted to run System.out.println(x), it is true that x has a value, but what is its location? If someBooleanCondition is true, x will be at the higher of the two addresses, whereas if it is false, x will be at the lower of the two addresses How would the compiler know where to direct System.out.println to find x?

Thus, the scope of variables declared during if statements must be local to that if statement, and cannot be used outside of it.

$\endgroup$
3
$\begingroup$

Java, like C/C++ has block scope. When you create a variable in a block, the stack pointer moves to make room for it. When the block ends, the stack pointer moves back. This makes the variable inaccessible. It will be overwritten the next time the stack pointer moves over it.

Python and JavaScript have function scope. Note, however that in ECMA 6, the let construct gives variables block scope.

$\endgroup$
3
$\begingroup$

You should be able to copy/paste block of codes that does not use other variables. But in your examples what if you want to copy/paste that to a code that already declared x? It would not work

String x = "Ben I.";
... a lot of code
...
...
if (someBooleanCondition){
    int x = 7;
} else {
    int x = 0;
}
System.out.println(x);

In that case you want to print Ben I. In block scope very often you need to use temporary variables to help you in some calculations and if you declared them in block then you want them to be cleared from stack when you get out of the block.

$\endgroup$
2
$\begingroup$

Something that might be helpful is using computers. Files created on the school computer in the classroom don't exist anywhere else. The file can be copied somewhere else, just like passing it back from a function copies the data, not the variable, to the caller.

To demonstrate inner block access to variables at higher level you can use Google Drive, or something similar. A file on Google Drive can be edited using the web interface, so the local computer has access to the data. Still, the data belongs to Google Drive, so any other computer can also access it and change it. Just like all the loops and blocks in the current subroutine have access to data that belongs to the routine, or anything that is has access to from an even higher level. (The last part might be language dependent, and not apply in the language you utilize, and can be dropped.)

A second option is just to use the directory structure of the computer itself. Creating /home/mine/Documents/computer_class/project_1/notes.txt will show file not found if you try to access /home/mine/Documents/computer_class/notes.txt. [Or for Windows C:\Users\mine\Documents\Computer Class\Project 1\notes.txt can't be edited using C:\Users\mine\Documents\Computer Class\notes.txt.]

One thing to bear in mind is that not all languages enforce variables to be scoped at that granular of a level, or at all. In addition, how that scope is enforced, or implemented, can also be language dependent. If the language in use has been dissected by the class, then using its internal process can explain why it happens in that case.

Unless the students will always be using that language, even after school, I think it's important to also make them aware that those rules may, or may not, apply, and that when they don't apply side effects can become an issue. In some cases the value isn't undefined, as in non-existent, rather it can be undetermined, as in something is there, but not sure what.

$\endgroup$
2
  • $\begingroup$ If we were to use this analogy, how would we deal with variables declared prior to the if, which are accessible inside of it, or instance variables? $\endgroup$
    – Ben I.
    Commented Jun 5, 2017 at 2:18
  • $\begingroup$ Depends on which version. For Google Drive, the local computer (inside if has access to Google Drive (outside if) but Google Drive has no access to local computer. For the file system version emulate the if block's access with a symlink/shortcut. The file (variable) still belongs to the higher level, but the inner block has been granted access (probably by reference, either to the outer block's scope, or to the data itself). $\endgroup$ Commented Jun 5, 2017 at 2:24
1
$\begingroup$

Another benefit of block-level scope is that because variables defined in a block go out of scope at the end of that block, their values are then eligible for garbage collection (assuming no other variables point to them).

Expand your example to use some really big object that takes up a lot of memory:

if (someBooleanCondition){
    ReallyBigObject rbo = getReallyBigObject();
    rbo.doSomeProcessing();
} else {
    ReallyBigObject rbo = getOtherReallyBigObject();
    rbo.doSomeOtherProcessing();
}

//rbo is out of scope and can be garbage collected!

With the way Java works, the really big object goes out of scope at the end of the if or else block it's declared in. That means it can be garbage collected, and that's awesome because we don't have to worry about it anymore!

It's possible to have function-level scope (like JavaScript), so the students' intuition isn't wrong. It's just that Java chose a set of rules to allow garbage collection to happen sooner rather than later.

But as a result, this also means that you can't use a variable outside of its scope.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.