Movatterモバイル変換


[0]ホーム

URL:


Oracle Logo

Java SE >Java SE Specifications >Java Language Specification

Chapter 6. Names
Prev   Next

Chapter 6. Names

Table of Contents

6.1. Declarations
6.2. Names and Identifiers
6.3. Scope of a Declaration
6.4. Shadowing and Obscuring
6.4.1. Shadowing
6.4.2. Obscuring
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.3.1. Simple Package Names
6.5.3.2. Qualified Package Names
6.5.4. Meaning ofPackageOrTypeNames
6.5.4.1. SimplePackageOrTypeNames
6.5.4.2. QualifiedPackageOrTypeNames
6.5.5. Meaning of Type Names
6.5.5.1. Simple Type Names
6.5.5.2. Qualified Type Names
6.5.6. Meaning of Expression Names
6.5.6.1. Simple Expression Names
6.5.6.2. Qualified Expression Names
6.5.7. Meaning of Method Names
6.5.7.1. Simple Method Names
6.6. Access Control
6.6.1. Determining Accessibility
6.6.2. Details onprotected Access
6.6.2.1. Access to aprotected Member
6.6.2.2. Qualified Access to aprotected Constructor
6.7. Fully Qualified Names and Canonical Names

Names are used to refer to entities declared in a program.

A declared entity (§6.1) is a package, class type (normal or enum), interface type (normal or annotation type), member (class, interface, field, or method) of a reference type, type parameter (of a class, interface, method or constructor), parameter (to a method, constructor, or exception handler), or local variable.

Names in programs are eithersimple, consisting of a single identifier, orqualified, consisting of a sequence of identifiers separated by "." tokens (§6.2).

Every declaration that introduces a name has ascope (§6.3), which is the part of the program text within which the declared entity can be referred to by a simple name.

A qualified nameN.x may be used to refer to amember of a package or reference type, whereN is a simple or qualified name andx is an identifier. IfN names a package, thenx is a member of that package, which is either a class or interface type or a subpackage. IfN names a reference type or a variable of a reference type, thenx names a member of that type, which is either a class, an interface, a field, or a method.

In determining the meaning of a name (§6.5), the context of the occurrence is used to disambiguate among packages, types, variables, and methods with the same name.

Access control (§6.6) can be specified in a class, interface, method, or field declaration to control whenaccess to a member is allowed. Access is a different concept from scope. Access specifies the part of the program text within which the declared entity can be referred to by a qualified name. Access to a declared entity is also relevant in a field access expression (§15.11), a method invocation expression in which the method is not specified by a simple name (§15.12), a method reference expression (§15.13), or a qualified class instance creation expression (§15.9). In the absence of an access modifier, most declarations have package access, allowing access anywhere within the package that contains its declaration; other possibilities arepublic,protected, andprivate.

Fully qualified and canonical names (§6.7) are also discussed in this chapter.

6.1. Declarations

Adeclaration introduces an entity into a program and includes an identifier (§3.8) that can be used in a name to refer to this entity.

A declared entity is one of the following:

  • A package, declared in apackage declaration (§7.4)

  • An imported type, declared in a single-type-import declaration or a type-import-on-demand declaration (§7.5.1,§7.5.2)

  • An importedstatic member, declared in a single-static-import declaration or a static-import-on-demand declaration (§7.5.3,§7.5.4)

  • A class, declared in a class type declaration (§8.1)

  • An interface, declared in an interface type declaration (§9.1)

  • A type parameter, declared as part of the declaration of a generic class, interface, method, or constructor (§8.1.2,§9.1.2,§8.4.4,§8.8.4)

  • A member of a reference type (§8.2,§9.2,§8.9.3,§9.6,§10.7), one of the following:

    • A member class (§8.5,§9.5)

    • A member interface (§8.5,§9.5)

    • An enum constant (§8.9)

    • A field, one of the following:

      • A field declared in a class type or enum type (§8.3,§8.9.2)

      • A field declared in an interface type or annotation type (§9.3,§9.6.1)

      • The fieldlength, which is implicitly a member of every array type (§10.7)

    • A method, one of the following:

      • A method (abstract or otherwise) declared in a class type or enum type (§8.4,§8.9.2)

      • A method (alwaysabstract) declared in an interface type or annotation type (§9.4,§9.6.1)

  • A parameter, one of the following:

    • A formal parameter of a method or constructor of a class type or enum type (§8.4.1,§8.8.1,§8.9.2), or of a lambda expression (§15.27.1)

    • A formal parameter of anabstract method of an interface type or annotation type (§9.4,§9.6.1)

    • An exception parameter of an exception handler declared in acatch clause of atry statement (§14.20)

  • A local variable, one of the following:

    • A local variable declared in a block (§14.4)

    • A local variable declared in afor statement (§14.14)

Constructors (§8.8) are also introduced by declarations, but use the name of the class in which they are declared rather than introducing a new name.

The declaration of a type which is not generic (class C ...) declares one entity: a non-generic type (C). A non-generic type is not a raw type, despite the syntactic similarity. In contrast, the declaration of a generic type (class C<T> ... orinterface C<T> ...) declares two entities: a generic type (C<T>) and a corresponding non-generic type (C). In this case, the meaning of the termC depends on the context where it appears:

  • If genericity is unimportant, as in thenon-generic contexts identified below, the identifierC denotes the non-generic typeC.

  • If genericity is important, as in all contexts from§6.5 except the non-generic contexts, the identifierC denotes either:

    • The raw typeC which is the erasure (§4.6) of the generic typeC<T>; or

    • A parameterized type which is a particular parameterization (§4.5) of the generic typeC<T>.

