Use of JCP site is subject to the
JCP Terms of Use and the
Oracle Privacy Policy
|
Importing Static Members in the Javatm Programming LanguageSummaryThe proposal is to introduce variants of the import statement into the JavaTM 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. MotivationThis proposal addresses two problems in current practice. (1) Mathematical functionsFirst 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 constantsIt 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 SyntaxOne 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 ProposalHere 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. |