CSCD 211 › lessons

Week 2: enums, built from "what stops a typo from becoming a bad value?"

By the end you can replace a field that should hold one of a fixed set of values with an enum, so an illegal value is a compile error instead of a runtime surprise, and you can give an enum constant its own data and its own behavior. It builds on the class you already write and points straight at the real Course, whose term field is exactly this.

The user story behind this. A department coordinator wants a section to refuse a meeting day that does not exist, so that a typo like Mnday is caught the moment it is typed, not discovered when a student shows up to an empty room. The set of weekdays is fixed and known. The coordinator wants the type system to enforce that, not their own vigilance.

Before you start

The problem (sit with this before reading on)

A Course needs a term. The quickest field type is a String:

private final String term;   // "SUMMER", maybe

Every one of these compiles and runs: "SUMMER", "summer", "Sumemr", "Q3", "". Only one of them is what you meant, and nothing catches the other four until something downstream breaks on a value it does not recognize. The set of real terms is small and fixed, but a String field does not know that.

Check yourself. The term field is a String. In one sentence, why does a typo like "Sumemr" survive all the way to runtime?

Atom 1: an enum is a type with a fixed set of named values

An enum is a class whose instances are a fixed, named set, listed once:

public enum Term {
    FALL, WINTER, SPRING, SUMMER;
}

Now the term field has type Term, and the only values that exist are the four you named. Term.SUMMER is the one way to say summer, and Term.Sumemr is not a typo that slips through, it is a compile error, because there is no such constant. The set is closed, so an illegal value cannot be constructed at all.

Check yourself. With private final Term term, what happens if you write Term.Sumemr, and how is that different from the String version?

Atom 2: each constant is a single shared instance

There is exactly one Term.SUMMER object for the whole program, and every mention of it is that same one instance. This is why == is safe and correct on enum constants, where it was unreliable on strings: term == Term.SUMMER asks the identity question, and for enums identity and value are the same thing, because there is only one of each.

Check yourself. In one sentence, why is term == Term.SUMMER a safe comparison when name == "SUMMER" on a String was not?

Atom 3: a constant can carry its own data

An enum constant can hold state. Give the enum a field and a constructor, and pass each constant its own value in the list:

public enum Term {
    FALL("Fall"), WINTER("Winter"), SPRING("Spring"), SUMMER("Summer");

    private final String label;
    Term(String label) { this.label = label; }
    public String label() { return label; }
}

Now Term.SUMMER.label() returns "Summer", a human-readable name that lives with the constant instead of in a lookup somewhere else. The enum is still a closed set; it just carries a little data on each member.

Check yourself. Term.SUMMER.label() returns "Summer". In one sentence, where does that string live, and why is that better than a separate if that turns SUMMER into "Summer"?

Atom 4: a constant can carry its own behavior

A constant can do more than hold data; it can answer a question differently per constant. A campus rule is the classic case: some campuses require teaching authorization and some do not.

public enum Campus {
    CHENEY    { public boolean requiresAuthorization() { return false; } },
    SPOKANE   { public boolean requiresAuthorization() { return true;  } };

    public abstract boolean requiresAuthorization();
}

Each constant gives its own answer, so the rule lives on the constant instead of in a long if that has to name every campus. Add a campus and the compiler makes you give its answer, because the method is abstract. This is the reason to reach for an enum over constants of a plain type: the behavior travels with the value.

Check yourself (competency close). Finish in your own words: "An enum is a type with , so a typo becomes a ___ instead of a . Putting data and behavior on a constant means the rule lives ___ instead of in ___."

What you collected

Where this is going

You can now hold one of a fixed set safely. Next is the other side of holding values: a growable list of many of them, the ArrayList the library gives you, and the List interface it implements. That is the last Week 2 lesson.