The 13 non-generic contexts are as follows:

  1. In a single-type-import declaration (§7.5.1)

  2. To the left of the. in a single-static-import declaration (§7.5.3)

  3. To the left of the. in a static-import-on-demand declaration (§7.5.4)

  4. To the left of the( in a constructor declaration (§8.8)

  5. After the@ sign in an annotation (§9.7)

  6. To the left of.class in a class literal (§15.8.2)

  7. To the left of.this in a qualifiedthis expression (§15.8.4)

  8. To the left of.super in a qualified superclass field access expression (§15.11.2)

  9. To the left of.Identifier or.super.Identifier in a qualified method invocation expression (§15.12)

  10. To the left of.super:: in a method reference expression (§15.13)

  11. In a qualified expression name in a postfix expression (§15.14.1)

  12. In athrows clause of a method or constructor (§8.4.6,§8.8.5,§9.4)

  13. In an exception parameter declaration (§14.20)

The first ten non-generic contexts correspond to the first ten syntactic contexts for aTypeName in§6.5.1. The eleventh non-generic context is a postfix expression, where a qualifiedExpressionName such asC.x may include aTypeNameC to denote static member access. The common use ofTypeName is significant: it indicates that these contexts involve a less-than-first-class use of a type. In contrast, the twelfth and thirteenth non-generic contexts employClassType, indicating thatthrows andcatch clauses use types in a first-class way, in line with, say, field declarations. The characterization of these two contexts as non-generic is due to the fact that an exception type cannot be parameterized.

Note that theClassType production allows annotations, so it is possible to annotate the use of a type in athrows orcatch clause, whereas theTypeName production disallows annotations, so it is not possible to annotate the name of a type in, say, a single-type-import declaration.

Naming Conventions

The class libraries of the Java SE platform attempt to use, whenever possible, names chosen according to the conventions presented below. These conventions help to make code more readable and avoid certain kinds of name conflicts.

We recommend these conventions for use in all programs written in the Java programming language. However, these conventions should not be followed slavishly if long-held conventional usage dictates otherwise. So, for example, thesin andcos methods of the classjava.lang.Math have mathematically conventional names, even though these method names flout the convention suggested here because they are short and are not verbs.

Package Names

Developers should take steps to avoid the possibility of two published packages having the same name by choosingunique package names for packages that are widely distributed. This allows packages to be easily and automatically installed and catalogued. This section specifies a suggested convention for generating such unique package names. Implementations of the Java SE platform are encouraged to provide automatic support for converting a set of packages from local and casual package names to the unique name format described here.

If unique package names are not used, then package name conflicts may arise far from the point of creation of either of the conflicting packages. This may create a situation that is difficult or impossible for the user or programmer to resolve. The classClassLoader can be used to isolate packages with the same name from each other in those cases where the packages will have constrained interactions, but not in a way that is transparent to a naïve program.

You form a unique package name by first having (or belonging to an organization that has) an Internet domain name, such asoracle.com. You then reverse this name, component by component, to obtain, in this example,com.oracle, and use this as a prefix for your package names, using a convention developed within your organization to further administer package names. Such a convention might specify that certain package name components be division, department, project, machine, or login names.

Example 6.1-1. Unique Package Names

com.nighthacks.java.jag.scrabbleorg.openjdk.tools.compilernet.jcip.annotationsedu.cmu.cs.bovik.cheesegov.whitehouse.socks.mousefinder

The first component of a unique package name is always written in all-lowercase ASCII letters and should be one of the top level domain names, such ascom,edu,gov,mil,net, ororg, or one of the English two-letter codes identifying countries as specified inISO Standard 3166.

The name of a package is not meant to imply where the package is stored on the Internet. The suggested convention for generating unique package names is merely a way to piggyback a package naming convention on top of an existing, widely known unique name registry instead of having to create a separate registry for package names.

For example, a package namededu.cmu.cs.bovik.cheese is not necessarily obtainable from Internet addresscmu.edu orcs.cmu.edu orbovik.cs.cmu.edu.

In some cases, the Internet domain name may not be a valid package name. Here are some suggested conventions for dealing with these situations:

  • If the domain name contains a hyphen, or any other special character not allowed in an identifier (§3.8), convert it into an underscore.

  • If any of the resulting package name components are keywords (§3.9), append an underscore to them.

  • If any of the resulting package name components start with a digit, or any other character that is not allowed as an initial character of an identifier, have an underscore prefixed to the component.

Names of packages intended only for local use should have a first identifier that begins with a lowercase letter, but that first identifier specifically should not be the identifierjava; package names that start with the identifierjava are reserved for packages of the Java SE platform.

Class and Interface Type Names

Names of class types should be descriptive nouns or noun phrases, not overly long, in mixed case with the first letter of each word capitalized.

Example 6.1-2. Descriptive Class Names

ClassLoaderSecurityManagerThreadDictionaryBufferedInputStream

Likewise, names of interface types should be short and descriptive, not overly long, in mixed case with the first letter of each word capitalized. The name may be a descriptive noun or noun phrase, which is appropriate when an interface is used as if it were an abstract superclass, such as interfacesjava.io.DataInput andjava.io.DataOutput; or it may be an adjective describing a behavior, as for the interfacesRunnable andCloneable.

Type Variable Names

Type variable names should be pithy (single character if possible) yet evocative, and should not include lower case letters. This makes it easy to distinguish type parameters from ordinary classes and interfaces.

Container types should use the nameE for their element type. Maps should useK for the type of their keys andV for the type of their values. The nameX should be used for arbitrary exception types. We useT for type, whenever there is not anything more specific about the type to distinguish it. (This is often the case in generic methods.)

If there are multiple type parameters that denote arbitrary types, one should use letters that neighborT in the alphabet, such asS. Alternately, it is acceptable to use numeric subscripts (e.g.,T1,T2) to distinguish among the different type variables. In such cases, all the variables with the same prefix should be subscripted.

If a generic method appears inside a generic class, it is a good idea to avoid using the same names for the type parameters of the method and class, to avoid confusion. The same applies to nested generic classes.

Example 6.1-3. Conventional Type Variable Names

public class HashSet<E> extends AbstractSet<E> { ... }public class HashMap<K,V> extends AbstractMap<K,V> { ... }public class ThreadLocal<T> { ... }public interface Functor<T, X extends Throwable> {    T eval() throws X;}

When type parameters do not fall conveniently into one of the categories mentioned, names should be chosen to be as meaningful as possible within the confines of a single letter. The names mentioned above (E,K,V,X,T) should not be used for type parameters that do not fall into the designated categories.

Method Names

Method names should be verbs or verb phrases, in mixed case, with the first letter lowercase and the first letter of any subsequent words capitalized. Here are some additional specific conventions for method names:

  • Methods to get and set an attribute that might be thought of as a variableV should be namedgetV andsetV. An example is the methodsgetPriority andsetPriority of classThread.

  • A method that returns the length of something should be namedlength, as in classString.

  • A method that tests a boolean conditionV about an object should be namedisV. An example is the methodisInterrupted of classThread.

  • A method that converts its object to a particular formatF should be namedtoF. Examples are the methodtoString of classObject and the methodstoLocaleString andtoGMTString of classjava.util.Date.

Whenever possible and appropriate, basing the names of methods in a new class on names in an existing class that is similar, especially a class from the Java SE platform API, will make it easier to use.

Field Names

Names of fields that are notfinal should be in mixed case with a lowercase first letter and the first letters of subsequent words capitalized. Note that well-designed classes have very fewpublic orprotected fields, except for fields that are constants (staticfinal fields).

Fields should have names that are nouns, noun phrases, or abbreviations for nouns.

Examples of this convention are the fieldsbuf,pos, andcount of the classjava.io.ByteArrayInputStream and the fieldbytesTransferred of the classjava.io.InterruptedIOException.

Constant Names

The names of constants in interface types should be, andfinal variables of class types may conventionally be, a sequence of one or more words, acronyms, or abbreviations, all uppercase, with components separated by underscore "_" characters. Constant names should be descriptive and not unnecessarily abbreviated. Conventionally they may be any appropriate part of speech.

Examples of names for constants includeMIN_VALUE,MAX_VALUE,MIN_RADIX, andMAX_RADIX of the classCharacter.

A group of constants that represent alternative values of a set, or, less frequently, masking bits in an integer value, are sometimes usefully specified with a common acronym as a name prefix.

For example:

interface ProcessStates {    int PS_RUNNING   = 0;    int PS_SUSPENDED = 1;}

Local Variable and Parameter Names

Local variable and parameter names should be short, yet meaningful. They are often short sequences of lowercase letters that are not words, such as:

  • Acronyms, that is the first letter of a series of words, as incp for a variable holding a reference to aColoredPoint

  • Abbreviations, as inbuf holding a pointer to a buffer of some kind

  • Mnemonic terms, organized in some way to aid memory and understanding, typically by using a set of local variables with conventional names patterned after the names of parameters to widely used classes. For example:

    • in andout, whenever some kind of input and output are involved, patterned after the fields ofSystem

    • off andlen, whenever an offset and length are involved, patterned after the parameters to theread andwrite methods of the interfacesDataInput andDataOutput ofjava.io

One-character local variable or parameter names should be avoided, except for temporary and looping variables, or where a variable holds an undistinguished value of a type. Conventional one-character names are:

  • b for abyte

  • c for achar

  • d for adouble

  • e for anException

  • f for afloat

  • i,j, andk forints

  • l for along

  • o for anObject

  • s for aString

  • v for an arbitrary value of some type

Local variable or parameter names that consist of only two or three lowercase letters should not conflict with the initial country codes and domain names that are the first component of unique package names.

6.2. Names and Identifiers

Aname is used to refer to an entity declared in a program.

There are two forms of names: simple names and qualified names.

Asimple name is a single identifier.

Aqualified 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 havemembers 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 inbreak andcontinue statements (§14.15,§14.16) that refer to statement labels.

    The identifiers used in labeled statements and their associatedbreak andcontinue statements are completely separate from those used in declarations.

  • In field access expressions (§15.11), where an identifier occurs after a "." token to indicate a member of the object denoted by the expression before the "." token, or the object denoted by thesuper orTypeName.super before the "." token.

  • In some method invocation expressions (§15.12), wherever an identifier occurs after a "." token and before a "(" token to indicate a method to be invoked for the object denoted by the expression before the "." token, or the type denoted by theTypeName before the "." token, or the object denoted by thesuper orTypeName.super before the "." token.

  • In some method reference expressions (§15.13), wherever an identifier occurs after a "::" token to indicate a method of the object denoted by the expression before the "::" token, or the type denoted by theTypeName before the "::" token, or the object denoted by thesuper orTypeName.super before the "::" token.

  • In qualified class instance creation expressions (§15.9), where an identifier occurs to the right of thenew token to indicate a type that is a member of the compile-time type of the expression preceding thenew token.

  • In element-value pairs of annotations (§9.7.1), to denote an element of the corresponding annotation type.

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 identifiersTest,main, and the first occurrences ofargs andc are not names. Rather, they are identifiers used in declarations to specify the names of the declared entities. The namesString,Class,System.out.getClass,System.out.println,c.toString,args, andargs.length appear in the example.

The occurrence oflength inargs.length is a name becauseargs.length is a qualified name (§6.5.6.2) and not a field access expression (§15.11). A field access expression, as well as a method invocation expression, a method reference expression, and a qualified class instance creation expression, uses an identifier rather than a name to denote the member of interest. Thus, the occurrence oflength inargs[0].length() isnot a name, but rather an identifier appearing in a method invocation expression.

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 (§6.5.6.1). On the other hand, field access, qualified method invocation, method references, and qualified class instance creation all refer to members whose names are not in the lexical environment. By definition, such names are bound only in the context provided by thePrimary of the field access expression, method invocation expression, method reference expression, or class instance creation expression; or by thesuper of the field access expression, method invocation expression, or method reference expression; and so on. Thus, 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 apply to both denotations of a field.

6.3. Scope of a Declaration

Thescope of a declaration is the region of the program within which the entity declared by the declaration can be referred to using a simple name, provided it is visible (§6.4.1).

A declaration is said to bein scope at a particular point in a program if and only if the declaration's scope includes that point.

The scope of the declaration of an observable (§7.4.3) top level package is all observable compilation units (§7.3).

The declaration of a package that is not observable is never in scope.

The declaration of a subpackage is never in scope.

The packagejava is always in scope.

The scope of a type imported by a single-type-import declaration (§7.5.1) or a type-import-on-demand declaration (§7.5.2) is all the class and interface type declarations (§7.6) in the compilation unit in which theimport declaration appears, as well as any annotations on the package declaration (if any) of the compilation unit .

The scope of a member imported by a single-static-import declaration (§7.5.3) or a static-import-on-demand declaration (§7.5.4) is all the class and interface type declarations (§7.6) in the compilation unit in which theimport declaration appears, as well as any annotations on the package declaration (if any) of the compilation unit .

The scope of a top level type (§7.6) is all type declarations in the package in which the top level type is declared.

The scope of a declaration of a memberm declared in or inherited by a class typeC (§8.1.6) is the entire body ofC, including any nested type declarations.

The scope of a declaration of a memberm declared in or inherited by an interface typeI (§9.1.4) is the entire body ofI, including any nested type declarations.

The scope of an enum constantC declared in an enum typeT is the body ofT, and anycase label of aswitch statement whose expression is of enum typeT (§14.11).

The scope of a formal parameter of a method (§8.4.1), constructor (§8.8.1), or lambda expression (§15.27) is the entire body of the method, constructor, or lambda expression.

The scope of a class's type parameter (§8.1.2) is the type parameter section of the class declaration, the type parameter section of any superclass or superinterface of the class declaration, and the class body.

The scope of an interface's type parameter (§9.1.2) is the type parameter section of the interface declaration, the type parameter section of any superinterface of the interface declaration, and the interface body.

The scope of a method's type parameter (§8.4.4) is the entire declaration of the method, including the type parameter section, but excluding the method modifiers.

The scope of a constructor's type parameter (§8.8.4) is the entire declaration of the constructor, including the type parameter section, but excluding the constructor modifiers.

The scope of a local class declaration immediately enclosed by a block (§14.2) is the rest of the immediately enclosing block, including its own class declaration.

The scope of a local class declaration immediately enclosed by a switch block statement group (§14.11) is the rest of the immediately enclosing switch block statement group, including its own class declaration.

The scope of a local variable declaration in a block (§14.4) is the rest of the block in which the declaration appears, starting with its own initializer and including any further declarators to the right in the local variable declaration statement.

The scope of a local variable declared in theForInit part of a basicfor statement (§14.14.1) includes all of the following:

  • Its own initializer

  • Any further declarators to the right in theForInit part of thefor statement

  • TheExpression andForUpdate parts of thefor statement

  • The containedStatement

The scope of a local variable declared in theFormalParameter part of an enhancedfor statement (§14.14.2) is the containedStatement.

The scope of a parameter of an exception handler that is declared in acatch clause of atry statement (§14.20) is the entire block associated with thecatch.

The scope of a variable declared in theResourceSpecification of atry-with-resources statement (§14.20.3) is from the declaration rightward over the remainder of theResourceSpecification and the entiretry block associated with thetry-with-resources statement.

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

Example 6.3-1. Scope of Type Declarations

These rules imply that declarations of class and interface types need not appear before uses of the types. In the following program, the use ofPointList in classPoint is valid, because the scope of the class declarationPointList includes both classPoint and classPointList, as well as any other type declarations in other compilation units of packagepoints.

package points;class Point {    int x, y;    PointList list;    Point next;}class PointList {    Point first;}

Example 6.3-2. Scope of Local Variable Declarations

The following program causes a compile-time error because the initialization of local variablex is within the scope of the declaration of local variablex, but the local variablex does not yet have a value and cannot be used. The fieldx has a value of0 (assigned whenTest1 was initialized) but is a red herring since it is shadowed (§6.4.1) by the local variablex.

class Test1 {    static int x;    public static void main(String[] args) {        int x = x;    }}

The following program does compile:

class Test2 {    static int x;    public static void main(String[] args) {        int x = (x=2)*2;        System.out.println(x);    }}

because the local variablex is definitely assigned (§16 (Definite Assignment)) before it is used. It prints:

4

In the following program, the initializer forthree can correctly refer to the variabletwo declared in an earlier declarator, and the method invocation in the next line can correctly refer to the variablethree 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,§15.27.1), exception parameter (§14.20), and local class (§14.3) can only be referred to using a simple name, not a qualified name (§6.2).

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 used to declare a new variable within the body of the method, constructor, or lambda expression, unless the new variable is declared within a class declaration contained by the method, constructor, or lambda expression.

