Scope of Declarations
You have seen declarations of various Java entities, such as classes, methods, variables and parameters. Declarations introduce names that can be used to refer to such Java entities. The scope of a declaration is the portion of the program that can refer to the declared entity by its name. Such an entity is said to be "in scope" for that portion of the program. This section introduces several important scope issues. (For more scope information, see the Java Language Specification, Section 6.3: Scope of a Declaration, at java.sun.com/docs/books/jls/second_edition/html/names.doc.html#103228.)
The basic scope rules are as follows:
- The scope of a parameter declaration is the body of the method in which the declaration appears.
- The scope of a local-variable declaration is from the point at which the declaration appears to the end of that block.
- The scope of a local-variable declaration that appears in the initialization section of a for statement's header is the body of the for statement and the other expressions in the header.
- The scope of a method or field of a class is the entire body of the class. This enables non-static methods of a class to use the class's fields and other methods.
Any block may contain variable declarations. If a local variable or parameter in a method has the same name as a field, the field is "hidden" until the block terminates executionthis is called shadowing. In Chapter 8, we discuss how to access shadowed fields.
Common Programming Error 6.10
A compilation error occurs when a local variable is declared more than once in a method. |
Error-Prevention Tip 6.3
Use different names for fields and local variables to help prevent subtle logic errors that occur when a method is called and a local variable of the method shadows a field of the same name in the class. |
The application in Fig. 6.11 and Fig. 6.12 demonstrates scoping issues with fields and local variables. When the application begins execution, class ScopeTest's main method (Fig. 6.12, lines 711) creates an object of class Scope (line 9) and calls the object's begin method (line 10) to produce the program's output (shown in Fig. 6.12).
Figure 6.11. Scope class demonstrating scopes of a field and local variables.
(This item is displayed on page 256 in the print version)
1 // Fig. 6.11: Scope.java 2 // Scope class demonstrates field and local variable scopes. 3 4 public class Scope 5 { 6 // field that is accessible to all methods of this class 7 private int x = 1; 8 9 // method begin creates and initializes local variable x 10 // and calls methods useLocalVariable and useField 11 public void begin() 12 { 13 int x = 5; // method's local variable x shadows field x 14 15 System.out.printf( "local x in method begin is %d ", x ); 16 17 useLocalVariable(); // useLocalVariable has local x 18 useField(); // useField uses class Scope's field x 19 useLocalVariable(); // useLocalVariable reinitializes local x 20 useField(); // class Scope's field x retains its value 21 22 System.out.printf( " local x in method begin is %d ", x ); 23 } // end method begin 24 25 // create and initialize local variable x during each call 26 public void useLocalVariable() 27 { 28 int x = 25; // initialized each time useLocalVariable is called 29 30 System.out.printf( 31 " local x on entering method useLocalVariable is %d ", x ); 32 ++x; // modifies this method's local variable x 33 System.out.printf( 34 "local x before exiting method useLocalVariable is %d ", x ); 35 } // end method useLocalVariable 36 37 // modify class Scope's field x during each call 38 public void useField() 39 { 40 System.out.printf( 41 " field x on entering method useField is %d ", x ); 42 x *= 10; // modifies class Scope's field x 43 System.out.printf( 44 "field x before exiting method useField is %d ", x ); 45 } // end method useField 46 } // end class Scope |
Figure 6.12. Application to test class Scope.
(This item is displayed on page 257 in the print version)
1 // Fig. 6.12: ScopeTest.java 2 // Application to test class Scope. 3 4 public class ScopeTest 5 { 6 // application starting point 7 public static void main( String args[] ) 8 { 9 Scope testScope = new Scope(); 10 testScope.begin(); 11 } // end main 12 } // end class ScopeTest
|
In class Scope, line 7 declares and initializes the field x to 1. This field is shadowed (hidden) in any block (or method) that declares a local variable named x. Method begin (lines 1123) declares a local variable x (line 13) and initializes it to 5. This local variable's value is output to show that the field x (whose value is 1) is shadowed in method begin. The program declares two other methodsuseLocalVariable (lines 2635) and useField (lines 3845)that each take no arguments and do not return results. Method begin calls each method twice (lines 1720). Method useLocalVariable declares local variable x (line 28). When useLocalVariable is first called (line 17), it creates local variable x and initializes it to 25 (line 28), outputs the value of x (lines 3031), increments x (line 32) and outputs the value of x again (lines 3334). When uselLocalVariable is called a second time (line 19), it re-creates local variable x and re-initializes it to 25, so the output of each useLocalVariable call is identical.
Method useField does not declare any local variables. Therefore, when it refers to x, field x (line 7) of the class is used. When method useField is first called (line 18), it outputs the value (1) of field x (lines 4041), multiplies the field x by 10 (line 42) and outputs the value (10) of field x again (lines 4344) before returning. The next time method useField is called (line 20), the field has its modified value, 10, so the method outputs 10, then 100. Finally, in method begin, the program outputs the value of local variable x again (line 22) to show that none of the method calls modified start's local variable x, because the methods all referred to variables named x in other scopes.