Declaring enums:
Using enums can help reduce the bugs in your code. Using enums can help reduce the bugs in your code. For instance, in your coffee shop application you might want to restrict your CoffeeSize selections to BIG,
HUGE, and OVERWHELMING. If you let an order for a LARGE or a GRANDE slip in, itmight cause an error. enums to the rescue. With the following simple declaration,
you can guarantee that the compiler will stop you from assigning anything to a
CoffeeSize except BIG, HUGE, or OVERWHELMING:
enum CoffeeSize { BIG, HUGE, OVERWHELMING };
From then on, the only way to get a CoffeeSize will be with a statement
something like this:
CoffeeSize cs = CoffeeSize.BIG;
The basic components of an enum are its constants (that is, BIG, HUGE, and OVERWHELMING), although in a minute you'll see that there can be a lot more to an
enum. enums can be declared as their own separate class or as a class member; however, they must not be declared within a method!
Here's an example declaring an enum outside a class:
enum. enums can be declared as their own separate class or as a class member; however, they must not be declared within a method!
Here's an example declaring an enum outside a class:
enum CoffeeSize { BIG, HUGE, OVERWHELMING } // this cannot be
// private or protected
class Coffee {
CoffeeSize size;
}
public class CoffeeTest1 {
public static void main(String[] args) {
Coffee drink = new Coffee();
drink.size = CoffeeSize.BIG; // enum outside class
}
}
Coffee drink = new Coffee();
drink.size = CoffeeSize.BIG; // enum outside class
}
}
The key point to remember is that an enum that isn't enclosed in a class can be
declared with only the public or default modifier, just like a non-inner class. Here's
an example of declaring an enum inside a class:
class Coffee2 {
enum CoffeeSize {BIG, HUGE, OVERWHELMING }
CoffeeSize size;
}
public class CoffeeTest2 {
public static void main(String[] args) {
Coffee2 drink = new Coffee2();
drink.size = Coffee2.CoffeeSize.BIG; // enclosing class
// name required
}
}
an example of declaring an enum inside a class:
class Coffee2 {
enum CoffeeSize {BIG, HUGE, OVERWHELMING }
CoffeeSize size;
}
public class CoffeeTest2 {
public static void main(String[] args) {
Coffee2 drink = new Coffee2();
drink.size = Coffee2.CoffeeSize.BIG; // enclosing class
// name required
}
}
The key points to take away from these examples are that enums can be declared
as their own class or enclosed in another class, and that the syntax for accessing an
enum's members depends on where the enum was declared.
The following is NOT legal:
public class CoffeeTest1 {
public static void main(String[] args) {
enum CoffeeSize { BIG, HUGE, OVERWHELMING } // WRONG! Cannot
// declare enums
// in methods
Coffee drink = new Coffee();
drink.size = CoffeeSize.BIG;
}
}
as their own class or enclosed in another class, and that the syntax for accessing an
enum's members depends on where the enum was declared.
The following is NOT legal:
public class CoffeeTest1 {
public static void main(String[] args) {
enum CoffeeSize { BIG, HUGE, OVERWHELMING } // WRONG! Cannot
// declare enums
// in methods
Coffee drink = new Coffee();
drink.size = CoffeeSize.BIG;
}
}
To make it more confusing for you, the Java language designers made it optional
to put a semicolon at the end of the enum declaration (when no other declarations
for this enum follow):
public class CoffeeTest1 {
enum CoffeeSize { BIG, HUGE, OVERWHELMING }; // <--semicolon
// is optional here
public static void main(String[] args) {
Coffee drink = new Coffee();
drink.size = CoffeeSize.BIG;
}
}
So what gets created when you make an enum? The most important thing to remember is that enums are not Strings or ints! Each of the enumerated CoffeeSize types is actually an instance of CoffeeSize. In other words, BIG is of type CoffeeSize. Think of an enum as a kind of class that looks something (but not exactly) like this:
to put a semicolon at the end of the enum declaration (when no other declarations
for this enum follow):
public class CoffeeTest1 {
enum CoffeeSize { BIG, HUGE, OVERWHELMING }; // <--semicolon
// is optional here
public static void main(String[] args) {
Coffee drink = new Coffee();
drink.size = CoffeeSize.BIG;
}
}
So what gets created when you make an enum? The most important thing to remember is that enums are not Strings or ints! Each of the enumerated CoffeeSize types is actually an instance of CoffeeSize. In other words, BIG is of type CoffeeSize. Think of an enum as a kind of class that looks something (but not exactly) like this:
Declare and Use enums (OCA Objective 1.2 and OCP Objective 2.5) 63
// conceptual example of how you can think
// about enums
class CoffeeSize {
public static final CoffeeSize BIG =
new CoffeeSize("BIG", 0);
public static final CoffeeSize HUGE =
new CoffeeSize("HUGE", 1);
public static final CoffeeSize OVERWHELMING =
new CoffeeSize("OVERWHELMING", 2);
CoffeeSize(String enumName, int index) {
// stuff here
}
public static void main(String[] args) {
System.out.println(CoffeeSize.BIG);
}
}
// conceptual example of how you can think
// about enums
class CoffeeSize {
public static final CoffeeSize BIG =
new CoffeeSize("BIG", 0);
public static final CoffeeSize HUGE =
new CoffeeSize("HUGE", 1);
public static final CoffeeSize OVERWHELMING =
new CoffeeSize("OVERWHELMING", 2);
CoffeeSize(String enumName, int index) {
// stuff here
}
public static void main(String[] args) {
System.out.println(CoffeeSize.BIG);
}
}
Declaring Constructors, Methods, and Variables in an enum
Because an enum really is a special kind of class, you can do more than just list the
enumerated constant values. You can add constructors, instance variables, methods,
and something really strange known as a constant specific class body.
enumerated constant values. You can add constructors, instance variables, methods,
and something really strange known as a constant specific class body.
enum CoffeeSize {
// 8, 10 & 16 are passed to the constructor
BIG(8), HUGE(10), OVERWHELMING(16);
CoffeeSize(int ounces) { // constructor
this.ounces = ounces;
}
private int ounces; // an instance variable
public int getOunces() {
return ounces;
}
}
class Coffee {
CoffeeSize size; // each instance of Coffee has an enum
public static void main(String[] args) {
Coffee drink1 = new Coffee();
drink1.size = CoffeeSize.BIG;
Coffee drink2 = new Coffee();
drink2.size = CoffeeSize.OVERWHELMING;
System.out.println(drink1.size.getOunces()); // prints 8
for(CoffeeSize cs: CoffeeSize.values())
System.out.println(cs + " " + cs.getOunces());
}
}
which produces:
8
BIG 8
HUGE 10
OVERWHELMING 16
// 8, 10 & 16 are passed to the constructor
BIG(8), HUGE(10), OVERWHELMING(16);
CoffeeSize(int ounces) { // constructor
this.ounces = ounces;
}
private int ounces; // an instance variable
public int getOunces() {
return ounces;
}
}
class Coffee {
CoffeeSize size; // each instance of Coffee has an enum
public static void main(String[] args) {
Coffee drink1 = new Coffee();
drink1.size = CoffeeSize.BIG;
Coffee drink2 = new Coffee();
drink2.size = CoffeeSize.OVERWHELMING;
System.out.println(drink1.size.getOunces()); // prints 8
for(CoffeeSize cs: CoffeeSize.values())
System.out.println(cs + " " + cs.getOunces());
}
}
which produces:
8
BIG 8
HUGE 10
OVERWHELMING 16
Note: Every enum has a static method, values(), that returns an array of the
enum's values in the order they're declared.
enum's values in the order they're declared.
■ You can NEVER invoke an enum constructor directly. The enum constructor
is invoked automatically, with the arguments you define after the constant
value. For example, BIG(8) invokes the CoffeeSize constructor that takes
an int, passing the int literal 8 to the constructor. (Behind the scenes, of
course, you can imagine that BIG is also passed to the constructor, but we
don't have to know—or care—about the details.)
is invoked automatically, with the arguments you define after the constant
value. For example, BIG(8) invokes the CoffeeSize constructor that takes
an int, passing the int literal 8 to the constructor. (Behind the scenes, of
course, you can imagine that BIG is also passed to the constructor, but we
don't have to know—or care—about the details.)
■ You can define more than one argument to the constructor, and you can
overload the enum constructors, just as you can overload a normal class constructor. We discuss constructors in much more detail in Chapter 2.
type, you'd pass two arguments to the constructor as BIG(8, "A"), which
means you have a constructor in CoffeeSize that takes both an int and
a String.
Imagine this scenario: You want enums to have two methods—one for ounces and
one for lid code (a String). Now imagine that most coffee sizes use the same lid
code, "B", but the OVERWHELMING size uses type "A". You can define a getLidCode()
method in the CoffeeSize enum that returns "B", but then you need a way to
override it for OVERWHELMING. You don't want to do some hard-to-maintain if/then
code in the getLidCode() method, so the best approach might be to somehow have
the OVERWHELMING constant override the getLidCode() method.
one for lid code (a String). Now imagine that most coffee sizes use the same lid
code, "B", but the OVERWHELMING size uses type "A". You can define a getLidCode()
method in the CoffeeSize enum that returns "B", but then you need a way to
override it for OVERWHELMING. You don't want to do some hard-to-maintain if/then
code in the getLidCode() method, so the best approach might be to somehow have
the OVERWHELMING constant override the getLidCode() method.
This looks strange, but you need to understand the basic declaration rules:
enum CoffeeSize {
BIG(8),
HUGE(10),
OVERWHELMING(16) { // start a code block that defines
// the "body" for this constant
public String getLidCode() { // override the method
// defined in CoffeeSize
return "A";
}
}; // the semicolon is REQUIRED when more code follows
CoffeeSize(int ounces) {
this.ounces = ounces;
}
private int ounces;
public int getOunces() {
return ounces;
}
public String getLidCode() { // this method is overridden
// by the OVERWHELMING constant
return "B"; // the default value we want to
// return for CoffeeSize constants
}
}
enum CoffeeSize {
BIG(8),
HUGE(10),
OVERWHELMING(16) { // start a code block that defines
// the "body" for this constant
public String getLidCode() { // override the method
// defined in CoffeeSize
return "A";
}
}; // the semicolon is REQUIRED when more code follows
CoffeeSize(int ounces) {
this.ounces = ounces;
}
private int ounces;
public int getOunces() {
return ounces;
}
public String getLidCode() { // this method is overridden
// by the OVERWHELMING constant
return "B"; // the default value we want to
// return for CoffeeSize constants
}
}
No comments:
Post a Comment