Names and Identifiers

6.2 Names and Identifiers

A name is used to refer to an entity declared in a program. There are two forms of names: simple names and qualified names.

A simple name is a single identifier.

6.2 Names and Identifiers NAMES

A qualified name consists of a name, a " . " token, and an identifier. In determining the meaning of a name (§6.5), the context in which the name appears

is taken into account. The rules of §6.5 distinguish among contexts where a name must denote (refer to) a package (§6.5.3), a type (§6.5.5), a variable or value in an expression (§6.5.6), or a method (§6.5.7).

Packages and reference types have members which may be accessed by qualified names. As background for the discussion of qualified names and the determination of the meaning of names, see the descriptions of membership in §4.4, §4.5.2, §4.8, §4.9, §7.1, §8.2, §9.2, and §10.7.

Not all identifiers in a program are a part of a name. Identifiers are also used in the following situations:

• In declarations (§6.1), where an identifier may occur to specify the name by which the declared entity will be known.

• As labels in labeled statements (§14.7) and in break and continue statements (§14.15, §14.16) that refer to statement labels.

• In field access expressions (§15.11), where an identifier occurs after a " . " token to indicate a member of an object that is the value of an expression or the keyword super that appears before the " . " token

• In some method invocation expressions (§15.12), where an identifier may occur after a " . " token and before a " ( " token to indicate a method to be invoked for an object that is the value of an expression or the keyword super that appears before the " . " token

• In qualified class instance creation expressions (§15.9), where an identifier occurs immediately to the right of the leftmost new token to indicate a type that must be a member of the compile-time type of the primary expression preceding the " . " preceding the leftmost new token.

In this program: class Test {

public static void main(String[] args) {

Class c = System.out.getClass(); System.out.println(c.toString().length() +

args[0].length() + args.length); } }

the identifiers Test , main , and the first occurrences of args and c are not names. Rather, they are used in declarations to specify the names of the declared entities. The names String , Class , System.out.getClass , System.out.println , c.toString ,

NAMES Names and Identifiers 6.2

args , and args.length appear in the example. The occurrence of length in args[0].length() is not a name, but rather an identifier appearing in a method invocation expression (§15.12). The occurrence of length in args.length is a name because args.length is a qualified name (§6.5.6.2) and not a field access expression (§15.11). (A field access expression, like a method invocation expression, uses an identifier rather than a name to denote the member of interest.)

One might wonder why these kinds of expression use an identifier rather than a simple name, which is after all just an identifier. The reason is that a simple expression name is defined in terms of the lexical environment; that is, a simple expression name must be in the scope of a variable declaration. But field access, and method invocation qualified by a Primary, and qualified class instance creation all denote members whose names are not in the lexical environment. By definition, such names are bound only in the context provided by the Primary of the field access expression, method invocation expression, or class instance creation expression. Therefore, we denote such members with identifiers rather than simple names.

To complicate things further, a field access expression is not the only way to denote a field of an object. For parsing reasons, a qualified name is used to denote a field of an in- scope variable. (The variable itself is denoted with a simple name, alluded to above.) It is necessary for access control (§6.6) to capture both mechanisms for denoting a field.

The identifiers used in labeled statements (§14.7) and their associated break and continue statements (§14.15, §14.16) are completely separate from those used in declarations.

Example 6.2-1. Identifiers and Obscuring

The following code was taken from a version of the class String and its method indexOf , where the label was originally called test . Changing the label to have the same name as the local variable i does not obscure (§6.4.2) the label in the scope of the declaration of i . Thus, the code is valid.

class Test { char[] value; int offset, count; int indexOf(TestString str, int fromIndex) {

char[] v1 = value, v2 = str.value; int max = offset + (count - str.count); int start = offset + ((fromIndex < 0) ? 0 : fromIndex);

i: for (int i = start; i <= max; i++) { int n = str.count, j = i, k = str.offset; while (n-- != 0) {

if (v1[j++] != v2[k++]) continue i;

} return i - offset;

} return -1;

6.3 Scope of a Declaration NAMES

} The identifier max could also have been used as the statement label; the label would not

obscure the local variable max within the labeled statement.