Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
java_language_specification_7.pdf
Скачиваний:
13
Добавлен:
21.03.2016
Размер:
3.11 Mб
Скачать

NAMES

Shadowing and Obscuring

6.4

In the following program, the initializer for three can correctly refer to the variable two declared in an earlier declarator, and the method invocation in the next line can correctly refer to the variable three declared earlier in the block.

class Test3 {

public static void main(String[] args) { System.out.print("2+1=");

int two = 2, three = two + 1; System.out.println(three);

}

}

This program produces the output:

2+1=3

6.4 Shadowing and Obscuring

A local variable (§14.4), formal parameter (§8.4.1), exception parameter (§14.20), and local class (§14.3) can only be referred to using a simple name (§6.2), not a qualified name (§6.6).

Some declarations are not permitted within the scope of a local variable, formal parameter, exception parameter, or local class declaration because it would be impossible to distinguish between the declared entities using only simple names.

For example, if the name of a formal parameter of a method could be redeclared as the name of a local variable in the method body, then the local variable would shadow the formal parameter and the formal parameter would no longer be visible - an undesirable outcome.

It is a compile-time error if the name of a formal parameter is redeclared as a local variable of the method or constructor; or as an exception parameter of a catch clause in a try statement in the body of the method or constructor; or as a resource in a try-with-resources statement in the body of the method or constructor.

It is a compile-time error if the name of a local variable v is redeclared as a local variable of the directly enclosing method, constructor, or initializer block within the scope of v; or as an exception parameter of a catch clause in a try statement of the directly enclosing method, constructor or initializer block within the scope of v; or as a resource in a try-with-resources statement of the directly enclosing method, constructor or initializer block within the scope of v.

133

6.4

Shadowing and Obscuring

NAMES

It is a compile-time error if the name of a local class C is redeclared as a local class of the directly enclosing method, constructor, or initializer block within the scope of C.

It is a compile-time error if the name of an exception parameter is redeclared within the Block of the catch clause as a local variable of the directly enclosing method, constructor, or initializer block; or as an exception parameter of a catch clause in a try statement of the directly enclosing method, constructor or initializer block; or as a resource in a try-with-resources statement of the directly enclosing method, constructor or initializer block.

It is a compile-time error if the name of a variable declared in a ResourceSpecification of a try-with-resources statement (§14.20.3) is redeclared within the try Block as a local variable of the directly enclosing method, constructor, or initializer block, or as an exception parameter of a catch clause in a try statement of the directly enclosing method or initializer block.

The translation of a try-with-resources statement implies the rule above.

Despite the above rules against redeclaration of variables, the rules of shadowing (§6.4.1) allow redeclaration in certain nested class declarations (i.e. local classes (§14.3) and anonymous classes (§15.9)) as follows:

A formal parameter of a method or constructor may be shadowed anywhere inside a class declaration nested within that method or constructor.

A local variable of a method, constructor, or initializer may be shadowed anywhere inside a class declaration nested within the scope of the local variable.

A local class declaration may be shadowed anywhere inside a class declaration nested within the local class declaration's scope.

An exception parameter may be shadowed anywhere inside a class declaration nested within the Block of the catch clause.

A variable declared in a ResourceSpecification may be shadowed anywhere inside a class declaration nested within the try Block.

Example 6.4-1. Attempted Shadowing Of A Local Variable

Because a declaration of an identifier as a local variable of a method, constructor, or initializer block must not appear within the scope of a parameter or local variable of the same name, a compile-time error occurs for the following program:

class Test1 {

public static void main(String[] args) { int i;

for (int i = 0; i < 10; i++) System.out.println(i);

}

134

NAMES

Shadowing

6.4.1

}

This restriction helps to detect some otherwise very obscure bugs. A similar restriction on shadowing of members by local variables was judged impractical, because the addition of a member in a superclass could cause subclasses to have to rename local variables. Related considerations make restrictions on shadowing of local variables by members of nested classes, or on shadowing of local variables by local variables declared within nested classes unattractive as well.

