Find JSRs
JCP Info
About JCP
Get Involved
Community Resources
Community News
FAQ
Contact Us
staticImport
Importing Static Members in the Javatm Programming Language
Summary
The proposal is to introduce variants of the import statement into the
Java
TM programming language so as to allow importation of static methods
and fields in the manner that classes and interfaces can now be imported.
We propose that a declaration of the form
import static TypeName
. Identifier ;
should import into the current compilation unit the name specified by
the Identifier, which must be a static member of the class or interface
named by TypeName. We also propose that a declaration of the form
import static TypeName
. * ;
should import into the current compilation unit the names of all
static members of the class or interface named by TypeName.
This proposal requires no changes to the JVM; it involves only the
processing of additional forms of import declarations and an extended
interpretation of simple names at compile time.
Motivation
This proposal addresses two problems in current practice.
(1) Mathematical functions
First is the customary notation for mathematical functions such as
"abs" and "sqrt" and "max". In the Java programming language,
when applying such functions to arguments of type float or double,
it is necessary to write
Math.abs(x)
Math.sqrt(x) Math.max(a, b)
where "Math" refers to the class whose full name is "java.lang.Math".
This is undesirably verbose for numerical code compared to what
one can write in languages such as C, Fortran, and Pascal:
abs(x)
sqrt(x) max(a, b)
(2) Named constants
It is desirable in many situations to have a set of named constants
such as
public static final int RED
= 0;
public static final int YELLOW
= 1;
public static final int GREEN
= 2;
for a traffic light, and it is often deemed undesirably verbose simply
to put them in some utility class
TrafficLightand refer to them
always
as
TrafficLight.RED,
TrafficLight.YELLOW, and
TrafficLight.GREEN
;
therefore some programmers have taken to defining such constants in
a utility *interface* and then "importing" such constants into a class
by the strategem of declaring the class to "implement" the (otherwise
vacuous) interface. But, inheriting from an interface to get access
to
constants in an implementation is a publicly visible operation, and is
therefore
subject to all the rules for binary compatibility when modifying the constatnts.
Moreover, it requires all other implementations to inherit the same interface
and the same constants,
even though that other implementation may not require them.
This proposal provides a more straightforward mechanism: define the
constants in a utility class, and then import them:
import static TrafficLight.*;
Another advantage: such a declaration is needed only once per
compilation unit rather than once per class.
Note: assuming the accompanying proposal for enumerations is adopted
public class TrafficLight {
...
public enum
Color {RED, YELLOW, GREEN}
...
}
Then one has the the choices of:
(a) Writing
import mypackage.TrafficLight; and
TrafficLight.Color.RED
.
(b) Writing
import mypackage.TrafficLight.Color; and
Color.RED
.
(c) Writing
import static mypackage.TrafficLight.Color.*; and
RED.
Rationale for Choice of Syntax
One might well ask why the keyword static should appear in the
import declaration, for the compiler can easily
tell what is to be
imported without the presence of that keyword. There are two reasons:
(a) To distinguish visually the importation of members, such as
methods and fields, from the importation of classes and interfaces
(while it easy for the compiler to tell them apart, it is harder
for people, so a redundant visual cue is useful).
(b) To remind the reader (and the programmer) that only static members
can be so imported. (It does not work to try to refer to an instance
member of an arbitrary class by a simple name, because a simple name
fails to supply necessary information as to which instance of the
class is involved.)
Full Proposal
Here we describe the necessary modifications the the Java Language
Specification (JLS), second edition, for this proposal.
Augment the syntax of the import statement (JLS 7.5) to allow two
more possibilities:
ImportDeclaration:
SingleTypeImportDeclaration
TypeImportOnDemandDeclaration
SingleStaticImportDeclaration
StaticImportOnDemandDeclaration
SingleStaticImportDeclaration:
import static TypeName . Identifier ;
StaticImportOnDemandDeclaration:
import static TypeName . * ;
The TypeName must be the canonical name of a class or interface
type;
a compile-time error occurs if the named type does not exist.
The named
type must be accessible or a compile-time error occurs.
For a
single-static-import declaration, the Identifier must name a static
member of the named type; a compile-time error occurs if there
is
no member of that name or if the named member is not accessible.
A single-static-import declaration in compilation unit c of
package p that imports a member named n shadows the declarations
of:
* any top level type named n declared in another compilation unit
of p.
* any type named n imported by a type-import-on-demand declaration
in c.
* any static member named n imported by a static-import-on-demand
declaration
in c.
(The rules for a single-type-import declaration in JLS 7.5.1 must have
a similar third bullet added.)
A static-import-on-demand declaration never causes any other
declaration
to be shadowed.
(These rules also need to be added to JLS 6.3.1.)
If two single-static-import declarations in the same compilation
unit
attempt to import members with the same simple name, then a compile-time
error occurs, unless the two members are the same member of the
same type,
in which case the duplicate declaration is ignored.
If a single-static-import declaration imports a member whose simple
name is n, and the compilation unit also contains a single-type-import
declaration that imports a type whose simple name is n, a compile-time
error occurs. (This error occurs even if both declarations
refer to
the same type, on the grounds that it is confusing to use two
different
mechanisms to redundantly import the same type.)
If a single-static-import declaration imports a member whose simple
name is n, and the compilation unit also declares a top level
type
whose simple name is n, a compile-time error occurs.
Option: We could choose to have another set of automatic imports (JLS
7.5.3) by specifying that each compilation unit, besides automatically
importing all public type names in package java.lang, should also
automatically import all public static members of
java.lang.Math
thereby making
abs sqrt and
PI automatically available in all programs.
The rules in JLS 6.5.2 for classification
of an AmbiguousName that is
a simple name must be augmented. Between the third and fourth
diamond-bulleted subparagraphs, add:
<> Otherwise, if a static member of that
name is declared
in the compilation unit containing
the Identifier by a
single-static-import-declaration,
then the AmbiguousName
is reclassified as a Typename,
a MethodName, or an
Expressionname according to
whether that static member
is a class or interface, a
method, or a field.
Also, the fifth and sixth diamond-bulleted subparagraphs are replaced
by
these three paragraphs:
<> Otherwise, if a type of that name is
declared by exactly one
type-import-on-demand declaration
of the compilation unit
containing the Identifier,
and not by any static-import-on-demand
declaration of the compilation
unit containing the Identifier,
then the AmbiguousName is
reclassified as a TypeName.
<> Otherwise, if a member of that name
is declared by exactly one
static-import-on-demand declaration
of the compilation unit
containing the Identifier,
and not by any type-import-on-demand
declaration of the compilation
unit containing the Identifier,
then the AmbiguousName is
reclassified as a TypeName, a MethodName,
or an Expressionname according
to whether that static member
is a class or interface, a
method, or a field.
<> Otherwise, if a type of that name is
declared by more than one
type-import-on-demand declaration
of the compilation unit
containing the Identifier,
or a member of that name is declared by
more than one static-import-on-demand
declaration of that compilation
unit, or a type of that name
is declared by a type-import-on-demand
declaration of that compilation
unit and a member of that name is
declared
by a static-import-on-demand
declaration of that compilation unit,
then a compile-time error
occurs.
The rules in JLS 6.5.5.1 for the meaning of a simple type name must
be augmented. The fourth bulleted paragraph is replaced by:
* Otherwise, if a type with that name
is declared in the current
compilation unit, either by
a single-type-import declaration,
by a single-static-import
declaration, or by a declaration
of a class or interface type,
then the simple type name denotes
that type.
Also, the sixth and seventh bulleted paragraphs are replaced by these
three paragraphs:
* Otherwise, if a type of that name is
declared by exactly one
type-import-on-demand declaration
of the compilation unit
containing the Identifier,
and not by any static-import-on-demand
declaration of the compilation
unit containing the Identifier,
then the simple type name
denotes that type.
* Otherwise, if a type of that name is
declared by exactly one
static-import-on-demand declaration
of the compilation unit
containing the Identifier,
and not by any type-import-on-demand
declaration of the compilation
unit containing the Identifier,
then the simple type name
denotes that type.
* Otherwise, if a type of that name is
declared by more than one
type-import-on-demand declaration
of the compilation unit
containing the Identifier,
or a member of that name is declared by
more than one static-import-on-demand
declaration of that compilation
unit, or a type of that name
is declared by a type-import-on-demand
declaration of that compilation
unit and a member of that name is
declared
by a static-import-on-demand
declaration of that compilation unit,
then the name is ambiguous
as a type name; a compile-time error occurs.
The rules in JLS 6.5.6.1 for the meaning of a simple expression name
must
be augmented. In the second bulleted paragraph, the second and
third
diamond-bulleted subparagraphs are replaced by these five subparagraphs:
<> Otherwise, if the class has a member
field of that name:
:: If the single member field
of that name is declared final ...
:: Otherwise, the expression
name denotes a variable ...
<> Otherwise, if a field of that name
is declared by exactly one
nonredundant single-static-import
declaration of the compilation unit
containing the Identifier:
:: If the static field of
that name is declared final or the
field is
a member of an interface ...
:: Otherwise, the expression
name denotes a variable ...
<> Otherwise, if a field of that name
is declared by exactly one
static-import-on-demand declaration
of the compilation unit
containing the Identifier:
:: If the static field of
that name is declared final or the
field is
a member of an interface ...
:: Otherwise, the expression
name denotes a variable ...
<> Otherwise, if a field of that name
is declared by more than one
static-import-on-demand declaration
of the compilation unit
containing the Identifier,
then the name is ambiguous as
an expression name; a compile-time
error occurs.
<> Otherwise, the name is undefined as
an expression name;
a compile-time error occurs.
In the third bulleted paragraph, the second diamond-bulleted
subparagraph is replaced by these five subparagraphs:
<> Otherwise, if the interface has a member
field of that name,
the expression name denotes
the value of the member field ...
<> Otherwise, if a field of that name
is declared by exactly one
nonredundant single-static-import
declaration of the compilation unit
containing the Identifier,
the expression name denotes the value
of the member field ...
:: If the static field of
that name is declared final or the
field is
a member of an interface ...
:: Otherwise, the expression
name denotes a variable ...
<> Otherwise, if a field of that name
is declared by exactly one
static-import-on-demand declaration
of the compilation unit
containing the Identifier:
:: If the static field of
that name is declared final or the
field is
a member of an interface ...
:: Otherwise, the expression
name denotes a variable ...
<> Otherwise, if a field of that name
is declared by more than one
static-import-on-demand declaration
of the compilation unit
containing the Identifier,
then the name is ambiguous as
an expression name; a compile-time
error occurs.
<> Otherwise, the name is undefined as
an expression name;
a compile-time error occurs.
The second sentence of JLS section 6.5.7.1 is replaced by:
The Identifier must name either at least one method of a class
or interface
within whose declaration the Identifier appears, or a method imported
by a single-static-import declaration or static-import-on-demand
declaration within the compilation unit within which the Identifier
appears.
JLS section 8.4.6.1 is amended by adding this sentence:
An instance method hides all methods of the same signature that
may be imported by single-static-import and static-import-on-demand
declarations.
JLS section 8.4.6.2 is amended by adding this sentence:
A static method also hides all methods of the same signature
that
may be imported by single-static-import and static-import-on-demand
declarations.
JLS section 15.12.2.1, the paragraph after the two bulleted paragraphs
has a sentence added to it, so that the whole paragraph reads as follows:
The class or interface determined by the process described
in section
15.12.1 is searched for all method declarations applicable to
this
method invocation; method definitions inherited from superclasses
and
superinterfaces are included in this search. In addition,
if the
method invocation has, before the left parenthesis, a MethodName
of
the form Identifier, then the search process also examines all
methods
that are (a) imported by single-static-import declarations and
static-import-on-demand declarations within the compilation unit
within which the method invocation occurs, and (b) not hidden
at the
place where the method invocation appears.
Copyright 2001-2002 Sun Microsystems, Inc., 901 San Antonio
Road, Palo Alto, California 94303 U.S.A. All rights reserved.