Scope

Things To Do First

Things To Do Later

What is Scope?

Scope refers to the visibility or accessibility of a variable (or a method, but for now we'll focus on variables) in a program. We've already had some dealings with variable scope: We know that a variable declared between a set of braces (e.g. in a loop or selection) is only available inside those braces. In the same way, a variable declared inside a method is local to that method. In other words, a variable declared inside a method can't be accessed outside that method. Recall a program such as this one:

public class MoreScope {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        int increment = 2;

        System.out.print("Please enter a whole number: ");
        int num = in.nextInt();

        addValue();
    }

    public static void addValue() {
        System.out.printf("Your value plus 2: %d\n", (num + increment));
    }
}

If you compile this program, you'll receive the following errors:

MoreScope.java:17: cannot find symbol
symbol  : variable num
location: class MoreScope
           System.out.printf("Your value plus 2: %d", (num + increment));
                                                            ^
MoreScope.java:17: cannot find symbol
symbol  : variable increment
location: class MoreScope
           System.out.printf("Your value plus 2: %d", (num + increment));
                                                                  ^
2 errors

Both of these errors occur because the addValue() method can't find a definition or declaration for the variables num and increment. These two variables were declared inside the main() method, so they are only available in the main() method. These variables are not available anywhere outside the main() method.

As we know, to solve this problem, we should pass the num and increment variables into the addValue() method as arguments.

Local Variables

Methods you write can include variable declarations, just keep in mind that these variables will be local variables: they will only be available inside that method. To understand the concept of local variables, type up the following program:

public class TestScope {
	
    public static void main(String[] args) {

        int number = 5;
        System.out.println("before method: " + number);
        doSomething();
        System.out.println("after method: " + number);
    }

    public static void doSomething() {
        int number = 10;
        System.out.println("in method: " + number);
    }
}

Before running the program, trace through it and see if you can guess what the output will be. Then run the program and see if your output matched the program's output.

When you run the program, you should see the following output:

before method: 5
in method: 10
after method: 5

Naturally, the first line of output displays the value in the main() method's number variable, which is 5. There is nothing unusual with this statement.

After displaying the value of number, the main() method then calls upon the doSomething() method. The program flow enters the doSomething() method and begins to execute the code statements within. The first statement declares a new int variable called number. This is a different variable than the one declared in the main() method! The doSomething() method's number variable is local to the doSomething() method -- it has it's own memory location, different from the one used by the main() method's number. If you were to imagine what the computer's memory would look like at this point in the program, it might look something like this:

scope of variables

After declaring and initializing the doSomething() method's number variable to 10, the contents of this variable are printed to the console. Then the method is finished and program flow returns to the main() method where it left off.

The next statement to execute is the second println() in the main() method. This statement displays the contents of the main() method's number variable on the screen.

In our program, we could have given the two variables different names if we wanted to (and this might even make the program easier to understand!). If you do decide to give two different local variables in two different methods the same name, that's ok. Just keep in mind that when a statement refers to a variable, it will always refer to the local one (the one declared in the same method in which the statement executes. For example, the main() method's print statements refer to the main() method's number variable, and the doSomething() statements will refer to the number variable defined inside the doSomething() method.

Sometimes a method is going to need access to variables that are not defined inside the method. Similarly, you will have programs that need access to variables that are defined in other methods and are therefore inaccessible. We can use arguments and parameters and methods that return values to help us get around these problems. Both of these concepts are covered in the next section.

Exercises

[solutions]

Manually trace the following program and determine the output, then run the program to see if you were correct.

public class TestScope {
	
    public static void main(String[] args) {

        int number = 1;
        System.out.println("in main: ");
        System.out.println("1. " + number);
        oneMethod();
        System.out.println("2. " + number);
        twoMethod();
        System.out.println("3. " + number);
    }

    public static void oneMethod() {
        int number = 5;
        System.out.print("  m1: ");
        System.out.print(number);
        number++;
        System.out.println(" " + number);
    }

    public static void twoMethod() {
        int number = 10;
        System.out.print("  m2:");
        System.out.println(" " + number);
    }
}

2. a) (if you've studied arrays)

Determine the output of the following code from each of the code segments below. Then copy the programs into your editor and run it. Is your output for each segment the same as the output you thought you would get? Why or why not?

// example 1
public static void main(String[] args) {
    int num = 10;
    doSomething(num); 
    System.out.println("num is " + num);
}
public static void doSomething(int n) {
    System.out.println("n is " + n);
    n = 0;
    System.out.println("now n is " + n);
}
                
// example 2
public static void main(String[] args) {
    int[] nums = {1, 2, 3};
    doSomething(nums); // pass nums array into method
    for (int n : nums)
        System.out.println(n);
}
// see the param: that's how you make array parameter
public static void doSomething(int[] array) {
    for (int i=0; i < array.length; i++)
        array[i] *= 2;
}
                

Class Variables (optional)

If you've programmed before or hung around people who have programmed, you might be familiar with public variables or global variables. These are variables with a higher level of scope; they are visible and accessible throughout an entire program or class. These are useful when you have a rare circumstance that requires a single variable to be accessible throughout a large program but it can't be passed from method to method. They're also useful when you want a variable to retain its value between invocations of methods while a program is running. For example, imagine you have a method, and you want to keep track of how many times that method executes. You might have something like:

public class ClassVarEx {
   
    public static void main(String[] args) {

        System.out.println("Testing class variables.");

        doSomething();
        doSomething();
        doSomething();
        doSomething();

        System.out.println("The method executed " 
            + numTimes + " times.");
    }

    public static void doSomething() {
        int numTimes = 0;
        System.out.println("This is my method.");
        numTimes++;
    }
}

You should recognize by now that this program will not work. Each time the method executes, the numTimes variable is declared and initialized to 0. Because numTimes is declared inside the doSomething() method, it's a local variable; once the method has finished execution, the variable no longer exists. It is then re-created and set to 0 each time the method starts again and encounters the variable's declaration statement. Clearly, this does not do what we'd like.

You might think a different solution would be to declare the variable in the main () method:

public class ClassVarEx {
   
    public static void main(String[] args) {

        int numTimes = 0; 
        System.out.println("Testing class variables.");

        doSomething();
        doSomething();
        doSomething();
        doSomething();

        System.out.println("The method executed " 
            + numTimes + " times.");
    }

    public static void doSomething() {
        System.out.println("This is my method.");
        numTimes++;
    }
}

Once again, this won't work. The numTimes variable is declared in the main() method, therefore it's local to the main() method. This variable is not available anywhere outside the main() method. Clearly we require some other solution.

In most programming languages, a global or public variable will do just fine. This kind of variable will allow your program to "remember" a value that can't be passed from one method to another. To do this in Java, we create a class variable. A class variable is declared inside your class but outside of any method (it usually goes at the top, under the class header, but that's not mandatory, just considered good style).

Unlike global or public variables in other languages, class variables used in a regular class that is not a template for objects should be declared as private static. When you start programming classes that model objects in an object-oriented program, you might declare them as public, but for now, they remain private.

The sample program is shown below, using a class variable:

public class ClassVarEx {
   
    private static int numTimes;

    public static void main(String[] args) {

        System.out.println("Testing class variables.");

        doSomething();
        doSomething();
        doSomething();
        doSomething();

        System.out.println("The method executed " 
            + numTimes + " times.");
   }

    public static void doSomething() {
        System.out.println("This is my method.");
        numTimes++;
   }
}

One serious thing you should have noted about this program is that the class variable numTimes was not initialized! This is yet another characteristic of class variables: They don't have to be initialized.