Extending the Enum Class

Enum's generic type is Enum<E extends Enum<E>>. Although the formal type parameter list looks ghastly, it is not that hard to understand. But first, take a look at Listing 5-42.

Listing 5-42. The Coin class as it appears from the perspective of its classfile public final class Coin extends Enum<Coin> {

public static final Coin PENNY = new Coin("PENNY", 0);

public static final Coin NICKEL = new Coin("NICKEL", 1);

public static final Coin DIME = new Coin("DIME", 2);

public static final Coin OUARTER = new Coin("0UARTER", 3);

private static final Coin[] $VALUES = { PENNY, NICKEL, DIME, QUARTER };

public static Coin[] values()

return Coin.$VALUES.clone(); public static Coin valueOf(String name)

return Enum.valueOf(Coin.class, "Coin"); private Coin(String name, int ordinal) super(name, ordinal);

Behind the scenes, the compiler converts Listing 5-36's Coin enum declaration into a class declaration that is similar to Listing 5-42.

The following rules show you how to interpret Enum<E extends Enum<E>> in the context of Coin extends Enum<Coin>:

■ Any subclass of Enum must supply an actual type argument to Enum. For example, Coin's header specifies Enum<Coin>.

■ The actual type argument must be a subclass of Enum. For example, Coin is a subclass of Enum.

■ A subclass of Enum (such as Coin) must follow the idiom that it supplies its own name (Coin) as an actual type argument.

The third rule allows Enum to declare methods—compareTo(), getDeclaringClass(), and valueOf() —whose parameter and/or return types are specified in terms of the subclass (Coin), and not in terms of Enum.

The rationale for doing this is to avoid having to specify casts. For example, you do not need to cast valueOf()'s return value to Coin in Coin penny = Enum.valueOf(Coin.class, "PENNY");.

NOTE: You cannot compile Listing 5-42 because the compiler will not compile any class that extends Enum. It will also complain about super(name, ordinal);.


The following exercises are designed to test your understanding of assertions, annotations, generics, and enums:

1. What is an assertion?

2. When would you use assertions?

3. True or false: Specifying the -ea command-line option with no argument enables all assertions, including system assertions.

4. What is an annotation?

5. What kinds of application elements can be annotated?

6. Identify the three compiler-supported annotation types.

7. How do you declare an annotation type?

8. What is a marker annotation?

9. What is an element?

10. How do you assign a default value to an element?

11. What is a meta-annotation?

12. Identify Java's four meta-annotation types.

13. Define generics.

14. Why would you use generics?

15. What is the difference between a generic type and a parameterized type?

16. Which one of the nonstatic member class, local class, and anonymous class inner class categories cannot be generic?

17. Identify the five kinds of actual type arguments.

18. True or false: You cannot specify a primitive type name (such as double or int) as an actual type argument.

20. When does the compiler report an unchecked warning message and why?

21. How do you suppress an unchecked warning message?

22. True or false: List<E>'s E type parameter is unbounded.

23. How do you specify a single upper bound?

24. True or false: MyList<E super Circle> specifies that the E type parameter has a lower bound of Circle.

25. What is a recursive type bound?

26. Why are wildcard type arguments necessary?

27. What is reification?

28. True or false: Type parameters are reified.

29. What is erasure?

30. What is a generic method?

31. In Listing 5-43, which overloaded method does the methodCaller() generic method call?

Listing 5-43. Which someOverloadedMethod() is called? import java.util.Date;

public class CallOverloadedNGMethodFromGMethod {

public static void someOverloadedMethod(Object o)

System.out.println("call to someOverloadedMethod(Object o)"); public static void someOverloadedMethod(Date d)

System.out.println("call to someOverloadedMethod(Date d)"); public static <T> void methodCaller(T t)

someOverloadedMethod(t); public static void main(String[] args)

methodCaller(new Date());

32. What is an enumerated type?

33. Identify three problems that can arise when you use enumerated types whose constants are int-based.

34. What is an enum?

35. How do you use the switch statement with an enum?

36. In what ways can you enhance an enum?

37. What is the purpose of the abstract Enum class?

38. What is the difference between Enum's name() and toString() methods?

39. True or false: Enum's generic type is Enum<E extends Enum<E>>.

40. Declare a ToDo marker annotation type that annotates only type elements, and that also uses the default retention policy.

41. Rewrite the StubFinder application to work with Listing 5-15's Stub annotation type (with appropriate @Target and @Retention annotations) and Listing 5-16's Deck class.

42. Implement a stack in a manner that is similar to Listing 5-24's Oueue class. Stack must be generic, it must declare push(), pop(), and isEmpty() methods (it could also declare an isFull() method but that method is not necessary in this exercise), push() must throw a StackFullException instance when the stack is full, and pop() must throw a StackEmptyException instance when the stack is empty. (You must create your own package-private StackFullException and StackEmptyException helper classes because they are not provided for you in Java's class library.) Declare a similar main() method, and insert two assertions into this method that validate your assumptions about the stack being empty immediately after being created and immediately after popping the last element.

NOTE: A stack is a data structure that stores elements in a last-in, first-out order. Elements are added to the stack via an operation known as push. They are removed from the stack via an operation known as pop. The last element pushed onto the stack is the first element popped off of the stack.

43. Declare a Compass enum with NORTH, SOUTH, EAST, and WEST members. Declare a UseCompass class whose main() method randomly selects one of these constants and then switches on that constant. Each of the switch statement's cases should output a message such as heading north.

Was this article helpful?

0 0

Post a comment