It is a compile-time error if the name of a local variablev is used to declare a new variable within the scope ofv, unless the new variable is declared within a class whose declaration is within the scope ofv.

It is a compile-time error if the name of an exception parameter is used to declare a new variable within theBlock of thecatch clause, unless the new variable is declared within a class declaration contained by theBlock of thecatch clause.

It is a compile-time error if the name of a local classC is used to declare a new local class within the scope ofC, unless the new local class is declared within another class whose declaration is within the scope ofC.

These rules allow redeclaration of a variable or local class in nested class declarations (local classes (§14.3) and anonymous classes (§15.9)) that occur in the scope of the variable or local class. Thus, the declaration of a formal parameter, local variable, or local class may be shadowed in a class declaration nested within a method, constructor, or lambda expression; and the declaration of an exception parameter may be shadowed inside a class declaration nested within theBlock of thecatch clause.

There are two design alternatives for handling name clashes created by lambda parameters and other variables declared in lambda expressions. One is to mimic class declarations: like local classes, lambda expressions introduce a new "level" for names, and all variable names outside the expression can be redeclared. Another is a "local" strategy: likecatch clauses,for loops, and blocks, lambda expressions operate at the same "level" as the enclosing context, and local variables outside the expression cannot be shadowed. The above rules use the local strategy; there is no special dispensation that allows a variable declared in a lambda expression to shadow a variable declared in an enclosing method.

