Let's rewrite the enum code from the preceding example, adding a variable type to the enum Size. The bounded type parameter (<T extends Measurement>) restricts the types that can be passed as arguments to the Size enum, to the Measurement class and its derived classes.
The modified code is as follows:
enum Size <T extends Measurement> { // enum with type parameter SMALL(new Small()), MEDIUM(new Medium()), LARGE(new Large()); private T mObj; Size(T obj) { mObj = obj; } T getMeasurement() { return mObj; } }
class Measurement {} class Small extends Measurement { String text = "Small"; } class Medium extends Measurement {} class Large extends Measurement { public int getLength() { return 40; } }
The following code can be used to access behavior that is specific to a constant, say, the getLength() method, which is accessible only to the LARGE constant, as follows:
var large = Size.LARGE; System.out.println(large.getMeasurement().getLength());
Let's work with another example of a generic enum, which can be used to restrict the user data to certain types.
The following example creates a generic enum, Data, which can be passed as a type parameter, T:
public enum Data<T> { NAME<String>, // constants of generic AGE<Integer>, // enum Data ADDRESS<Address>; }
The FormData class defines a generic method that can accept a constant of the Data enum and a value of the same type that is used for the enum constant:
public class FormData { public <T> void add(Data<T> type, T value) { //..code } }
The following code shows how you can use the constants of the Data enum to restrict the combination of types of values that you pass to the add method:
FormData data = new FormData(); data.add(Data.NAME, "Pavni"); // okay; type of NAME and
// Pavni is String data.add(Data.AGE, 22); // okay; type of AGE and 22 is
// Integer data.add(Data.ADDRESS, "California"); // Won't compile. "California" // is String, not Address
// instance
With the mismatched data, the code fails at compilation, making it easier for the developer to correct it.