|
CHAPTER 6: Names |
|
 Previous |
 Java Language |
 Index |
 Next |
6.5 Determining the Meaning of a Name
6.5.1 Syntactic Classification of a Name According to Context
, 6.5.2 Reclassification of Contextually Ambiguous Names
, 6.5.3 Meaning of Package Names
, 6.5.4 Meaning of Type Names
, 6.5.5 Meaning of Expression Names
, 6.5.6 Meaning of Method Names
The meaning of a name in Java depends on the context in which it is used. The determination of the meaning of a name requires three steps. First, context causes a name syntactically to fall into one of five categories: PackageName, TypeName, ExpressionName, MethodName, or AmbiguousName. Second, a name that is initially classified by its context as an AmbiguousName is then reclassified by certain scoping rules to be a PackageName, TypeName, or ExpressionName. Third, the resulting category then dictates the final determination of the meaning of the name (or a compilation error if the name has no meaning).
PackageName:
Identifier
PackageName . Identifier
TypeName:
Identifier
PackageName . Identifier
ExpressionName:
Identifier
AmbiguousName . Identifier
MethodName:
Identifier
AmbiguousName . Identifier
AmbiguousName:
Identifier
AmbiguousName . Identifier
Java's use of context helps to minimize name conflicts between entities of different kinds. Such conflicts will be rare if the naming conventions described in S6.8 are followed. Nevertheless, conflicts may arise unintentionally as types developed by different programmers or different organizations evolve. For example, types, methods, and fields may have the same name. Java never has trouble distinguishing between a method and a field with the same name, since the context of a use always tells whether a method or a field is intended.
A name is syntactically classified as a PackageName in these contexts:
- In a package declaration (S7.4)
- In a type-import-on-demand declaration (S7.5.2)
- To the left of the ".
" in a qualified PackageName
- To the left of the ".
" in a qualified TypeName
A name is syntactically classified as a TypeName in these contexts:
- In a single-type-import declaration (S7.5.1)
- In an extends
clause in a class declaration (S8.1.3)
- In an implements
clause in a class declaration (S8.1.4)
- In an extends
clause in an interface declaration (S9.1.3)
- As a Type (or the part of a Type that remains after all brackets are deleted) in any of the following contexts:
- In a field declaration (S8.3, S9.3)
- As the result type of a method (S8.4, S9.4)
- As the type of a formal parameter of a method or constructor (S8.4.1, S8.6.1, S9.4)
- As the type of an exception that can be thrown by a method or constructor (S8.4.4, S8.6.4, S9.4)
- As the type of a local variable (S14.3)
- As the type of an exception parameter in a catch
clause of a try
statement (S14.18)
- As the class type of an instance that is to be created in a class instance creation expression (S15.8)
- As the element type of an array to be created in an array creation expression (S15.9)
- As the type mentioned in the cast operator of a cast expression (S15.15)
- As the type that follows the instanceof
relational operator (S15.19.2)
A name is syntactically classified as an ExpressionName in these contexts:
- As the array reference expression in an array access expression (S15.12)
- As a PostfixExpression (S15.13)
- As the left-hand operand of an assignment operator (S15.25)
A name is syntactically classified as a MethodName in this context:
· Before the "(
" in a method invocation expression (S15.11)
A name is syntactically classified as an AmbiguousName in these contexts:
- To the left of the ".
" in a qualified ExpressionName
- To the left of the ".
" in a qualified MethodName
- To the left of the ".
" in a qualified AmbiguousName
An AmbiguousName is then reclassified as follows:
- If the AmbiguousName is a simple name, consisting of a single Identifier:
- If the Identifier appears within the scope (S6.3) of a local variable declaration (S14.3) or parameter declaration (S8.4.1, S8.6.1, S14.18) with that name, then the AmbiguousName is reclassified as an ExpressionName.
- Otherwise, consider the class or interface C within whose declaration the Identifier occurs. If C has one or more fields with that name, which may be either declared within it or inherited, then the AmbiguousName is reclassified as an ExpressionName.
- Otherwise, if a type of that name is declared in the compilation unit (S7.3) containing the Identifier, either by a single-type-import declaration (S7.5.1) or by a class or interface type declaration (S7.6), then the AmbiguousName is reclassified as a TypeName.
- Otherwise, if a type of that name is declared in another compilation unit (S7.3) of the package (S7.1) of the compilation unit containing the Identifier, then the AmbiguousName is reclassified as a TypeName.
- Otherwise, if a type of that name is declared by exactly one type-import-on-demand declaration (S7.5.2) of the compilation unit containing the Identifier, then the AmbiguousName is reclassified as a TypeName.
- Otherwise, if a type of that name is declared by more than one type-import-on-demand declaration of the compilation unit containing the Identifier, then a compile-time error results.
- Otherwise, the AmbiguousName is reclassified as a PackageName. A later step determines whether or not a package of that name actually exists.
- If the AmbiguousName is a qualified name, consisting of a name, a ".
", and an Identifier, then the name to the left of the ".
" is first reclassified, for it is itself an AmbiguousName. There is then a choice:
- If the name to the left of the ".
" is reclassified as a PackageName, then there is a further choice:
- If there is a package whose name is the name to the left of the ".
" and that package contains a declaration of a type whose name is the same as the Identifier, then this AmbiguousName is reclassified as a TypeName.
- Otherwise, this AmbiguousName is reclassified as a PackageName. A later step determines whether or not a package of that name actually exists.
- If the name to the left of the ".
" is reclassified as a TypeName, then this AmbiguousName is reclassified as an ExpressionName. u If the name to the left of the ".
" is reclassified as an ExpressionName, then this AmbiguousName is reclassified as an ExpressionName.
As an example, consider the following contrived "library code":
package ORG.rpgpoet;
import java.util.Random;
interface Music { Random[] wizards = new Random[4]; }
and then consider this example code in another package:
package bazola;
class Gabriel {
static int n = ORG.rpgpoet.Music.wizards.length;
}
First of all, the name ORG.rpgpoet.Music.wizards.length
is classified as an ExpressionName because it functions as a PostfixExpression. Therefore, each of the names:
ORG.rpgpoet.Music.wizards
ORG.rpgpoet.Music
ORG.rpgpoet
ORG
is initially classified as an AmbiguousName. These are then reclassified:
- Assuming that there is no class or interface named ORG
in any other compilation unit of package bazola
, then the simple name ORG
is reclassified as a PackageName.
- Next, assuming that there is no class or interface named rpgpoet
in any compilation unit of package ORG
(and we know that there is no such class or interface because package ORG
has a subpackage named rpgpoet
), the qualified name ORG.rpgpoet
is reclassified as a PackageName.
- Next, because package ORG.rpgpoet
has an interface type named Music
, the qualified name ORG.rpgpoet.Music
is reclassified as a TypeName.
- Finally, because the name ORG.rpgpoet.Music
is a TypeName, the qualified name ORG.rpgpoet.Music.wizards
is reclassified as an ExpressionName.
The meaning of a name classified as a PackageName is determined as follows.
If a package name consists of a single Identifier, then this identifier denotes a top- level package named by that identifier. If no package of that name is accessible, as determined by the host system (S7.4.3), then a compile-time error occurs.
If a package name is of the form Q.
Id, then Q must also be a package name. The package name Q.
Id names a package that is the member named Id within the package named by Q. If Q does not name an accessible package or Id does not name an accessible subpackage of that package, then a compile-time error occurs.
The meaning of a name classified as a TypeName is determined as follows.
If a type name consists of a single Identifier, then the identifier must occur in the scope of a declaration of a type with this name, or a compile-time error occurs. It is possible that the identifier occurs within the scope of more than one type with that name, in which case the type denoted by the name is determined as follows:
- If a type with that name is declared in the current compilation unit (S7.3), either by a single-type-import declaration (S7.5.1) or by a declaration of a class or interface type (S7.6), then the simple type name denotes that type.
- Otherwise, if a type with that name is declared in another compilation unit (S7.3) of the package (S7.1) containing the identifier, then the identifier denotes that type. Note that, in systems that store compilation units in a file system, such a compilation unit must have a file name that is the name of the type (S7.6).
- Otherwise, if a type of that name is declared by exactly one type-import-on-demand declaration (S7.5.2) of the compilation unit containing the identifier, then the simple type name denotes that type.
- Otherwise, if a type of that name is declared by more than one type-import-on-demand declaration of the compilation unit, then the name is ambiguous as a type name; a compile-time error occurs.
- Otherwise, the name is undefined as a type name; a compile-time error occurs.
This order for considering type declarations is designed to choose the most explicit of two or more applicable type declarations.
If a type name is of the form Q.
Id, then Q must be a package name. The type name Q.
Id names a type that is the member named Id within the package named by Q. If Q does not name an accessible package, or Id does not name a type within that package, or the type named Id within that package is not accessible (S6.6), then a compile-time error occurs.
The example:
package wnj.test;
class Test {
public static void main(String[] args) {
java.util.Date date =
new java.util.Date(System.currentTimeMillis());
System.out.println(date.toLocaleString());
}
}
produced the following output the first time it was run:
Sun Jan 21 22:56:29 1996
In this example:
- The name wnj.test
must name a package on the host system. It is resolved by first looking for the package wnj
, using the procedure described in S6.5.3.1, and then making sure that the subpackage test
of this package is accessible.
- The name java.util.Date
(S21.3) must denote a type, so we first use the procedure recursively to determine if java.util
is an accessible package, which it is, and then look to see if the type Date
is accessible in this package.
The meaning of a name classified as an ExpressionName is determined as follows.
If an expression name consists of a single Identifier, then:
- If the Identifier appears within the scope (S6.3) of a local variable declaration (S14.3) or parameter declaration (S8.4.1, S8.6.1, S14.18) with that name, then the expression name denotes a variable, that is, that local variable or parameter. Local variables and parameters are never hidden (S6.3, S6.3.1, S14.3), so there is necessarily at most one such local variable or parameter. The type of the expression name is the declared type of the local variable or parameter.
- Otherwise, if the Identifier appears within a class declaration (Chapter 8):
- If there is not exactly one member of that class (S8.2) that is a field with that name, then a compile-time error results.
- Otherwise, if the single member field with that name is declared final
(S8.3.1.2), then the expression name denotes the value of the field. The type of the expression name is the declared type of the field. If the Identifier appears in a context that requires a variable and not a value, then a compile-time error occurs.
- Otherwise, the expression name denotes a variable, the single member field with that name. The type of the expression name is the field's declared type.
If the field is an instance variable (S8.3.1.1), the expression name must appear within the declaration of an instance method (S8.4), constructor (S8.6), or instance variable initializer (S8.3.2.2). If it appears within a static
method (S8.4.3.2), static initializer (S8.5), or initializer for a static
variable (S8.3.1.1, S12.4.2), then a compile-time error occurs.
- Otherwise, the identifier appears within an interface declaration (Chapter 9):
- If there is not exactly one member of that interface (S9.2) that is a field with that name, then a compile-time error results.
- Otherwise, the expression name denotes the value of the single member field of that name. The type of the expression name is the declared type of the field. If the Identifier appears in a context that requires a variable and not a value, then a compile-time error occurs.
In the example:
class Test {
static int v;
static final int f = 3;
public static void main(String[] args) {
int i;
i = 1;
v = 2;
f = 33; // compile-time error
System.out.println(i + " " + v + " " + f);
}
}
the names used as the left-hand-sides in the assignments to i
, v
, and f
denote the local variable i
, the field v
, and the value of f
(not the variable f
, because f
is a final
variable). The example therefore produces an error at compile time because the last assignment does not have a variable as its left-hand side. If the erroneous assignment is removed, the modified code can be compiled and it will produce the output:
1 2 3
If an expression name is of the form Q.
Id, then Q has already been classified as a package name, a type name, or an expression name:
- If Q is a package name, then a compile-time error occurs.
- If Q is a type name that names a class type (Chapter 8), then:
- If there is not exactly one accessible (S6.6) member of the class type that is a field named Id, then a compile-time error occurs.
- Otherwise, if the single accessible member field is not a class variable (that is, it is not declared static
), then a compile-time error occurs.
- Otherwise, if the class variable is declared final
, then Q.
Id denotes the value of the class variable. The type of the expression Q.
Id is the declared type of the class variable. If Q.
Id appears in a context that requires a variable and not a value, then a compile-time error occurs.
- Otherwise, Q.
Id denotes the class variable. The type of the expression Q.
Id is the declared type of the class variable.
- If Q is a type name that names an interface type (Chapter 9), then:
- If there is not exactly one accessible (S6.6) member of the interface type that is a field named Id, then a compile-time error occurs.
- Otherwise, Q.
Id denotes the value of the field. The type of the expression Q.
Id is the declared type of the field. If Q.
Id appears in a context that requires a variable and not a value, then a compile-time error occurs.
- If Q is an expression name, let T be the type of the expression Q:
- If T is not a reference type, a compile-time error occurs.
- If there is not exactly one accessible (S6.6) member of the type T that is a field named Id, then a compile-time error occurs.
- Otherwise, if this field is any of the following:
- A field of an interface type
- A final
field of a class type (which may be either a class variable or an instance variable)
- The final
field length
of an array type then Q.
Id denotes the value of the field. The type of the expression Q.
Id is the declared type of the field. If Q.
Id appears in a context that requires a variable and not a value, then a compile-time error occurs.
- Otherwise, Q.
Id denotes a variable, the field Id of class T, which may be either a class variable or an instance variable. The type of the expression Q.
Id is the declared type of the field
The example:
class Point {
int x, y;
static int nPoints;
}
class Test {
public static void main(String[] args) {
int i = 0;
i.x++; // compile-time error
Point p = new Point();
p.nPoints(); // compile-time error
}
}
encounters two compile-time errors, because the int
variable i
has no members, and because nPoints
is not a method of class Point
.
A MethodName can appear only in a method invocation expression (S15.11). The meaning of a name classified as a MethodName is determined as follows.
If a method name consists of a single Identifier, then Identifier is the method name to be used for method invocation. The Identifier must name at least one method of the class or interface within whose declaration the Identifier appears. See S15.11 for further discussion of the interpretation of simple method names in method invocation expressions.
If a method name is of the form Q.
Id, then Q has already been classified as a package name, a type name, or an expression name. If Q is a package name, then a compile-time error occurs. Otherwise, Id is the method name to be used for method invocation. If Q is a type name, then Id must name at least one static
method of the type Q. If Q is an expression name, then let T be the type of the expression Q; Id must name at least one method of the type T. See S15.11 for further discussion of the interpretation of qualified method names in method invocation expressions.
 | © 1996 Sun Microsystems, Inc. All rights reserved. |