Note that the rule for local classes does not make an exception for a class of the same name declared within the local class itself. However, this case is prohibited by a separate rule: a class cannot have the same name as a class that encloses it (§8.1).

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);    }}

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 orfor 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 beshadowed 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.

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 declarationd is said to bevisible at pointp in a program if the scope ofd includesp, andd is not shadowed by any other declaration atp.

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

A declarationd of a type namedn shadows the declarations of any other types namedn that are in scope at the point whered occurs throughout the scope ofd.

A declarationd of a field or formal parameter namedn shadows, throughout the scope ofd, the declarations of any other variables namedn that are in scope at the point whered occurs.

A declarationd of a local variable or exception parameter namedn shadows, throughout the scope ofd, (a) the declarations of any other fields namedn that are in scope at the point whered occurs, and (b) the declarations of any other variables namedn that are in scope at the point whered occurs but arenot declared in the innermost class in whichd is declared.

A declarationd of a method namedn shadows the declarations of any other methods namedn that are in an enclosing scope at the point whered occurs throughout the scope ofd.

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 declarationd in a compilation unitc of packagep that imports a type namedn shadows, throughoutc, the declarations of:

  • any top level type namedn declared in another compilation unit ofp

  • any type namedn imported by a type-import-on-demand declaration inc

  • any type namedn imported by a static-import-on-demand declaration inc

A single-static-import declarationd in a compilation unitc of packagep that imports a field namedn shadows the declaration of any static field namedn imported by a static-import-on-demand declaration inc, throughoutc.

A single-static-import declarationd in a compilation unitc of packagep that imports a method namedn with signatures shadows the declaration of any static method namedn with signatures imported by a static-import-on-demand declaration inc, throughoutc.

A single-static-import declarationd in a compilation unitc of packagep that imports a type namedn shadows, throughoutc, the declarations of:

  • any static type namedn imported by a static-import-on-demand declaration inc;

  • any top level type (§7.6) namedn declared in another compilation unit (§7.3) ofp;

  • any type namedn imported by a type-import-on-demand declaration (§7.5.2) inc.

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 classTest

  • a class (static) variablex that is a member of the classTest

  • a class methodmain that is a member of the classTest

  • a parameterargs of themain method

  • a local variablex of themain method

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

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

This means that:

  • The expressionx in the invocation ofprint refers to (denotes) the value of the local variablex.

  • The invocation ofprintln uses a qualified name (§6.6)Test.x, which uses the class type nameTest to access the class variablex, because the declaration ofTest.x is shadowed at this point and cannot be referred to by its simple name.

The keywordthis can also be used to access a shadowed fieldx, using the formthis.x. Indeed, this idiom typically appears in constructors (§8.8):

class Pair {    Object first, second;    public Pair(Object first, Object second) {        this.first = first;        this.second = second;    }}

Here, the constructor takes parameters having the same names as the fields to be initialized. This is simpler than having to invent different names for the parameters and is not too confusing in this stylized context. In general, however, it is considered poor style to have local variables with the same names as fields.


Example 6.4.1-2. Shadowing of a Type Declaration by Another Type Declaration

import java.util.*;class Vector {    int val[] = { 1 , 2 };}class Test {    public static void main(String[] args) {        Vector v = new Vector();        System.out.println(v.val[0]);    }}

The program compiles and prints:

1

using the classVector declared here in preference to the generic classjava.util.Vector (§8.1.2) that might be imported on demand.


6.4.2. Obscuring

A simple name may occur in contexts where it may potentially be interpreted as the name of a variable, a type, or a package. In these situations, the rules of§6.5 specify that a variable will be chosen in preference to a type, and that a type will be chosen in preference to a package. Thus, it is may sometimes be impossible to refer to a visible type or package declaration via its simple name. We say that such a declaration isobscured.

Obscuring is distinct from shadowing (§6.4.1) and hiding (§8.3,§8.4.8.2,§8.5,§9.3,§9.5).

The naming conventions of§6.1 help reduce obscuring, but if it does occur, here are some notes about what you can do to avoid it.

When package names occur in expressions:

  • If a package name is obscured by a field declaration, thenimport declarations (§7.5) can usually be used to make available the type names declared in that package.

  • If a package name is obscured by a declaration of a parameter or local variable, then the name of the parameter or local variable can be changed without affecting other code.

The first component of a package name is normally not easily mistaken for a type name, as a type name normally begins with a single uppercase letter. (The Java programming language does not actually rely on case distinctions to determine whether a name is a package name or a type name.)

Obscuring involving class and interface type names is rare. Names of fields, parameters, and local variables normally do not obscure type names because they conventionally begin with a lowercase letter whereas type names conventionally begin with an uppercase letter.

Method names cannot obscure or be obscured by other names (§6.5.7).

Obscuring involving field names is rare; however:

  • If a field name obscures a package name, then animport declaration (§7.5) can usually be used to make available the type names declared in that package.

  • If a field name obscures a type name, then a fully qualified name for the type can be used unless the type name denotes a local class (§14.3).

  • Field names cannot obscure method names.

  • If a field name is shadowed by a declaration of a parameter or local variable, then the name of the parameter or local variable can be changed without affecting other code.

Obscuring involving constant names is rare:

  • Constant names normally have no lowercase letters, so they will not normally obscure names of packages or types, nor will they normally shadow fields, whose names typically contain at least one lowercase letter.

  • Constant names cannot obscure method names, because they are distinguished syntactically.

6.5. Determining the Meaning of a Name

The meaning of a name 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 six categories:PackageName,TypeName,ExpressionName,MethodName,PackageOrTypeName, orAmbiguousName.

  • Second, a name that is initially classified by its context as anAmbiguousName or as aPackageOrTypeName is then reclassified to be aPackageName,TypeName, orExpressionName.

  • Third, the resulting category then dictates the final determination of the meaning of the name (or a compile-time error if the name has no meaning).

PackageName:
Identifier
PackageName.Identifier
TypeName:
Identifier
PackageOrTypeName.Identifier
PackageOrTypeName:
Identifier
PackageOrTypeName.Identifier
ExpressionName:
Identifier
AmbiguousName.Identifier
MethodName:
Identifier
AmbiguousName:
Identifier
AmbiguousName.Identifier

The use of context helps to minimize name conflicts between entities of different kinds. Such conflicts will be rare if the naming conventions described in§6.1 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. It is always possible to distinguish between a method and a field with the same name, since the context of a use always tells whether a method is intended.

6.5.1. Syntactic Classification of a Name According to Context

