Skip to main content

Unit 3 · Topic 3.8

3.8 Scope and Access

Scope is the part of a program where a variable can be used. This topic covers local variables and parameters, the blocks that limit them, and shadowing, where a local name hides an instance variable with the same name.

Key terms

  • scope
  • local variable
  • block
  • shadowing

Local variables

A local variable is declared inside a block of code: a method, a constructor, a loop or an if body. It exists only from where it's declared to the end of that block. A variable declared in a for loop header exists only inside that loop.

Parameters are local variables too. They exist only inside their method or constructor.

Local variables can't be marked public or private. Those words only make sense for things that belong to the class, like instance variables and methods. Writing private int result = 0; inside a method is a compile error.

Instance variables are different: they're declared in the class, outside every method, so every method and constructor in the class can use them.

Two different methods can each have a local variable with the same name, like i or total. They're completely separate variables that happen to share a name, and changing one never affects the other. Each call to a method also gets fresh local variables, so locals don't remember anything from one call to the next. If a value has to be remembered between calls, it must be an instance variable.

Blocks

In this method, score and bonus can be used anywhere in record, but gap exists only inside the if body:

public class Scores { private int best; public void record(int score) { int bonus = 5; if (score > best) { int gap = score - best; best = score; System.out.println("new best by " + gap); } System.out.println(bonus + score); } }

Trying to print gap after the if would be a compile error, because by then gap no longer exists. If you need a value after a block ends, declare the variable before the block.

Shadowing

When a parameter or local variable has the same name as an instance variable, the name refers to the local one inside that method or constructor. The instance variable is hidden, or shadowed.

That causes a quiet bug when a parameter has the same name as the instance variable it's meant to set:

public class Pet { private String name; public Pet(String name) { name = name; } public String getName() { return name; } }

Inside the constructor, both names mean the parameter, so name = name; copies the parameter into itself. The instance variable is never set and stays null. To fix it, give the parameter a different name, or use this.name = name; (3.9).

Worked examples

Try each one yourself first, then open the solution.

  1. Example 1

    The shadowing bug

    Using the Pet class above, what does this code print?Pet p = new Pet("Biscuit"); System.out.println(p.getName());

    Show the solution
    1. Step 1: The constructor's parameter is called name, the same as the instance variable.
    2. Step 2: Inside the constructor, name means the parameter, so name = name; just assigns the parameter to itself.
    3. Step 3: The instance variable name was never assigned, so it still has its default value, null.
    4. Step 4: getName() isn't shadowed (it has no local name), so it returns the instance variable.

    Answer: It prints null.

  2. Example 2

    Finding the scope error

    Why doesn't this class compile?public class Scores { private int best; public void record(int score) { if (score > best) { int gap = score - best; best = score; } System.out.println(gap); } }

    Show the solution
    1. Step 1: gap is declared inside the if body, so its scope is just that block.
    2. Step 2: The println comes after the if block ends, where gap doesn't exist.
    3. Step 3: The fix is to declare int gap = 0; before the if and assign it inside, or to move the println into the block.

    Answer: gap is used outside the block where it was declared, so the compiler can't find it.

Common mistakes

  • Writing name = name; in a constructor whose parameter shares the instance variable's name. Use a different parameter name or this.name.
  • Using a variable after the block it was declared in has ended.
  • Putting private or public on a local variable.
  • Redeclaring an instance variable inside the constructor (like int count = 0;), which makes a new local variable instead of setting the instance variable.

On the exam

  • Questions about why an object's instance variable is still 0 or null after construction often come down to shadowing, or to a constructor that declares a local variable by mistake.

Connected topics

Videos

Check yourself

4 questions on 3.8 Scope and Access. Pick an answer to see if you got it, and why.

Question 1 of 4

Consider the following class.public class Score { private int points; public Score(int points) { points = points; } public int getPoints() { return points; } }What is printed as a result of executing System.out.println(new Score(50).getPoints()); in another class?

Question 2 of 4

Consider the following method.public static int calc(int n) { if (n > 0) { int doubled = n * 2; } return doubled; }Which of the following best describes the result of compiling the method?

Question 3 of 4

Each of the following statements appears inside the body of a method. Which one causes a compile-time error?

Question 4 of 4

Consider the following class.public class Game { private int points; public Game(int p) { points = p; } public void addPoints(int amount) { int points = 0; points += amount; } public int getPoints() { return points; } }What is printed as a result of executing the following code segment, which appears in a class other than the one shown?Game g = new Game(10); g.addPoints(5); System.out.println(g.getPoints());

0 of 4 answered