Spec-Zone .ru
спецификации, руководства, описания, API
|
Contents | Prev | Next | Index | Java Language Specification Third Edition |
CHAPTER 6
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) (§4.4), parameter (to a method, constructor, or exception handler), or local variable.
Names in programs are either simple, consisting of a single identifier, or qualified, consisting of a sequence of identifiers separated by ".
" tokens (§6.2).
Every declaration that introduces a name has a scope (§6.3), which is the part of the program text within which the declared entity can be referred to by a simple name.
Packages and reference types (that is, class types, interface types, and array types) have members (§6.4). A member can be referred to using a qualified name N.x, where N is a simple or qualified name and x is an identifier. If N names a package, then x is a member of that package, which is either a class or interface type or a subpackage. If N names a reference type or a variable of a reference type, then x 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 when access 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, a field access expression (§15.11), or a method invocation expression (§15.12) in which the method is not specified by a simple name. The default access is that a member can be accessed anywhere within the package that contains its declaration; other possibilities are public
, protected
, and private
.
Fully qualified and canonical names (§6.7) and naming conventions (§6.8) are also discussed in this chapter.
The name of a field, parameter, or local variable may be used as an expression (§15.14.2). 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 qualified this expression (§15.8.4), a class instance creation expression (§15.9), an array creation expression (§15.10), a cast expression (§15.16), an instanceof
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.
package
declaration (§7.4)
length
, which is implicitly a member of every array type (§10.7)
abstract
method of an interface (§9.4)
catch
clause of a try
statement (§14.20)
There are two forms of names: simple names and qualified names. A simple name is a single identifier. 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).
Not all identifiers in programs are a part of a name. Identifiers are also used in the following situations:
.
" token to indicate a member of an object that is the value of an expression or the keyword super
that appears before the ".
" token
.
" 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
break
(§14.15) and continue
(§14.16) statements that refer to statement labels.
the identifiersclass Test { public static void main(String[] args) { Class c = System.out.getClass(); System.out.println(c.toString().length() + args[0].length() + args.length); } }
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
, args
, and args.length
appear in the example. The first occurrence of length
is not a name, but rather an identifier appearing in a method invocation expression (§15.12). The second occurrence of length
is not a name, but rather an identifier appearing in a method invocation expression (§15.12).The identifiers used in labeled statements and their associated break
and continue
statements are completely separate from those used in declarations. Thus, the following code is valid:
This code was taken from a version of the classclass TestString { 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; } }
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.3.2) the label in the scope of the declaration of i
. 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.The scoping rules for various constructs are given in the sections that describe those constructs. For convenience, the rules are repeated here:
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. Subpackage declarations are never 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 the import declaration appears.
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 the import declaration appears.
The scope of a top level type is all type declarations in the package in which the top level type is declared.
The scope of a declaration of a member m declared in or inherited by a class type C is the entire body of C, including any nested type declarations.
The scope of the declaration of a member m declared in or inherited by an interface type I is the entire body of I, including any nested type declarations.
The scope of a parameter of a method (§8.4.1) or constructor (§8.8.1) is the entire body of the method or constructor.
The scope of an interface's type parameter is the entire declaration of the interface including the type parameter section itself. Therefore, type parameters can appear as parts of their own bounds, or as bounds of other type parameters declared in the same section.
The scope of a method's type parameter is the entire declaration of the method, including the type parameter section itself. Therefore, type parameters can appear as parts of their own bounds, or as bounds of other type parameters declared in the same section.
The scope of a constructor's type parameter is the entire declaration of the constructor, including the type parameter section itself. Therefore, type parameters can appear as parts of their own bounds, or as bounds of other type parameters declared in the same section.
The scope of a local variable declaration in a block (§14.4.2) is the rest of the block in which the declaration appears, starting with its own initializer (§14.4) and including any further declarators to the right in the local variable declaration statement.
The scope of a local class 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 immediately enclosed by in 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 declared in the forInit part of a basic for
statement (§14.14) includes all of the following:
for
statement
for
statement
for
statement (§14.14) is the contained Statement
The scope of a parameter of an exception handler that is declared in a catch
clause of a try
statement (§14.20) is the entire block associated with the catch
.
These rules imply that declarations of class and interface types need not appear before uses of the types.
In the example:
package points; class Point { int x, y; PointList list; Point next; } class PointList { Point first; }
the use of PointList
in class Point
is correct, because the scope of the class declaration PointList
includes both class Point
and class PointList
, as well as any other type declarations in other compilation units of package points
.
A declaration d of a type named n shadows the declarations of any other types named n that are in scope at the point where d occurs throughout the scope of d.
A declaration d of a field, local variable, method parameter, constructor parameter or exception handler parameter named n shadows the declarations of any other fields, local variables, method parameters, constructor parameters or exception handler parameters named n that are in scope at the point where d occurs throughout the scope of d.
A declaration d of a method named n shadows the declarations of any other methods named n that are in an enclosing scope at the point where d occurs throughout the scope of d.
A package declaration never shadows any other declaration.
A single-type-import declaration d in a compilation unit c of package p that imports a type named n shadows the declarations of:
A single-static-import declaration d in a compilation unit c of package p that imports a field named n shadows the declaration of any static field named n imported by a static-import-on-demand declaration in c, throughout c.
A single-static-import declaration d in a compilation unit c of package p that imports a method named n with signature s shadows the declaration of any static method named n with signature s imported by a static-import-on-demand declaration in c, throughout c.
A single-static-import declaration d in a compilation unit c of package p that imports a type named n shadows the declarations of:
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 declaration d is said to be visible at point p in a program if the scope of d includes p, and d is not shadowed by any other declaration at p. When the program point we are discussing is clear from context, we will often simply say that a declaration is visible.
Note that shadowing is distinct from hiding (§8.3, §8.4.8.2, §8.5, §9.3, §9.5). Hiding, in the technical sense defined in this specification, 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.3.2).
Here is an example of shadowing of a field declaration by a local variable declaration:
produces the output: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 example declares:x=0, Test.x=1
Test
static
) variable x
that is a member of the class Test
main
that is a member of the class Test
args
of the main
method.
x
of the main
method
Since the scope of a class variable includes the entire body of the class (§8.2) the class variable x
would normally be available throughout the entire body of the method main
. In this example, however, the class variable x
is shadowed within the body of the method main
by the declaration of the local variable x
.
A local variable has as its scope the rest of the block in which it is declared (§14.4.2); in this case this is the rest of the body of the main
method, namely its initializer "0
" and the invocations of print
and println
.
This means that:
x
" in the invocation of print
refers to (denotes) the value of the local variable x
.
println
uses a qualified name (§6.6) Test.x
, which uses the class type name Test
to access the class variable x
, because the declaration of Test.x
is shadowed at this point and cannot be referred to by its simple name.
The following example illustrates the shadowing of one type declaration by another:
compiles and prints: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]); } }
using the class1
Vector
declared here in preference to the generic (§8.1.2) class java.util.Vector
that might be imported on demand.Obscuring is distinct from shadowing (§6.3.1) and hiding (§8.3, §8.4.8.2, §8.5, §9.3, §9.5). The naming conventions of §6.8 help reduce obscuring.
This section provides an overview of the members of packages and reference types here, as background for the discussion of qualified names and the determination of the meaning of names. For a complete description of membership, see §4.4, §4.5.2, §4.8, §4.9, §7.1, §8.2, §9.2, and §10.7.
The members of a package are its subpackages and all the top level (§7.6) class types (§8) and top level interface types (§9) declared in all the compilation units (§7.3) of the package.
In general, the subpackages of a package are determined by the host system (§7.2). However, the package java
always includes the subpackages lang
and io
and may include other subpackages. No two distinct members of the same package may have the same simple name (§7.1), but members of different packages may have the same simple name.
For example, it is possible to declare a package:
that has as a member apackage vector; public class Vector { Object[] vec; }
public
class named Vector
, even though the package java.util
also declares a class named Vector
. These two class types are different, reflected by the fact that they have different fully qualified names (§6.7). The fully qualified name of this example Vector
is vector.Vector
, whereas java.util.Vector
is the fully qualified name of the Vector
class usually included in the Java platform. Because the package vector
contains a class named Vector
, it cannot also have a subpackage named Vector
.The members of a class type are all of the following:
Object
has no direct superclass)
There is no restriction against a field and a method of a class type having the same simple name. Likewise, there is no restriction against a member class or member interface of a class type having the same simple name as a field or method of that class type.
A class may have two or more fields with the same simple name if they are declared in different interfaces and inherited. An attempt to refer to any of the fields by its simple name results in a compile-time error (§6.5.7.2, §8.2).
In the example:
the nameinterface Colors { int WHITE = 0, BLACK = 1; } interface Separates { int CYAN = 0, MAGENTA = 1, YELLOW = 2, BLACK = 3; } class Test implements Colors, Separates { public static void main(String[] args) { System.out.println(BLACK); // compile-time error: ambiguous } }
BLACK
in the method main
is ambiguous, because class Test
has two members named BLACK
, one inherited from Colors
and one from Separates
.A class type may have two or more methods with the same simple name if the methods have signatures that are not override-equivalent (§8.4.2). Such a method member name is said to be overloaded.
A class type may contain a declaration for a method with the same name and the same signature as a method that would otherwise be inherited from a superclass or superinterface. In this case, the method of the superclass or superinterface is not inherited. If the method not inherited is abstract
, then the new declaration is said to implement it; if the method not inherited is not abstract
, then the new declaration is said to override it.
In the example:
the classclass Point { float x, y; void move(int dx, int dy) { x += dx; y += dy; } void move(float dx, float dy) { x += dx; y += dy; } public String toString() { return "("+x+","+y+")"; } }
Point
has two members that are methods with the same name, move
. The overloaded move
method of class Point
chosen for any particular method invocation is determined at compile time by the overloading resolution procedure given in §15.12.In this example, the members of the class Point
are the float
instance variables x
and y
declared in Point
, the two declared move
methods, the declared toString
method, and the members that Point
inherits from its implicit direct superclass Object
(§4.3.2), such as the method hashCode
. Note that Point
does not inherit the toString
method of class Object
because that method is overridden by the declaration of the toString
method in class Point
.
throws
clause t corresponding to each public instance method m with signature s, return type r, and throws
clause t declared in Object
, unless a method with the same signature, same return type, and a compatible throws
clause is explicitly declared by the interface. It is a compile-time error if the interface explicitly declares such a method m in the case where m is declared to be final
in Object
.
An interface may have two or more fields with the same simple name if they are declared in different interfaces and inherited. An attempt to refer to any such field by its simple name results in a compile-time error (§6.5.6.1, §9.2).
In the example:
the members of the interfaceinterface Colors { int WHITE = 0, BLACK = 1; } interface Separates { int CYAN = 0, MAGENTA = 1, YELLOW = 2, BLACK = 3; } interface ColorsAndSeparates extends Colors, Separates { int DEFAULT = BLACK; // compile-time error: ambiguous }
ColorsAndSeparates
include those members inherited from Colors
and those inherited from Separates
, namely WHITE
, BLACK
(first of two), CYAN
, MAGENTA
, YELLOW
, and BLACK
(second of two). The member name BLACK
is ambiguous in the interface ColorsAndSeparates
.The members of an array type are all of the following:
public
final
field length
, which contains the number of components of the array (length
may be positive or zero).
public
method clone
, which overrides the method of the same name in class Object
and throws no checked exceptions. The return type of the clone method of an array type T[] is T[].
Object
; the only method of Object
that is not inherited is its clone
method.
produces the output:class Test { public static void main(String[] args) { int[] ia = new int[3]; int[] ib = new int[6]; System.out.println(ia.getClass() == ib.getClass()); System.out.println("ia has length=" + ia.length); } }
This example uses the methodtrue ia has length=3
getClass
inherited from class Object
and the field length
. The result of the comparison of the Class
objects in the first println
demonstrates that all arrays whose components are of type int
are instances of the same array type, which is int[]
.
PackageName: Identifier PackageName . Identifier TypeName: Identifier PackageOrTypeName . Identifier ExpressionName: Identifier AmbiguousName . Identifier MethodName: Identifier AmbiguousName . Identifier PackageOrTypeName: Identifier PackageOrTypeName . 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.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. 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.
.
" in a qualified PackageName
extends
clause in a type variable declaration (§8.1.2)
extends
clause of a wildcard type argument (§4.5.1)
super
clause of a wildcard type argument (§4.5.1)
extends
clause in a class declaration (§8.1.4)
implements
clause in a class declaration (§8.1.5)
extends
clause in an interface declaration (§9.1.3)
catch
clause of a try
statement (§14.20)
this
expression (§15.8.4).
super
(§15.11.2)
super
(§15.12)
instanceof
relational operator (§15.20.2)
A name is syntactically classified as an ExpressionName in these contexts:
(
" in a method invocation expression (§15.12)
.
" in a qualified ExpressionName
.
" in a qualified MethodName
.
" in a qualified AmbiguousName
.
", 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:
.
" is reclassified as a PackageName, 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 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.
.
" is reclassified as a TypeName, then if the Identifier is the name of a method or field of the type denoted by TypeName, this AmbiguousName is reclassified as an ExpressionName. Otherwise, if the Identifier is the name of a member type of the type denoted by TypeName, this AmbiguousName is reclassified as a TypeName. Otherwise, a compile-time error results.
.
" is reclassified as an ExpressionName, then let T be the type of the expression denoted by ExpressionName. If the Identifier is the name of a method or field of the type denoted by T, this AmbiguousName is reclassified as an ExpressionName. Otherwise, if the Identifier is the name of a member type (§8.5, §9.5) of the type denoted by T, then this AmbiguousName is reclassified as a TypeName. Otherwise, a compile-time error results.
As an example, consider the following contrived "library code":
and then consider this example code in another package:package org.rpgpoet; import java.util.Random; interface Music { Random[] wizards = new Random[4]; }
First of all, the namepackage bazola; class Gabriel { static int n = org.rpgpoet.Music.wizards.length; }
org.rpgpoet.Music.wizards.length
is classified as an ExpressionName because it functions as a PostfixExpression. Therefore, each of the names:
is initially classified as an AmbiguousName. These are then reclassified:org.rpgpoet.Music.wizards org.rpgpoet.Music org.rpgpoet org
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.
org.rpgpoet
has an interface type named Music
, the qualified name org.rpgpoet.Music
is reclassified as a TypeName.
org.rpgpoet.Music
is a TypeName, the qualified name org.rpgpoet.Music.wizards
is reclassified as an ExpressionName.
.
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 observable package (§7.4.3), or Id is not the simple name an observable subpackage of that package, then a compile-time error occurs.Otherwise, the PackageOrTypeName is reclassified as a PackageName. The meaning of the PackageOrTypeName is the meaning of the reclassified name.
Otherwise, it is reclassified as a PackageName. The meaning of the qualified PackageOrTypeName is the meaning of the reclassified name.
.
Id, then Q must be either a type name or a package name. If Id names exactly one type that is a member of the type or package denoted by Q, then the qualified type name denotes that type. If Id does not name a member type (§8.5, §9.5) within Q, or the member type named Id within Q is not accessible (§6.6), or Id names more than one member type within Q, then a compile-time error occurs. The example:
produced the following output the first time it was run: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()); } }
In this example the nameSun Jan 21 22:56:29 1996
java.util.Date
must denote a type, so we first use the procedure recursively to determine if java.util
is an accessible type or a package, which it is, and then look to see if the type Date
is accessible in this package.
Discussion
Type names are distinct from type declaration specifiers (§4.3). A type name is always qualified by meas of another type name. In some cases, it is necessary to access an inner class that is a member of a parameterized type:
If we accessedclass GenericOuter<T extends Number> { public class Inner<S extends Comparable<S>> { T getT() { return null;} S getS() { return null;} } }; GenericOuter<Integer>.Inner<Double> x1 = null; Integer i = x1.getT(); Double d = x1.getS();
Inner
by qualifying it with a type name, as in:
we would force its use as a raw type, losing type information.GenericOuter.Inner x2 = null;
If the declaration declares a final field, the meaning of the name is the value of that field. Otherwise, the meaning of the expression name is the variable declared by the declaration.
If the field is 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.2). If it appears within a static
method (§8.4.3.2), static initializer (§8.7), or initializer for a static
variable (§8.3.2.1, §12.4.2), then a compile-time error occurs.
The type of the expression name is the declared type of the field, local variable or parameter after capture conversion (§5.1.10).
the names used as the left-hand-sides in the assignments toclass 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); } }
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
.
Id, then Q has already been classified as a package name, a type name, or an expression name:
static
), then a compile-time error occurs.
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 after capture conversion (§5.1.10). If Q.
Id appears in a context that requires a variable and not a value, then a compile-time error occurs.
.
Id denotes the class variable. The type of the expression Q.
Id is the declared type of the class variable after capture conversion (§5.1.10). Note that this clause covers the use of enum constants (§8.9), since these always have a corresponding final
class variable.
.
Id denotes the value of the field. The type of the expression Q.
Id is the declared type of the field after capture conversion (§5.1.10). If Q.
Id appears in a context that requires a variable and not a value, then a compile-time error occurs.
final
field of a class type (which may be either a class variable or an instance variable)
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 after capture conversion (§5.1.10). If Q.
Id appears in a context that requires a variable and not a value, then a compile-time error occurs.
.
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 type of the field member after capture conversion (§5.1.10).
The example:
encounters two compile-time errors, because theclass 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 } }
int
variable i
has no members, and because nPoints
is not a method of class Point
.Discussion
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
Instead, one writesclass Foo<T> { public static int classVar = 42; } Foo<String>.classVar = 91; // illegal
This does not restrict the language in any meaningful way. Type parameters may not be used in the types of static variables, and so the actual parameters of a parameterized type can never influence the type of a static variable. Therefore, no expressive power is lost. Technically, the type nameFoo.classVar = 91;
Foo
above is a raw type, but this use of raw types is harmless, and does not give rise to warnings
Otherwise, a simple method name necessarily appears in the context of a method invocation expression. In that case, 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 visible (§6.3.1) method that is in scope at the point where the Identifier appear or a method imported by a single-static-import declaration (§7.5.3) or static-import-on-demand declaration (§7.5.4) within the compilation unit within which the Identifier appears.
See §15.12 for further discussion of the interpretation of simple method names in method invocation expressions.
.
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 §15.12 for further discussion of the interpretation of qualified method names in method invocation expressions.Discussion
Like expression names, method names may be qualified by type names, but not by types in general. The implications are similar to those for expression names as discussed in §6.5.6.2.
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; related means of access include field access expressions (§15.11) and method invocation expressions (§15.12). All three are syntactically similar in that a ".
" token appears, preceded by some indication of a package, type, or expression having a type and followed by an Identifier that names a member of the package or type. These are collectively known as constructs for qualified access.
Access control applies to qualified access and to the invocation of constructors by class instance creation expressions (§15.9) and explicit constructor invocations (§8.8.7.1). Accessibility also effects inheritance of class members (§8.2), including hiding and method overriding (§8.4.8.1).
public
, then it may be accessed by any code, provided that the compilation unit (§7.3) in which it is declared is observable. If a top level class or interface type is not declared public
, then it may be accessed only from within the package in which it is declared.
public
, then access is permitted. All members of interfaces are implicitly public
.
protected
, then access is permitted only when one of the following is true:
protected
member or constructor is declared.
private
, then 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.
protected
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.protected
member m is declared. Access is permitted only within the body of a subclass S of C. In addition, if Id denotes an instance field or instance method, then:
.
Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S.
.
Id, where E is a Primary expression, or by a method invocation expression E.
Id(
. . .)
, where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.
protected
constructor is declared and let S be the innermost class in whose declaration the use of the protected
constructor occurs. Then:
super(
. . .)
or by a qualified superclass constructor invocation of the form E.super(. . .)
, where E is a Primary expression, then the access is permitted.
(. . .){...}
or by a qualified class instance creation expression of the form E.new
C(. . .){...}
, where E is a Primary expression, then the access is permitted.
new
C(
. . .)
or by a qualified class instance creation expression of the form E.new
C(. . .)
, where E is a Primary expression, then the access is not permitted. A protected
constructor can be accessed by a class instance creation expression (that does not declare an anonymous class) only from within the package in which it is defined.
and:package points; class PointVec { Point[] vec; }
which declare two class types in the packagepackage 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; } }
points
:
PointVec
is not public
and not part of the public
interface of the package points
, but rather can be used only by other classes in the package.
Point
is declared public
and is available to other packages. It is part of the public
interface of the package points
.
move
, getX
, and getY
of the class Point
are declared public
and so are available to any code that uses an object of type Point
.
x
and y
are declared protected
and are accessible outside the package points
only in subclasses of class Point,
and only when they are fields of objects that are being implemented by the code that is accessing them.
protected
access modifier limits access. public
modifier, access to the class declaration is limited to the package in which it is declared (§6.6). In the example:
two classes are declared in the compilation unit. The classpackage points; public class Point { public int x, y; public void move(int dx, int dy) { x += dx; y += dy; }}
class PointList { Point next, prev; }
Point
is available outside the package points
, while the class PointList
is available for access only within the package. Thus a compilation unit in another package can access points.Point
, either by using its fully qualified name:
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; class Test { public static void main(String[] args) { points.Point p = new points.Point(); System.out.println(p.x + " " + p.y); } }
However, this compilation unit cannot use or importpackage pointsUser; import points.Point; class Test { public static void main(String[] args) { Point p = new Point(); System.out.println(p.x + " " + p.y); }}
points.PointList
, which is not declared public
and is therefore inaccessible outside package points
.public
, protected
, or private
are specified, a class member or constructor 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 a public
class has a method or constructor with default access, then this method or constructor is not accessible to or inherited by a subclass declared outside this package.
For example, if we have:
then a subclass in another package may declare an unrelatedpackage 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); } }
move
method, with the same signature (§8.4.2) and return type. Because the original move
method is not accessible from package morepoints
, super
may not be used:
Because move ofpackage morepoints; public class PlusPoint extends points.Point { public void move(int dx, int dy) { super.move(dx, dy); // compile-time error moveAlso(dx, dy); } }
Point
is not overridden by move
in PlusPoint
, the method moveAlso
in Point
never calls the method move in PlusPoint
.Thus if you delete the super.move
call from PlusPoint
and execute the test program:
it terminates normally. If move ofimport points.Point; import morepoints.PlusPoint; class Test { public static void main(String[] args) { PlusPoint pp = new PlusPoint(); pp.move(1, 1);}
}
Point
were overridden by move
in PlusPoint
, then this program would recurse infinitely, until a StackoverflowError
occurred.public
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:
thepackage points; public class Point { int x, y; public void move(int dx, int dy) { x += dx; y += dy; moves++; } public static int moves = 0; }
public
class Point
has as public
members the move
method and the moves
field. These public
members are accessible to any other package that has access to package points
. The fields x
and y
are not public
and therefore are accessible only from within the package points
.points
package declares:
and thepackage 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); } }
threePoint
package declares:
which defines a classpackage 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; } }
Point3d
. A compile-time error occurs in the method delta
here: it cannot access the protected members x
and y
of its parameter p
, because while Point3d
(the class in which the references to fields x
and y
occur) is a subclass of Point
(the class in which x
and y
are declared), it is not involved in the implementation of a Point
(the type of the parameter p
). The method delta3d
can access the protected members of its parameter q
, because the class Point3d
is a subclass of Point
and is involved in the implementation of a Point3d
.The method delta
could try to cast (§5.5, §15.16) its parameter to be a Point3d
, but this cast would fail, causing an exception, if the class of p
at run time were not Point3d
.
A compile-time error also occurs in the method warp: it cannot access the protected member z
of its parameter a
, because while the class Point
(the class in which the reference to field z
occurs) is involved in the implementation of a Point3d
(the type of the parameter a
), it is not a subclass of Point3d
(the class in which z
is declared).
A
private
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:
theclass Point { Point() { setMasterID(); } int x, y; private int ID; private static int masterID = 0; private void setMasterID() { ID = masterID++; } }
private
members ID,
masterID
, and setMasterID
may be used only within the body of class Point
. They may not be accessed by qualified names, field access expressions, or method invocation expressions outside the body of the declaration of Point
.See §8.8.8 for an example that uses a private
constructor.
boolean
, char
, byte
, short
, int
, long
, float
, or double
.
.
", followed by the simple (member) name of the subpackage.
.
", followed by the simple name of the class or interface.
[]
".
long
is "long
".
java.lang
is "java.lang
" because it is subpackage lang
of package java
.
Object
, which is defined in the package java.lang
, is "java.lang.Object
".
Enumeration
, which is defined in the package java.util
, is "java.util.Enumeration
".
double
" is "double[]
".
String
" is "java.lang.String[][][][]
".
the fully qualified name of the typepackage points; class Point { int x, y; } class PointVec { Point[] vec; }
Point
is "points.Point
"; the fully qualified name of the type PointVec
is "points.PointVec
"; and the fully qualified name of the type of the field vec
of class PointVec
is "points.Point[]
".
Every package, top level class, top level interface, and primitive type has a canonical name. An array type has a canonical name if and only if its element type has a canonical name. A member class or member interface M declared in another class C has a canonical name if and only if C has a canonical name. In that case, the canonical name of M consists of the canonical name of C, followed by ".", followed by the simple name of M. For every package, top level class, top level interface and primitive type, the canonical name is the same as the fully qualified name. The canonical name of an array type is defined only when the component type of the array 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 "[]
".
The difference between a fully qualified name and a canonical name can be seen in examples such as:
In this example bothpackage p; class O1 { class I{}} class O2 extends O1{};
p.O1.I
and p.O2.I
are fully qualified names that denote the same class, but only p.O1.I
is its canonical name.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, the sin
and cos
methods of the class java.lang.Math
have mathematically conventional names, even though these method names flout the convention suggested here because they are short and are not verbs.
com
, edu
, gov
, mil
, net
, org
, or a two-letter ISO country code such as uk
or jp
. Here are examples of hypothetical unique names that might be formed under this convention:
com.JavaSoft.jag.Oak org.npr.pledge.driver uk.ac.city.rugby.game
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 identifier java
; package names that start with the identifier java
are reserved by Sun for naming Java platform packages.
When package names occur in expressions:
import
declarations (§7.5) can usually be used to make available the type names declared in that package.
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.)
ClassLoader
SecurityManager
Thread
Dictionary
BufferedInputStream
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 interfaces java.io.DataInput
and java.io.DataOutput
; or it may be an adjective describing a behavior, as for the interfaces Runnable
and Cloneable
.
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.
Discussion
This makes it easy to distinguish formal type parameters from ordinary classes and interfaces.
Container types should use the name E
for their element type. Maps should use K
for the type of their keys and V
for the type of their values. The name X
should be used for arbitrary exception types. We use T
for type, whenever there isn't anything more specific about the type to distinguish it.
Discussion
This is often the case in generic methods.
If there are multiple type parameters that denote arbitrary types, one should use letters that neighbor T
in the alphabet, such as S
. 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.
Discussion
If a generic method appears inside a generic class, it's 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.
Discussion
These conventions are illustrated in the code snippets below:
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; }
E, K, T, V, X
) should not be used for type parameters that do not fall into the designated categories.
get
and set
an attribute that might be thought of as a variable V should be named get
V and set
V. An example is the methods getPriority
and setPriority
of class Thread
.
length
, as in class String
.
boolean
condition V about an object should be named is
V. An example is the method isInterrupted
of class Thread
.
to
F. Examples are the method toString
of class Object
and the methods toLocaleString
and toGMTString
of class java.util.Date
.
Method names cannot obscure or be obscured by other names (§6.5.7).
final
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 few public
or protected
fields, except for fields that are constants (final
static
fields) (§6.8.6).Fields should have names that are nouns, noun phrases, or abbreviations for nouns. Examples of this convention are the fields buf
, pos
, and count
of the class java.io.ByteArrayInputStream
and the field bytesTransferred
of the class java.io.InterruptedIOException
.
Obscuring involving field names is rare.
import
declaration (§7.5) can usually be used to make available the type names declared in that package.
final
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 include MIN_VALUE
, MAX_VALUE
, MIN_RADIX
, and MAX_RADIX
of the class Character
.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, as in:
Obscuring involving constant names is rare:interface ProcessStates { int PS_RUNNING = 0; int PS_SUSPENDED = 1; }
cp
for a variable holding a reference to a ColoredPoint
buf
holding a pointer to a buffer
of some kind
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 a byte
c
for a char
d
for a double
e
for an Exception
f
for a float
i
, j
, and k
for integers
l
for a long
o
for an Object
s
for a String
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 (§7.7).
Contents | Prev | Next | Index | Java Language Specification Third Edition |
Copyright © 1996-2005 Sun Microsystems, Inc.
All rights reserved
Please send any comments or corrections via our