A name is syntactically classified as aTypeName in these contexts:

  • The first ten non-generic contexts (§6.1):

    1. In a single-type-import declaration (§7.5.1)

    2. To the left of the. in a single-static-import declaration (§7.5.3)

    3. To the left of the. in a static-import-on-demand declaration (§7.5.4)

    4. To the left of the( in a constructor declaration (§8.8)

    5. After the@ sign in an annotation (§9.7)

    6. To the left of.class in a class literal (§15.8.2)

    7. To the left of.this in a qualifiedthis expression (§15.8.4)

    8. To the left of.super in a qualified superclass field access expression (§15.11.2)

    9. To the left of.Identifier or.super.Identifier in a qualified method invocation expression (§15.12)

    10. To the left of.super:: in a method reference expression (§15.13)

  • As theIdentifier or dottedIdentifier sequence that constitutes anyReferenceType (including aReferenceType to the left of the brackets in an array type, or to the left of the < in a parameterized type, or in a non-wildcard type argument of a parameterized type, or in anextends orsuper clause of a wildcard type argument of a parameterized type) in the 16 contexts where types are used (§4.11):

    1. In anextends orimplements clause of a class declaration (§8.1.4,§8.1.5,§8.5,§9.5)

    2. In anextends clause of an interface declaration (§9.1.3)

    3. The return type of a method (§8.4,§9.4) (including the type of an element of an annotation type (§9.6.1))

    4. In thethrows clause of a method or constructor (§8.4.6,§8.8.5,§9.4)

    5. In anextends clause of a type parameter declaration of a generic class, interface, method, or constructor (§8.1.2,§9.1.2,§8.4.4,§8.8.4)

    6. The type in a field declaration of a class or interface (§8.3,§9.3)

    7. The type in a formal parameter declaration of a method, constructor, or lambda expression (§8.4.1,§8.8.1,§9.4,§15.27.1)

    8. The type of the receiver parameter of a method (§8.4.1)

    9. The type in a local variable declaration (§14.4,§14.14.1,§14.14.2,§14.20.3)

    10. A type in an exception parameter declaration (§14.20)

    11. In an explicit type argument list to an explicit constructor invocation statement or class instance creation expression or method invocation expression (§8.8.7.1,§15.9,§15.12)

    12. In an unqualified class instance creation expression, either as the class type to be instantiated (§15.9) or as the direct superclass or direct superinterface of an anonymous class to be instantiated (§15.9.5)

    13. The element type in an array creation expression (§15.10.1)

    14. The type in the cast operator of a cast expression (§15.16)

    15. The type that follows theinstanceof relational operator (§15.20.2)

    16. In a method reference expression (§15.13), as the reference type to search for a member method or as the class type or array type to construct.

The extraction of aTypeName from the identifiers of aReferenceType in the 16 contexts above is intended to apply recursively to all sub-terms of theReferenceType, such as its element type and any type arguments.

For example, suppose a field declaration uses the typep.q.Foo[]. The brackets of the array type are ignored, and the termp.q.Foo is extracted as a dotted sequence ofIdentifiers to the left of the brackets in an array type, and classified as aTypeName. A later step determines which ofp,q, andFoo is a type name or a package name.

As another example, suppose a cast operator uses the typep.q.Foo<? extends String>. The termp.q.Foo is again extracted as a dotted sequence ofIdentifier terms, this time to the left of the< in a parameterized type, and classified as aTypeName. The termString is extracted as anIdentifier in anextends clause of a wildcard type argument of a parameterized type, and classified as aTypeName.

A name is syntactically classified as anExpressionName in these contexts:

  • As the qualifying expression in a qualified superclass constructor invocation (§8.8.7.1)

  • As the qualifying expression in a qualified class instance creation expression (§15.9)

  • As the array reference expression in an array access expression (§15.10.3)

  • As aPostfixExpression (§15.14)

  • As the left-hand operand of an assignment operator (§15.26)

A name is syntactically classified as aMethodName in this context:

  • Before the "(" in a method invocation expression (§15.12)

A name is syntactically classified as aPackageOrTypeName in these contexts:

  • To the left of the "." in a qualifiedTypeName

  • In a type-import-on-demand declaration (§7.5.2)

A name is syntactically classified as anAmbiguousName in these contexts:

  • To the left of the "." in a qualifiedExpressionName

  • To the left of the rightmost. that occurs before the "(" in a method invocation expression

  • To the left of the "." in a qualifiedAmbiguousName

  • In the default value clause of an annotation type element declaration (§9.6.2)

  • To the right of an "=" in an an element-value pair (§9.7.1)

  • To the left of:: in a method reference expression (§15.13)

The effect of syntactic classification is to restrict certain kinds of entities to certain parts of expressions:

  • The name of a field, parameter, or local variable may be used as an expression (§15.14.1).

  • The name of a method may appear in an expression only as part of a method invocation expression (§15.12).

  • The name of a class or interface type may appear in an expression only as part of a class literal (§15.8.2), a qualifiedthis expression (§15.8.4), a class instance creation expression (§15.9), an array creation expression (§15.10.1), a cast expression (§15.16), aninstanceof expression (§15.20.2), an enum constant (§8.9), or as part of a qualified name for a field or method.

  • The name of a package may appear in an expression only as part of a qualified name for a class or interface type.

6.5.2. Reclassification of Contextually Ambiguous Names

AnAmbiguousName is then reclassified as follows.

If theAmbiguousName is a simple name, consisting of a singleIdentifier:

  • If theIdentifier appears within the scope (§6.3) of a local variable declaration (§14.4) or parameter declaration (§8.4.1,§8.8.1,§14.20) or field declaration (§8.3) with that name, then theAmbiguousName is reclassified as anExpressionName.

  • Otherwise, if a field of that name is declared in the compilation unit (§7.3) containing theIdentifier by a single-static-import declaration (§7.5.3), or by a static-import-on-demand declaration (§7.5.4) then theAmbiguousName is reclassified as anExpressionName.

  • Otherwise, if theIdentifier appears within the scope (§6.3) of a top level class (§8 (Classes)) or interface type declaration (§9 (Interfaces)), a local class declaration (§14.3) or member type declaration (§8.5,§9.5) with that name, then theAmbiguousName is reclassified as aTypeName.

  • Otherwise, if a type of that name is declared in the compilation unit (§7.3) containing theIdentifier, either by a single-type-import declaration (§7.5.1), or by a type-import-on-demand declaration (§7.5.2), or by a single-static-import declaration (§7.5.3), or by a static-import-on-demand declaration (§7.5.4), then theAmbiguousName is reclassified as aTypeName.

  • Otherwise, theAmbiguousName is reclassified as aPackageName. A later step determines whether or not a package of that name actually exists.

If theAmbiguousName is a qualified name, consisting of a name, a ".", and anIdentifier, then the name to the left of the "." is first reclassified, for it is itself anAmbiguousName. There is then a choice:

  • If the name to the left of the "." is reclassified as aPackageName, then:

    • 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 theIdentifier, then thisAmbiguousName is reclassified as aTypeName.

    • Otherwise, thisAmbiguousName is reclassified as aPackageName. 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 aTypeName, then:

    • If theIdentifier is the name of a method or field of the type denoted byTypeName, thisAmbiguousName is reclassified as anExpressionName.

    • Otherwise, if theIdentifier is the name of a member type of the type denoted byTypeName, thisAmbiguousName is reclassified as aTypeName.

    • Otherwise, a compile-time error occurs.

  • If the name to the left of the "." is reclassified as anExpressionName, then letT be the type of the expression denoted byExpressionName.

    • If theIdentifier is the name of a method or field of the type denoted byT, thisAmbiguousName is reclassified as anExpressionName.

    • Otherwise, if theIdentifier is the name of a member type (§8.5,§9.5) of the type denoted byT, then thisAmbiguousName is reclassified as aTypeName.

    • Otherwise, a compile-time error occurs.

Example 6.5.2-1. Reclassification of Contextually Ambiguous Names

Consider the following contrived "library code":

package org.rpgpoet;import java.util.Random;public 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 nameorg.rpgpoet.Music.wizards.length is classified as anExpressionName because it functions as aPostfixExpression. Therefore, each of the names:

org.rpgpoet.Music.wizardsorg.rpgpoet.Musicorg.rpgpoetorg

is initially classified as anAmbiguousName. These are then reclassified:

  • The simple nameorg is reclassified as aPackageName (since there is no variable or type named org in scope).

  • Next, assuming that there is no class or interface namedrpgpoet in any compilation unit of packageorg (and we know that there is no such class or interface because packageorg has a subpackage namedrpgpoet), the qualified nameorg.rpgpoet is reclassified as aPackageName.

  • Next, because packageorg.rpgpoet has an accessible (§6.6) interface type namedMusic, the qualified nameorg.rpgpoet.Music is reclassified as aTypeName.

  • Finally, because the nameorg.rpgpoet.Music is aTypeName, the qualified nameorg.rpgpoet.Music.wizards is reclassified as anExpressionName.


6.5.3. Meaning of Package Names

The meaning of a name classified as aPackageName is determined as follows.

6.5.3.1. Simple Package Names

If a package name consists of a singleIdentifier, then this identifier denotes a top level package named by that identifier.

If no top level package of that name is in scope (§6.3), then a compile-time error occurs.

6.5.3.2. Qualified Package Names

If a package name is of the formQ.Id, thenQ must also be a package name. The package nameQ.Id names a package that is the member namedId within the package named byQ.

IfQ does not name an observable package (§7.4.3), orId is not the simple name of an observable subpackage of that package, then a compile-time error occurs.

6.5.4. Meaning ofPackageOrTypeNames

6.5.4.1. SimplePackageOrTypeNames

If thePackageOrTypeName,Q, occurs in the scope of a type namedQ, then thePackageOrTypeName is reclassified as aTypeName.

Otherwise, thePackageOrTypeName is reclassified as aPackageName. The meaning of thePackageOrTypeName is the meaning of the reclassified name.

6.5.4.2. QualifiedPackageOrTypeNames

Given a qualifiedPackageOrTypeName of the formQ.Id, if the type or package denoted byQ has a member type namedId, then the qualifiedPackageOrTypeName name is reclassified as aTypeName.

Otherwise, it is reclassified as aPackageName. The meaning of the qualifiedPackageOrTypeName is the meaning of the reclassified name.

6.5.5. Meaning of Type Names

The meaning of a name classified as aTypeName is determined as follows.

6.5.5.1. Simple Type Names

If a type name consists of a singleIdentifier, then the identifier must occur in the scope of exactly one visible declaration of a type with this name, or a compile-time error occurs. The meaning of the type name is that type.

6.5.5.2. Qualified Type Names

If a type name is of the formQ.Id, thenQ must be either a type name or a package name.

IfId names exactly one accessible type (§6.6) that is a member of the type or package denoted byQ, then the qualified type name denotes that type.

IfId does not name a member type withinQ (§8.5,§9.5), or the member type namedId withinQ is not accessible (§6.6), orId names more than one member type withinQ, then a compile-time error occurs.

Example 6.5.5.2-1. Qualified Type Names

class Test {    public static void main(String[] args) {        java.util.Date date =            new java.util.Date(System.currentTimeMillis());        System.out.println(date.toLocaleString());    }}

This program produced the following output the first time it was run:

Sun Jan 21 22:56:29 1996

In this example, the namejava.util.Date must denote a type, so we first use the procedure recursively to determine ifjava.util is an accessible type or a package, which it is, and then look to see if the typeDate is accessible in this package.


6.5.6. Meaning of Expression Names

The meaning of a name classified as anExpressionName is determined as follows.

6.5.6.1. Simple Expression Names

If an expression name consists of a singleIdentifier, then there must be exactly one declaration denoting either a local variable, parameter, or field visible (§6.4.1) at the point at which theIdentifier occurs. Otherwise, a compile-time error occurs.

If the declaration denotes an instance variable (§8.3), the expression name must appear within the declaration of an instance method (§8.4), constructor (§8.8), instance initializer (§8.6), or instance variable initializer (§8.3.2). If the expression name appears within astatic method (§8.4.3.2), static initializer (§8.7), or initializer for astatic variable (§8.3.2,§12.4.2), then a compile-time error occurs.

If the declaration declares afinal variable which is definitely assigned before the simple expression, the meaning of the name is the value of that variable. Otherwise, the meaning of the expression name is the variable declared by the declaration.

If the expression name appears in an assignment context, invocation context, or casting context, then the type of the expression name is the declared type of the field, local variable, or parameter after capture conversion (§5.1.10).

Otherwise, the type of the expression name is the declared type of the field, local variable or parameter.

That is, if the expression name appears "on the right hand side", its type is subject to capture conversion. If the expression name is a variable that appears "on the left hand side", its type is not subject to capture conversion.

Example 6.5.6.1-1. Simple Expression Names

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);    }}

