This program has two declarations of the same name in the same
scope and no obvious way to choose between them. Does the program print
Black? Does it print White? Is it even legal?
public class ShadesOfGray { public static void main(String[] args){ System.out.println(X.Y.Z); } } class X { static class Y { static String Z = "Black"; } static C Y = new C(); } class C { String Z = "White"; }
Solution 68: Shades of Gray
There is no
obvious way to decide whether this program should print Black or
White. The compiler generally rejects ambiguous programs, and this one
certainly appears ambiguous. Therefore, it seems only natural that it should be
illegal. If you tried it, you found that it is legal and prints White.
How could you possibly have known?
It turns out that there is a rule that governs program behavior
under these circumstances. When a variable and a type
have the same name and both are in scope, the variable name takes
precedence [JLS 6.5.2]. The variable name is said to obscure the type name [JLS 6.3.2]. Similarly, variable and type names can obscure package
names. This rule is indeed obscure, and any program that depends on it is
likely to confuse its readers.
Fortunately, programs that obey the
standard Java naming conventions almost never encounter this issue.
Classes begin with a capital letter and are written in MixedCase,
variables begin with a lowercase letter and are written in mixedCase,
and constants begin with a capital letter and are written in ALL_CAPS.
Single capital letters are used only for type parameters, as in the generic
interface Map<K, V>. Package names are written in
lower.case [JLS 6.8].
To avoid conflict between constant names and class names, treat
acronyms as ordinary words in class names [EJ Item 38]. For example, a class
representing a universally unique identifier should be named Uuid
rather than UUID, even though the acronym is typically written UUID.
(The Java platform libraries violate this advice with such class names as
UUID, URL, and URI.) To avoid conflicts between
variable names and package names, don't use a top-level package or domain name
as a variable name. Specifically, don't name a variable com,
org, net, edu, java, or javax.
To remove all ambiguity from the ShadesOfGray program,
simply rewrite it to obey the naming conventions. It is clear that the following
program prints Black. As an added bonus, it sounds the same as the
original program when read aloud.
public class ShadesOfGray { public static void main(String[] args){ System.out.println(Ex.Why.z); } } class Ex { static class Why { static String z = "Black"; } static See y = new See(); } class See { String z = "White"; }
In summary, obey the standard naming
conventions to avoid conflicts between different namespaces (and because your
program will be illegible if you violate these conventions). Also, avoid
variable names that conflict with common top-level package names, and use
MixedCase for class names even if they are acronyms. By following these
rules, you'll ensure that your programs never obscure class or package names.
Yet again, this is a case of the general rule that you should avoid name reuse
except for overriding. For language designers, consider eliminating the
possibility of obscuring. C# does this by putting fields and nested classes into
the same name space.
No comments:
Post a Comment
Your comments are welcome!