4.5 Scope Rules

Java provides explicit accessibility modifiers to control the accessibility of members in a class by external clients (see Section 4.9, p. 137), but in two areas access is governed by specific scope rules:

  • Class scope for members: how member declarations are accessed within the class.

  • Block scope for local variables: how local variable declarations are accessed within a block.

Class Scope for Members

Class scope concerns accessing members (including inherited ones) from code within a class. Table 4.1 gives an overview of how static and non-static code in a class can access members of the class, including those that are inherited. Table 4.1 assumes the following declarations:

class SuperName {
    int instanceVarInSuper;
    static int staticVarInSuper;

    void instanceMethodInSuper()      { /* ... */ }
    static void staticMethodInSuper() { /* ... */ }
    // ...
}

class ClassName extends SuperName {
    int instanceVar;
    static int staticVar;

    void instanceMethod()      { /* ... */ }
    static void staticMethod() { /* ... */ }
    // ...
}

The golden rule is that static code cannot access non-static members by their simple names. Static code is not executed in the context of an object, therefore the references this and super are not available. An object has knowledge of its class, therefore, static members are always accessible in a non-static context.

Note that using the class name to access static members within the class is no different from how external clients access these static members.

Some factors that can influence the scope of a member declaration are

  • shadowing of a field declaration, either by local variables (see Section 4.3, p. 114) or by declarations in the subclass (see Section 6.2, p. 233)

  • initializers preceding the field declaration (see Section 8.2, p. 331)

  • overriding an instance method from a superclass (see Section 6.2, p. 233)

  • hiding a static method declared in a superclass (see Section 6.2, p. 233)

Accessing members within nested classes is discussed in Chapter 7.

Table 4.1. Accessing Members within a Class

Member declarations

Non-static Code in the Class ClassName Can Refer to the Member as

Static Code in the Class ClassName Can Refer to the Member as

Instance variables

instanceVar
this.instanceVar
instanceVarInSuper
this.instanceVarInSuper
super.instanceVarInSuper

Not possible

Instance methods

instanceMethod()
this.instanceMethod()
instanceMethodInSuper()
this.instanceMethodInSuper()
super.instanceMethodInSuper()

Not possible

Static variables

staticVar
this.staticVar
ClassName.staticVar
staticVarInSuper
this.staticVarInSuper
super.staticVarInSuper
ClassName.staticVarInSuper
SuperName.staticVarInSuper
staticVar

ClassName.staticVar
staticVarInSuper


ClassName.staticVarInSuper
SuperName.staticVarInSuper

Static methods

staticMethod()
this.staticMethod()
ClassName.staticMethod()
staticMethodInSuper()
this.staticMethodInSuper()
super.staticMethodInSuper()
ClassName.staticMethodInSuper()
SuperName.staticMethodInSuper()
staticMethod()

ClassName.staticMethod()
staticMethodInSuper()


ClassName.staticMethodInSuper()
SuperName.staticMethodInSuper()

Within a class C, reference variables of type C can be used to access all members in the class C, regardless of their accessibility modifiers. In Example 4.6, the method duplicateLight at (1) in class Light has a parameter oldLight and a local variable newLight that are references to Light objects. Even though the fields of the class are private, they are accessible through the two references (oldLight and newLight) in the method duplicateLight() as shown at (2), (3), and (4).

Example 4.6 Class Scope
class Light {
    // Instance variables
    private int     noOfWatts;       // wattage
    private boolean indicator;       // on or off
    private String  location;        // placement

    // Instance methods
    public void switchOn()  { indicator = true; }
    public void switchOff() { indicator = false; }
    public boolean isOn()   { return indicator; }

    public static Light duplicateLight(Light oldLight) {       // (1)
        Light newLight = new Light();
        newLight.noOfWatts = oldLight.noOfWatts;               // (2)
        newLight.indicator = oldLight.indicator;               // (3)
        newLight.location  = oldLight.location;                // (4)
        return newLight;
   }
}

Block Scope for Local Variables

Declarations and statements can be grouped into a block using braces, {}. Blocks can be nested, and certain scope rules apply to local variable declarations in such blocks. A local declaration can appear anywhere in a block. The general rule is that a variable declared in a block is in scope inside the block in which it is declared, but it is not accessible outside of this block. It is not possible to redeclare a variable if a local variable of the same name is already declared in the current scope.

Local variables of a method are comprised of formal parameters of the method and variables that are declared in the method body. The local variables in a method are distinct for each invocation, and have their own storage.

A method body is a block. Parameters cannot be redeclared in the method body, as shown at (1) in Block 1 (see Figure 4.2).

Figure 4.2. Block Scope

graphics/04fig02.gif

A local variable?already declared in an enclosing block and, therefore, visible in a nested block?cannot be redeclared in the nested block. These cases are shown at (3), (5), and (6).

A local variable in a block can be redeclared in another block if the blocks are disjoint, that is, they do not overlap. This is the case for variable i at (2) in Block 3 and at (4) in Block 4, as these two blocks are disjoint.

The scope of a declaration begins from where it is declared in the block and ends where this block terminates. The scope of the loop variable index is Block 2. Even though Block 2 is nested in Block 1, the declaration of the variable index at (7) in Block 1 is valid. Its scope spans from its declaration to the end of this block, and it does not overlap with that of the loop variable index in Block 2.