In this program, the names used as the left-hand-sides in the assignments toi,v, andf denote the local variablei, the fieldv, and the value off (not the variablef, becausef is afinal 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

6.5.6.2. Qualified Expression Names

If an expression name is of the formQ.Id, thenQ has already been classified as a package name, a type name, or an expression name.

IfQ is a package name, then a compile-time error occurs.

IfQ is a type name that names a class type (§8 (Classes)), then:

  • If there is not exactly one accessible (§6.6) member of the class type that is a field namedId, then a compile-time error occurs.

  • Otherwise, if the single accessible member field is not a class variable (that is, it is not declaredstatic), then a compile-time error occurs.

  • Otherwise, if the class variable is declaredfinal, thenQ.Id denotes the value of the class variable.

    The type of the expressionQ.Id is the declared type of the class variable after capture conversion (§5.1.10).

    IfQ.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 expressionQ.Id is the declared type of the class variable after capture conversion (§5.1.10).

    Note that this clause covers the use ofenum constants (§8.9), since these always have a correspondingfinal class variable.

IfQ is a type name that names an interface type (§9 (Interfaces)), then:

  • If there is not exactly one accessible (§6.6) member of the interface type that is a field namedId, then a compile-time error occurs.

  • Otherwise,Q.Id denotes the value of the field.

    The type of the expressionQ.Id is the declared type of the field after capture conversion (§5.1.10).

    IfQ.Id appears in a context that requires a variable and not a value, then a compile-time error occurs.

IfQ is an expression name, letT be the type of the expressionQ:

  • IfT is not a reference type, a compile-time error occurs.

  • If there is not exactly one accessible (§6.6) member of the typeT that is a field namedId, then a compile-time error occurs.

  • Otherwise, if this field is any of the following:

    • A field of an interface type

    • Afinal field of a class type (which may be either a class variable or an instance variable)

    • Thefinal fieldlength of an array type (§10.7)

    thenQ.Id denotes the value of the field, unless it appears in a context that requires a variable and the field is a definitely unassigned blankfinal field, in which case it yields a variable.

    The type of the expressionQ.Id is the declared type of the field after capture conversion (§5.1.10).

    IfQ.Id appears in a context that requires a variable and not a value, and the field denoted byQ.Id is definitely assigned, then a compile-time error occurs.

  • Otherwise,Q.Id denotes a variable, the fieldId of classT, which may be either a class variable or an instance variable.

    The type of the expressionQ.Id is the type of the field member after capture conversion (§5.1.10).

Example 6.5.6.2-1. Qualified Expression Names

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    }}

This program encounters two compile-time errors, because theint variablei has no members, and becausenPoints is not a method of classPoint.


Example 6.5.6.2-2. Qualifying an Expression with a Type Name

Note that expression names may be qualified by type names, but not by types in general. A consequence is that it is not possible to access a class variable through a parameterized type. For example, given the code:

class Foo<T> {    public static int classVar = 42;}

the following assignment is illegal:

Foo<String>.classVar = 91; // illegal

Instead, one writes:

Foo.classVar = 91;

This does not restrict the Java programming language in any meaningful way. Type parameters may not be used in the types of static variables, and so the type arguments of a parameterized type can never influence the type of a static variable. Therefore, no expressive power is lost. The type nameFoo appears to be a raw type, but it is not; rather, it is the name of the non-generic typeFoo whose static member is to be accessed (§6.1). Since there is no use of a raw type, there are no unchecked warnings.


6.5.7. Meaning of Method Names

The meaning of a name classified as aMethodName is determined as follows.

6.5.7.1. Simple Method Names

A simple method name appears in the context of a method invocation expression (§15.12). The simple method name consists of a singleIdentifier which specifies the name of the method to be invoked. The rules of method invocation require that theIdentifier either denotes a method that is visible at the point of the method invocation, or denotes a method imported by a single-static-import declaration or static-import-on-demand declaration (§7.5.3,§7.5.4).

Example 6.5.7.1-1. Simple Method Names and Visibility

The following program demonstrates the role of method visibility when determining which method to invoke.

