Download a PDF of this article
More quiz questions available here
Given an interface and two enums
interface Emoticonable {
public String getIcon();
}
enum Mood implements Emoticonable {
GOOD { public String getIcon() { return ";-)"; } },
BAD { public String getIcon() { return ";-("; } };
public String toString() { return getIcon(); }
}
enum Emotion implements Emoticonable {
LAUGHING { public String toString() { return getIcon(); }},
CRYING { public String getIcon() { return ";'-("; } };
public String getIcon() { return ";-|"; }
}
and this code fragment
System.out.println("Good mood, laughing " + Mood.GOOD + " " + Emotion.LAUGHING);
Which is true? Choose one.
A. | Both enum types fail to compile. | |
B. | The Emotion enum fails to compile. |
|
C. | The output is the following:Good mood, laughing ;-) ;-| |
|
D. | The output is the following:Good mood, laughing GOOD LAUGHING |
Answer. This question investigates enums and the implementation of interfaces.
The syntax used here for enumeration types is not seen as frequently as other syntaxes. However, it is a valid syntax.
An enum type declaration cannot use an extends
clause (because these declarations implicitly extend java.lang.Enum
), but implementing interfaces is completely valid. Of course, an enum that does so must properly implement the abstract
methods declared by the interface, as would any other concrete class.
By the way, an enum cannot be abstract—this wouldn’t make much sense since its role is to enumerate actual values of the type. Therefore, an enum cannot be subclassed using the extends
syntax.
In the syntax used for this question, the enum values are followed by curly braces. Even though an enum cannot use or be the target of the extends
clause, it is possible—in specific and limited situations—to have an enum that is a subclass of another enum.
As you might have guessed from this preamble, following an enum value (sometimes referred to as the constant) with curly braces is exactly that situation. What happens here is that each value declared like this actually becomes an instance of a subclass of the enclosing enum type, and the contents of the curly braces define members (such as fields and methods) in that subclass.
Of course, where you have subclassing and method definitions, you expect to find method overriding, and that is true here. If one of these values has a class body that declares a method that exists in the enclosing enum (remember, the enclosing enum is also the parent class in this situation), then the value’s method is an override of the original. As with other overriding methods, the overriding method can invoke the overridden method using super
. You can see part of this in the definition of LAUGHING
, which overrides toString
although it does not use super
to do any delegation.
When using these syntaxes together, it’s necessary for every instance value of the enum to implement all the abstract
methods declared in any interfaces implemented by the outer enum. This can be done by implementing the methods in the outer enum, or in every single instance, or a combination. As long as an implementation is available for every instance, things work out just fine. Notice that in the question code, GOOD
, BAD
, and CRYING
all implement getIcon
directly, while LAUGHING
simply inherits the implementation from the enclosing Emotion
type.
Because all of the enum values—GOOD
, BAD
, LAUGHING
, and CRYING
—have an implementation of getIcon()
, the code is correct and can be compiled. This makes options A and B incorrect.
The default behavior for toString
in an enum type is identical to the final
method name()
. That is, it prints the constant name (such as GOOD
or BAD
). However, for Mood
the toString()
is overridden at the global scope, and for LAUGHING
the method is overridden specifically for that instance.
In this question, the code prints the text representation of the two values: Mood.GOOD
and Emotion.LAUGHING
. The Mood
enum has a toString
that delegates to the getIcon
method, which in the case of the GOOD
instance is overridden to return the text ;-)
.
The LAUGHING
instance overrides toString
to delegate to getIcon
, and in this case, that invokes the getIcon
method of the enclosing Emotion
enum. The result of this is the text ;-|
. Knowing that, it’s clear the output will be
Good mood, laughing ;-) ;-|
This makes option C correct and option D incorrect.
As a side note, observe that the toString
method of Emotion.CRYING
is not overridden anywhere. Therefore, if you were to run
System.out.println("Good mood, crying " + Mood.GOOD + " " + Emotion.CRYING);
The output would be the following, where the toString
default behavior is used to convert Emotion.CRYING
to text:
Good mood, crying ;-) CRYING
Conclusion. The correct answer is option C.
Simon Roberts joined Sun Microsystems in time to teach Sun’s first Java classes in the UK. He created the Sun Certified Java Programmer and Sun Certified Java Developer exams. He wrote several Java certification guides and is currently a freelance educator who publishes recorded and live video training through Pearson InformIT (available direct and through the O’Reilly Safari Books Online service). He remains involved with Oracle’s Java certification projects.
Mikalai Zaikin is a lead Java developer at IBA Lithuania (part of worldwide IBA Group) and currently located in Vilnius. During his career, Zaikin has helped Oracle with development of Java certification exams, and he has been a technical reviewer of several Java certification books, including three editions of the famous Sun Certified Programmer for Java study guides by Kathy Sierra and Bert Bates.
Previous Post
Next Post