Hence, the following program compiles without error:

class Test2 {

public static void main(String[] args) { int i;

class Local {

{

for (int i = 0; i < 10; i++) System.out.println(i);

}

}

new Local();

}

}

On the other hand, local variables with the same name may be declared in two separate blocks or for statements, neither of which contains the other:

class Test3 {

public static void main(String[] args) { for (int i = 0; i < 10; i++)

System.out.print(i + " "); for (int i = 10; i > 0; i--)

System.out.print(i + " "); System.out.println();

}

}

This program compiles without error and, when executed, produces the output:

0 1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1

6.4.1 Shadowing

Some declarations may be shadowed in part of their scope by another declaration of the same name, in which case a simple name cannot be used to refer to the declared entity.

135

6.4.1

Shadowing

NAMES

Shadowing is distinct from hiding (§8.3, §8.4.8.2, §8.5, §9.3, §9.5), which applies only to members which would otherwise be inherited but are not because of a declaration in a subclass. Shadowing is also distinct from obscuring (§6.4.2).

A declaration d is said to be visible at point p in a program if the scope of d includes p, and d is not shadowed by any other declaration at p.

When the program point we are discussing is clear from context, we will often simply say that a declaration is visible.

A declaration d of a type named n shadows the declarations of any other types named n that are in scope at the point where d occurs throughout the scope of d.

A declaration d of a field or formal parameter named n shadows, throughout the scope of d, the declarations of any other variables named n that are in scope at the point where d occurs.

A declaration d of a local variable or exception parameter named n shadows, throughout the scope of d, (a) the declarations of any other fields named n that are in scope at the point where d occurs, and (b) the declarations of any other variables named n that are in scope at the point where d occurs but are not declared in the innermost class in which d is declared.

A declaration d of a method named n shadows the declarations of any other methods named n that are in an enclosing scope at the point where d occurs throughout the scope of d.

A package declaration never shadows any other declaration.

A type-import-on-demand declaration never causes any other declaration to be shadowed.

A static-import-on-demand declaration never causes any other declaration to be shadowed.

A single-type-import declaration d in a compilation unit c of package p that imports a type named n shadows, throughout c, the declarations of:

any top level type named n declared in another compilation unit of p

any type named n imported by a type-import-on-demand declaration in c

any type named n imported by a static-import-on-demand declaration in c

A single-static-import declaration d in a compilation unit c of package p that imports a field named n shadows the declaration of any static field named n imported by a static-import-on-demand declaration in c, throughout c.

136

NAMES

Shadowing

6.4.1

A single-static-import declaration d in a compilation unit c of package p that imports a method named n with signature s shadows the declaration of any static method named n with signature s imported by a static-import-on-demand declaration in c, throughout c.

A single-static-import declaration d in a compilation unit c of package p that imports a type named n shadows, throughout c, the declarations of:

any static type named n imported by a static-import-on-demand declaration in c;

any top level type (§7.6) named n declared in another compilation unit (§7.3) of p;

any type named n imported by a type-import-on-demand declaration (§7.5.2) in c.

Example 6.4.1-1. Shadowing of a Field Declaration by a Local Variable Declaration

class Test {

static int x = 1;

public static void main(String[] args) { int x = 0;

System.out.print("x=" + x); System.out.println(", Test.x=" + Test.x);

}

}

This program produces the output:

x=0, Test.x=1

This program declares:

a class Test

a class (static) variable x that is a member of the class Test

a class method main that is a member of the class Test

a parameter args of the main method

a local variable x of the main method

Since the scope of a class variable includes the entire body of the class (§8.2), the class variable x would normally be available throughout the entire body of the method main. In this example, however, the class variable x is shadowed within the body of the method main by the declaration of the local variable x.

A local variable has as its scope the rest of the block in which it is declared (§6.4); in this case this is the rest of the body of the main method, namely its initializer "0" and the invocations of System.out.print and System.out.println.

137

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]