class Super {    void f2(String s)       {}    void f3(String s)       {}    void f3(int i1, int i2) {}}class Test {    void f1(int i) {}    void f2(int i) {}    void f3(int i) {}    void m() {        new Super() {            {                f1(0);  // OK, resolves to Test.f1(int)                f2(0);  // compile-time error                f3(0);  // compile-time error            }        };    }}

For the invocationf1(0), only one method namedf1 is visible. It is the methodTest.f1(int), whose declaration is in scope throughout the body ofTest including the anonymous class declaration.§15.12.1 chooses to search in classTest since the anonymous class declaration has no member namedf1. Eventually,Test.f1(int) is resolved.

For the invocationf2(0), two methods namedf2 are visible. First, the declaration of the methodSuper.f2(String) is in scope throughout the anonymous class declaration. Second, the declaration of the methodTest.f2(int) is in scope throughout the body ofTest including the anonymous class declaration.§15.12.1 chooses to search in classSuper because it has a member namedf2. However,Super.f2(String) is not applicable tof2(0), so a compile-time error occurs. Note that classTest is not searched.

For the invocationf3(0), three methods namedf3 are visible. First and second, the declarations of the methodsSuper.f3(String) andSuper.f3(int,int) are in scope throughout the anonymous class declaration. Third, the declaration of the methodTest.f3(int) is in scope throughout the body ofTest including the anonymous class declaration.§15.12.1 chooses to search in classSuper because it has a member namedf3. However,Super.f3(String) andSuper.f3(int,int) are not applicable tof3(0), so a compile-time error occurs. Note that classTest is not searched.

Choosing to search a nested class's superclass hierarchy before the lexically enclosing scope is called the "comb rule" (§15.12.1).


6.6. Access Control

The Java programming language provides mechanisms foraccess control, to prevent the users of a package or class from depending on unnecessary details of the implementation of that package or class. If access is permitted, then the accessed entity is said to beaccessible.

Note that accessibility is a static property that can be determined at compile time; it depends only on types and declaration modifiers.

Qualified names are a means of access to members of packages and reference types. When the name of such a member is classified from its context (§6.5.1) as a qualified type name (denoting a member of a package or reference type,§6.5.5.2) or a qualified expression name (denoting a member of a reference type,§6.5.6.2), access control is applied.

For example, a single-type-import statement (§7.5.1) uses a qualified type name, so the named type must be accessible from the compilation unit containing the import statement. As another example, a class declaration may use a qualified type name for a superclass (§8.1.5), and again the named type must be accessible.

Some obvious expressions are "missing" from context classification in§6.5.1: field access on aPrimary (§15.11.1), method invocation on aPrimary (§15.12), method reference via aPrimary (§15.13), and the instantiated class in a qualified class instance creation (§15.9). Each of these expressions uses identifiers, rather than names, for the reason given in§6.2. Consequently, access control to members (whether fields, methods, or types) is appliedexplicitly by field access expressions, method invocation expressions, method reference expressions, and qualified class instance creation expressions. (Note that access to a field may also be denoted by a qualified name occuring as a postfix expression.)

In addition, many statements and expressions allow the use of types rather than type names. For example, a class declaration may use a parameterized type (§4.5) to denote a superclass. Because a parameterized type is not a qualified type name, it is necessary for the class declaration to explicitly perform access control for the denoted superclass. Consequently, most of the statements and expressions that provide contexts in§6.5.1 to classify aTypeName also perform their own access control checks.

Beyond access to members of a package or reference type, there is the matter of access to constructors of a reference type. Access control must be checked when a constructor is invoked explicitly or implicitly. Consequently, access control is checked by an explicit constructor invocation statement (§8.8.7.1) and by a class instance creation expression (§15.9.3). Such checks are necessary because§6.5.1 has no mention of explicit constructor invocation statements (because they reference constructor names indirectly) and is unaware of the distinction between the class type denoted by an unqualified class instance creation expression and a constructor of that class type. Also, constructors do not have qualified names, so we cannot rely on access control being checked during classification of qualified type names.

Accessibility affects inheritance of class members (§8.2), including hiding and method overriding (§8.4.8.1).

6.6.1. Determining Accessibility

  • A package is always accessible.

  • If a class or interface type is declaredpublic, then it may be accessed by any code, provided that the compilation unit (§7.3) in which it is declared is observable.

    If a class or interface type is declared with package access, then it may be accessed only from within the package in which it is declared.

    A class or interface type declared without an access modifier implicitly has package access.

  • An array type is accessible if and only if its element type is accessible.

  • A member (class, interface, field, or method) of a reference type, or a constructor of a class type, is accessible only if the type is accessible and the member or constructor is declared to permit access:

    • If the member or constructor is declaredpublic, then access is permitted.

      All members of interfaces lacking access modifiers are implicitlypublic.

    • Otherwise, if the member or constructor is declaredprotected, then access is permitted only when one of the following is true:

      • Access to the member or constructor occurs from within the package containing the class in which theprotected member or constructor is declared.

      • Access is correct as described in§6.6.2.

    • Otherwise, if the member or constructor is declared with package access, then access is permitted only when the access occurs from within the package in which the type is declared.

      A class member or constructor declared without an access modifier implicitly has package access.

    • Otherwise, the member or constructor is declaredprivate, and access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.

Example 6.6-1. Access Control

Consider the two compilation units:

package points;class PointVec { Point[] vec; }

and:

package points;public class Point {    protected int x, y;    public void move(int dx, int dy) { x += dx; y += dy; }    public int getX() { return x; }    public int getY() { return y; }}

which declare two class types in the packagepoints:

  • The class typePointVec is notpublic and not part of thepublic interface of the packagepoints, but rather can be used only by other classes in the package.

  • The class typePoint is declaredpublic and is available to other packages. It is part of thepublic interface of the packagepoints.

  • The methodsmove,getX, andgetY of the classPoint are declaredpublic and so are available to any code that uses an object of typePoint.

  • The fieldsx andy are declaredprotected and are accessible outside the packagepoints only in subclasses of classPoint, and only when they are fields of objects that are being implemented by the code that is accessing them.

