This puzzle examines what happens when you attempt to hide a
final field. What does this program do?
class Jeopardy { public static final String PRIZE = "$64,000"; } public class DoubleJeopardy extends Jeopardy { public static final String PRIZE = "2 cents"; public static void main(String[] args) { System.out.println(DoubleJeopardy.PRIZE); } }
Solution 72: Final Jeopardy
Because the
PRIZE field in Jeopardy is declared public and
final, you might think that the language would prevent you from reusing
this field name in a subclass. After all, final methods cannot be overridden or
hidden. If you tried the program, you found that it compiles without a hitch and
prints 2 cents. What went wrong?
It turns out that the final
modifier means something completely different on methods and fields. On a
method, final means that the method may not be overridden (for instance
methods) or hidden (for static methods) [JLS 8.4.3.3]. On a field,
final means the field may not be assigned more than once [JLS 8.3.1.2].
The keyword is the same, but the behavior is unrelated.
In the program, the final field DoubleJeopardy.PRIZE
hides final field Jeopardy.PRIZE, for a net loss of $63,999.98.
Although it is possible to hide fields, it is generally a bad idea. As we
discussed in Puzzle
66, hiding fields can violate subsumption and confound our intuition about
the relationship between types and their members.
If you want to guarantee the prize in the Jeopardy
class even while preserving the ability to subclass it, use a final method
instead of a final field:
class Jeopardy { private static final String PRIZE = "$64,000"; public static final String prize() { return PRIZE; } }
For language designers, the lesson is to avoid reusing the same
keyword for unrelated concepts. A keyword should be reused only for closely
related concepts, where it helps programmers build an intuition about the
relationship among the language features in question. In the case of the Java's
final keyword, reuse leads to confusion. It should be noted that as a
language ages, there is a natural tendency to reuse keywords for unrelated
concepts. This avoids the need to introduce new keywords, which is enormously
destabilizing. When language designers do this, they are generally choosing the
lesser of two evils.
In summary, avoid reusing names for unrelated variables or
unrelated concepts. Using distinct names for unrelated concepts helps readers
and programmers to keep the concepts separate.
No comments:
Post a Comment
Your comments are welcome!