a black woman types on a laptop
Photo from create her stock

Scope is where a variable exists can be accessed in your code, and it’s surprisingly complicated.

The short version is that a variable that was declared inside a block only exists inside that block. Great, what’s a block? In Java, it’s anything between a set of curly brackets { }. Blocks can be nested, too. A method inside of a class can see the class’s variables, and a block inside of a method (like an if or a loop) can see the method’s variables. Nesting only works inwards, outer blocks can’t see inside inner blocks. Once a block finishes executing its variables cease to exist, so there’s really nothing for the outer block to see.

Java also makes things more complicated with scope modifiers: classes, methods, and variables can be public, private, or protected. Those modifiers only apply outside of methods, they don’t make sense for variables that are just going to vanish after the method executes. Public means the “thing” (class, method, or field/class variable) can be accessed from outside the class. Private and protected classes are sort of a weird special case, they only make sense if you have a nested class inside another one. Public things can be accessed from outside the class, private things can be accessed only from inside the class, and protected things can only be accessed by subclasses of the class where they were declared.

Just like each time a method is run it gets a fresh copy of all of its variables, each time a class is instantiated it gets a fresh copy of all of its variables too. Unless any of them were declared static, in case you didn’t already have enough to keep track of :) The difference between classes and objects created by instantiating those classes was a hard concept for me when I started programming, don’t feel bad if you’re confused. Classes aren’t things you can interact with, they’re just blueprints for things. Once you create an actual thing by instantiating a class, then you can call methods on it. Unless you made that method or variable static, then you can use it without actually having an instance of the class. Static variables are special, normally every instantiation of the class gets its own variables, but static variables are shared between all instances of the class.

Why would you want to have just one instance of a variable for all instances of a class you’ll ever have? If you have any constants in the class, they should be declared static (also final, which means, surprisingly enough, that you can never change it) to save memory. If the constant is only ever going to have one value, there’s no reason to waste memory by giving every instance of the class its own copy. You might also want to make something static if it’s a shared resource like a logger. You really only need one logger per class, so again you can save memory by sharing one logger instead of giving every instance its own copy.

So that’s all well and good, but why does scope work the way it does? Partially I think it’s for the convenience of the programmer :) How much would it suck if you could never reuse a variable name because all variables were visible anywhere? And how much of a hassle would it be to keep track of which variable you were using versus which one you meant if all of them were visible?

Aside from convenience, there is an actual reason for variable scope to work the way it does. It has to do with the way the computer keeps track of exactly which code is executing at any given time. To over simplify a bit, when a program is executed it gets two chunks of memory, the stack and the heap. The heap is where objects live, and the stack is where the computer keeps track of where it is in the program and what values all the variables have. When method a calls method b, the computer stores the state of method a on the stack, then creates a new state for method b with all of its variables and stores it on the stack too. When method b finishes, the computer keeps its return value (if it returned anything), to update method a’s state with, then it throws away the state for method b. That’s what I was talking about when I said that variables cease to exist when a block finishes executing – the computer throws out its only record of what values those variables had. You can read more about memory and execution in this article, which has some pictures to help visualize what’s going on.

What about static variables, if they live in the stack why don’t they disappear? My understanding is that they actually live in the heap (where stuff stays until you deliberately get rid of it), and what goes on the stack is just the address of where the static variable lives in the heap.

Scope might seem really simple if you’ve been programming for a little while, but let me throw a wrench into that idea: multi-threading. With multiple threads running the same code, it can be really difficult to figure out why on earth your variable suddenly has a value that makes no sense. Not that I’ve ever spent multiple days swearing at my computer for making no sense ;)