    See§6.6.2 for an example of how theprotected access modifier limits access.


Example 6.6-2. Access topublic Fields, Methods, and Constructors

Apublic class member or constructor is accessible throughout the package where it is declared and from any other package, provided the package in which it is declared is observable (§7.4.3). For example, in the compilation unit:

package points;public class Point {    int x, y;    public void move(int dx, int dy) {        x += dx; y += dy;        moves++;    }    public static int moves = 0;}

thepublic classPoint has aspublic members themove method and themoves field. Thesepublic members are accessible to any other package that has access to packagepoints. The fieldsx andy are notpublic and therefore are accessible only from within the packagepoints.


Example 6.6-3. Access topublic and Non-public Classes

If a class lacks thepublic modifier, access to the class declaration is limited to the package in which it is declared (§6.6). In the example:

package points;public class Point {    public int x, y;    public void move(int dx, int dy) { x += dx; y += dy; }}class PointList {    Point next, prev;}

two classes are declared in the compilation unit. The classPoint is available outside the packagepoints, while the classPointList is available for access only within the package. Thus a compilation unit in another package can accesspoints.Point, either by using its fully qualified name:

package pointsUser;class Test1 {    public static void main(String[] args) {        points.Point p = new points.Point();        System.out.println(p.x + " " + p.y);    }}

or by using a single-type-import declaration (§7.5.1) that mentions the fully qualified name, so that the simple name may be used thereafter:

package pointsUser;import points.Point;class Test2 {    public static void main(String[] args) {        Point p = new Point();        System.out.println(p.x + " " + p.y);    }}

However, this compilation unit cannot use or importpoints.PointList, which is not declaredpublic and is therefore inaccessible outside packagepoints.


Example 6.6-4. Access to Package-Access Fields, Methods, and Constructors

If none of the access modifierspublic,protected, orprivate are specified, a class member or constructor has package access: it is accessible throughout the package that contains the declaration of the class in which the class member is declared, but the class member or constructor is not accessible in any other package.

If apublic class has a method or constructor with package access, then this method or constructor is not accessible to or inherited by a subclass declared outside this package.

For example, if we have:

package points;public class Point {    public int x, y;    void move(int dx, int dy) { x += dx; y += dy; }    public void moveAlso(int dx, int dy) { move(dx, dy); }}

then a subclass in another package may declare an unrelatedmove method, with the same signature (§8.4.2) and return type. Because the originalmove method is not accessible from packagemorepoints,super may not be used:

package morepoints;public class PlusPoint extends points.Point {    public void move(int dx, int dy) {        super.move(dx, dy);  // compile-time error        moveAlso(dx, dy);    }}

Becausemove ofPoint is not overridden bymove inPlusPoint, the methodmoveAlso inPoint never calls the methodmove inPlusPoint. Thus if you delete thesuper.move call fromPlusPoint and execute the test program:

import points.Point;import morepoints.PlusPoint;class Test {    public static void main(String[] args) {        PlusPoint pp = new PlusPoint();        pp.move(1, 1);    }}

it terminates normally. Ifmove ofPoint were overridden bymove inPlusPoint, then this program would recurse infinitely, until aStackOverflowError occurred.


Example 6.6-5. Access toprivate Fields, Methods, and Constructors

Aprivate class member or constructor is accessible only within the body of the top level class (§7.6) that encloses the declaration of the member or constructor. It is not inherited by subclasses. In the example:

class Point {    Point() { setMasterID(); }    int x, y;    private int ID;    private static int masterID = 0;    private void setMasterID() { ID = masterID++; }}

the private membersID,masterID, andsetMasterID may be used only within the body of classPoint. They may not be accessed by qualified names, field access expressions, or method invocation expressions outside the body of the declaration ofPoint.

See§8.8.8 for an example that uses aprivate constructor.


6.6.2. Details onprotected Access

Aprotected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.

6.6.2.1. Access to aprotected Member

LetC be the class in which aprotected member is declared. Access is permitted only within the body of a subclassS ofC.

In addition, ifId denotes an instance field or instance method, then:

  • If the access is by a qualified nameQ.Id or a method reference expressionQ:: Id (§15.13), whereQ is anExpressionName, then the access is permitted if and only if the type of the expressionQ isS or a subclass ofS.

  • If the access is by a field access expressionE.Id, or a method invocation expressionE.Id(...), or a method reference expressionE:: Id, whereE is aPrimary expression (§15.8), then the access is permitted if and only if the type ofE isS or a subclass ofS.

  • If the access is by a method reference expressionT:: Id, whereT is aReferenceType, then the access is permitted if and only if the typeT isS or a subclass ofS.

More information about access toprotected members can be found inChecking Access to Protected Members in the Java Virtual Machine by Alessandro Coglio, in theJournal of Object Technology, October 2005.

6.6.2.2. Qualified Access to aprotected Constructor

LetC be the class in which aprotected constructor is declared and letS be the innermost class in whose declaration the use of theprotected constructor occurs. Then:

  • If the access is by a superclass constructor invocationsuper(...), or a qualified superclass constructor invocationE.super(...), whereE is aPrimary expression, then the access is permitted.

  • If the access is by an anonymous class instance creation expressionnewC(...){...}, or a qualified anonymous class instance creation expressionE.newC(...){...}, whereE is aPrimary expression, then the access is permitted.

  • If the access is by a simple class instance creation expressionnewC(...), or a qualified class instance creation expressionE.newC(...), whereE is aPrimary expression, or a method reference expressionC::new, whereC is aClassType, then the access is not permitted. Aprotected constructor can be accessed by a class instance creation expression (that does not declare an anonymous class) or a method reference expression only from within the package in which it is defined.

Example 6.6.2-1. Access toprotected Fields, Methods, and Constructors

Consider this example, where thepoints package declares:

package points;public class Point {    protected int x, y;    void warp(threePoint.Point3d a) {        if (a.z > 0)  // compile-time error: cannot access a.z            a.delta(this);    }}

and thethreePoint package declares:

package threePoint;import points.Point;public class Point3d extends Point {    protected int z;    public void delta(Point p) {        p.x += this.x;  // compile-time error: cannot access p.x        p.y += this.y;  // compile-time error: cannot access p.y    }    public void delta3d(Point3d q) {        q.x += this.x;        q.y += this.y;        q.z += this.z;    }}

A compile-time error occurs in the methoddelta here: it cannot access theprotected membersx andy of its parameterp, because whilePoint3d (the class in which the references to fieldsx andy occur) is a subclass ofPoint (the class in whichx andy are declared), it is not involved in the implementation of aPoint (the type of the parameterp). The methoddelta3d can access theprotected members of its parameterq, because the classPoint3d is a subclass ofPoint and is involved in the implementation of aPoint3d.

The methoddelta could try to cast (§5.5,§15.16) its parameter to be aPoint3d, but this cast would fail, causing an exception, if the class ofp at run time were notPoint3d.

A compile-time error also occurs in the methodwarp: it cannot access theprotected memberz of its parametera, because while the classPoint (the class in which the reference to fieldz occurs) is involved in the implementation of aPoint3d (the type of the parametera), it is not a subclass ofPoint3d (the class in whichz is declared).


6.7. Fully Qualified Names and Canonical Names

Every primitive type, named package, top level class, and top level interface has afully qualified name:

  • The fully qualified name of a primitive type is the keyword for that primitive type, namelybyte,short,char,int,long,float,double, orboolean.

  • The fully qualified name of a named package that is not a subpackage of a named package is its simple name.

  • The fully qualified name of a named package that is a subpackage of another named package consists of the fully qualified name of the containing package, followed by ".", followed by the simple (member) name of the subpackage.

  • The fully qualified name of a top level class or top level interface that is declared in an unnamed package is the simple name of the class or interface.

  • The fully qualified name of a top level class or top level interface that is declared in a named package consists of the fully qualified name of the package, followed by ".", followed by the simple name of the class or interface.

Each member class, member interface, and array typemay have a fully qualified name:

  • A member class or member interfaceM of another class or interfaceC has a fully qualified name if and only ifC has a fully qualified name.

    In that case, the fully qualified name ofM consists of the fully qualified name ofC, followed by ".", followed by the simple name ofM.

  • An array type has a fully qualified name if and only if its element type has a fully qualified name.

    In that case, the fully qualified name of an array type consists of the fully qualified name of the component type of the array type followed by "[]".

A local class does not have a fully qualified name.

Every primitive type, named package, top level class, and top level interface has acanonical name:

  • For every primitive type, named package, top level class, and top level interface, the canonical name is the same as the fully qualified name.

Each member class, member interface, and array typemay have a canonical name:

  • A member class or member interfaceM declared in another class or interfaceC has a canonical name if and only ifC has a canonical name.

    In that case, the canonical name ofM consists of the canonical name ofC, followed by ".", followed by the simple name ofM.

  • An array type has a canonical name if and only if its component type has a canonical name.

    In that case, the canonical name of the array type consists of the canonical name of the component type of the array type followed by "[]".

A local class does not have a canonical name.

Example 6.7-1. Fully Qualified Names

  • The fully qualified name of the typelong is "long".

  • The fully qualified name of the packagejava.lang is "java.lang" because it is subpackagelang of packagejava.

  • The fully qualified name of the classObject, which is defined in the packagejava.lang, is "java.lang.Object".

  • The fully qualified name of the interfaceEnumeration, which is defined in the packagejava.util, is "java.util.Enumeration".

  • The fully qualified name of the type "array ofdouble" is "double[]".

  • The fully qualified name of the type "array of array of array of array ofString" is "java.lang.String[][][][]".

In the code:

package points;class Point    { int x, y; }class PointVec { Point[] vec; }

the fully qualified name of the typePoint is "points.Point"; the fully qualified name of the typePointVec is "points.PointVec"; and the fully qualified name of the type of the fieldvec of classPointVec is "points.Point[]".


Example 6.7-2. Fully Qualified Names v. Canonical Name

The difference between a fully qualified name and a canonical name can be seen in code such as:

package p;class O1 { class I {} }class O2 extends O1 {}

Bothp.O1.I andp.O2.I are fully qualified names that denote the member classI, but onlyp.O1.I is its canonical name.



Prev   Next
Chapter 5. Conversions and Contexts Home Chapter 7. Packages

Legal Notice

[8]ページ先頭

©2009-2025 Movatter.jp