This commit is contained in:
Bruce Eckel 2015-05-31 10:58:40 -07:00
parent 19bee902e0
commit 186333e022
39 changed files with 1427 additions and 0 deletions

7
enums/AlarmPoints.java Normal file
View File

@ -0,0 +1,7 @@
//: enums/AlarmPoints.java
// ©2015 MindView LLC: see Copyright.txt
package enums;
public enum AlarmPoints {
STAIR1, STAIR2, LOBBY, OFFICE1, OFFICE2, OFFICE3,
OFFICE4, BATHROOM, UTILITY, KITCHEN
} ///:~

19
enums/BigEnumSet.java Normal file
View File

@ -0,0 +1,19 @@
//: enums/BigEnumSet.java
// ©2015 MindView LLC: see Copyright.txt
import java.util.*;
public class BigEnumSet {
enum Big { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10,
A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21,
A22, A23, A24, A25, A26, A27, A28, A29, A30, A31, A32,
A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43,
A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54,
A55, A56, A57, A58, A59, A60, A61, A62, A63, A64, A65,
A66, A67, A68, A69, A70, A71, A72, A73, A74, A75 }
public static void main(String[] args) {
EnumSet<Big> bigEnumSet = EnumSet.allOf(Big.class);
System.out.println(bigEnumSet);
}
} /* Output:
[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, A70, A71, A72, A73, A74, A75]
*///:~

20
enums/Burrito.java Normal file
View File

@ -0,0 +1,20 @@
//: enums/Burrito.java
// ©2015 MindView LLC: see Copyright.txt
package enums;
import static enums.Spiciness.*;
public class Burrito {
Spiciness degree;
public Burrito(Spiciness degree) { this.degree = degree;}
@Override
public String toString() { return "Burrito is "+ degree;}
public static void main(String[] args) {
System.out.println(new Burrito(NOT));
System.out.println(new Burrito(MEDIUM));
System.out.println(new Burrito(HOT));
}
} /* Output:
Burrito is NOT
Burrito is MEDIUM
Burrito is HOT
*///:~

68
enums/CarWash.java Normal file
View File

@ -0,0 +1,68 @@
//: enums/CarWash.java
// ©2015 MindView LLC: see Copyright.txt
import java.util.*;
import static net.mindview.util.Print.*;
public class CarWash {
public enum Cycle {
UNDERBODY {
@Override
void action() { print("Spraying the underbody"); }
},
WHEELWASH {
@Override
void action() { print("Washing the wheels"); }
},
PREWASH {
@Override
void action() { print("Loosening the dirt"); }
},
BASIC {
@Override
void action() { print("The basic wash"); }
},
HOTWAX {
@Override
void action() { print("Applying hot wax"); }
},
RINSE {
@Override
void action() { print("Rinsing"); }
},
BLOWDRY {
@Override
void action() { print("Blowing dry"); }
};
abstract void action();
}
EnumSet<Cycle> cycles =
EnumSet.of(Cycle.BASIC, Cycle.RINSE);
public void add(Cycle cycle) { cycles.add(cycle); }
public void washCar() {
for(Cycle c : cycles)
c.action();
}
@Override
public String toString() { return cycles.toString(); }
public static void main(String[] args) {
CarWash wash = new CarWash();
print(wash);
wash.washCar();
// Order of addition is unimportant:
wash.add(Cycle.BLOWDRY);
wash.add(Cycle.BLOWDRY); // Duplicates ignored
wash.add(Cycle.RINSE);
wash.add(Cycle.HOTWAX);
print(wash);
wash.washCar();
}
} /* Output:
[BASIC, RINSE]
The basic wash
Rinsing
[BASIC, HOTWAX, RINSE, BLOWDRY]
The basic wash
Applying hot wax
Rinsing
Blowing dry
*///:~

8
enums/Competitor.java Normal file
View File

@ -0,0 +1,8 @@
//: enums/Competitor.java
// ©2015 MindView LLC: see Copyright.txt
// Switching one enum on another.
package enums;
public interface Competitor<T extends Competitor<T>> {
Outcome compete(T competitor);
} ///:~

View File

@ -0,0 +1,31 @@
//: enums/ConstantSpecificMethod.java
// ©2015 MindView LLC: see Copyright.txt
import java.util.*;
import java.text.*;
public enum ConstantSpecificMethod {
DATE_TIME {
@Override
String getInfo() {
return
DateFormat.getDateInstance().format(new Date());
}
},
CLASSPATH {
@Override
String getInfo() {
return System.getenv("CLASSPATH");
}
},
VERSION {
@Override
String getInfo() {
return System.getProperty("java.version");
}
};
abstract String getInfo();
public static void main(String[] args) {
for(ConstantSpecificMethod csm : values())
System.out.println(csm.getInfo());
}
} /* (Execute to see output) *///:~

44
enums/EnumClass.java Normal file
View File

@ -0,0 +1,44 @@
//: enums/EnumClass.java
// ©2015 MindView LLC: see Copyright.txt
// Capabilities of the Enum class
import static net.mindview.util.Print.*;
enum Shrubbery { GROUND, CRAWLING, HANGING }
public class EnumClass {
public static void main(String[] args) {
for(Shrubbery s : Shrubbery.values()) {
print(s + " ordinal: " + s.ordinal());
printnb(s.compareTo(Shrubbery.CRAWLING) + " ");
printnb(s.equals(Shrubbery.CRAWLING) + " ");
print(s == Shrubbery.CRAWLING);
print(s.getDeclaringClass());
print(s.name());
print("----------------------");
}
// Produce an enum value from a string name:
for(String s : "HANGING CRAWLING GROUND".split(" ")) {
Shrubbery shrub = Enum.valueOf(Shrubbery.class, s);
print(shrub);
}
}
} /* Output:
GROUND ordinal: 0
-1 false false
class Shrubbery
GROUND
----------------------
CRAWLING ordinal: 1
0 true true
class Shrubbery
CRAWLING
----------------------
HANGING ordinal: 2
1 false false
class Shrubbery
HANGING
----------------------
HANGING
CRAWLING
GROUND
*///:~

31
enums/EnumMaps.java Normal file
View File

@ -0,0 +1,31 @@
//: enums/EnumMaps.java
// ©2015 MindView LLC: see Copyright.txt
// Basics of EnumMaps.
package enums;
import java.util.*;
import static enums.AlarmPoints.*;
import static net.mindview.util.Print.*;
interface Command { void action(); }
public class EnumMaps {
public static void main(String[] args) {
EnumMap<AlarmPoints,Command> em =
new EnumMap<>(AlarmPoints.class);
em.put(KITCHEN, () -> print("Kitchen fire!"));
em.put(BATHROOM, () -> print("Bathroom alert!"));
for(Map.Entry<AlarmPoints,Command> e : em.entrySet()) {
printnb(e.getKey() + ": ");
e.getValue().action();
}
try { // If there's no value for a particular key:
em.get(UTILITY).action();
} catch(Exception e) {
print("Expected: " + e);
}
}
} /* Output:
BATHROOM: Bathroom alert!
KITCHEN: Kitchen fire!
Expected: java.lang.NullPointerException
*///:~

31
enums/EnumSets.java Normal file
View File

@ -0,0 +1,31 @@
//: enums/EnumSets.java
// ©2015 MindView LLC: see Copyright.txt
// Operations on EnumSets
package enums;
import java.util.*;
import static enums.AlarmPoints.*;
import static net.mindview.util.Print.*;
public class EnumSets {
public static void main(String[] args) {
EnumSet<AlarmPoints> points =
EnumSet.noneOf(AlarmPoints.class); // Empty set
points.add(BATHROOM);
print(points);
points.addAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
print(points);
points = EnumSet.allOf(AlarmPoints.class);
points.removeAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
print(points);
points.removeAll(EnumSet.range(OFFICE1, OFFICE4));
print(points);
points = EnumSet.complementOf(points);
print(points);
}
} /* Output:
[BATHROOM]
[STAIR1, STAIR2, BATHROOM, KITCHEN]
[LOBBY, OFFICE1, OFFICE2, OFFICE3, OFFICE4, BATHROOM, UTILITY]
[LOBBY, BATHROOM, UTILITY]
[STAIR1, STAIR2, OFFICE1, OFFICE2, OFFICE3, OFFICE4, KITCHEN]
*///:~

29
enums/Input.java Normal file
View File

@ -0,0 +1,29 @@
//: enums/Input.java
// ©2015 MindView LLC: see Copyright.txt
import java.util.*;
public enum Input {
NICKEL(5), DIME(10), QUARTER(25), DOLLAR(100),
TOOTHPASTE(200), CHIPS(75), SODA(100), SOAP(50),
ABORT_TRANSACTION {
@Override
public int amount() { // Disallow
throw new RuntimeException("ABORT.amount()");
}
},
STOP { // This must be the last instance.
@Override
public int amount() { // Disallow
throw new RuntimeException("SHUT_DOWN.amount()");
}
};
int value; // In cents
Input(int value) { this.value = value; }
Input() {}
int amount() { return value; }; // In cents
static Random rand = new Random(47);
public static Input randomSelection() {
// Don't include STOP:
return values()[rand.nextInt(values().length - 1)];
}
} ///:~

16
enums/NonEnum.java Normal file
View File

@ -0,0 +1,16 @@
//: enums/NonEnum.java
// ©2015 MindView LLC: see Copyright.txt
public class NonEnum {
public static void main(String[] args) {
Class<Integer> intClass = Integer.class;
try {
for(Object en : intClass.getEnumConstants())
System.out.println(en);
} catch(Exception e) {
System.out.println("Expected: " + e);
}
}
} /* Output:
Expected: java.lang.NullPointerException
*///:~

27
enums/NotClasses.java Normal file
View File

@ -0,0 +1,27 @@
//: enums/NotClasses.java
// ©2015 MindView LLC: see Copyright.txt
// {Exec: javap -c LikeClasses}
import static net.mindview.util.Print.*;
enum LikeClasses {
WINKEN {@Override
void behavior() { print("Behavior1"); } },
BLINKEN {@Override
void behavior() { print("Behavior2"); } },
NOD {@Override
void behavior() { print("Behavior3"); } };
abstract void behavior();
}
public class NotClasses {
// void f1(LikeClasses.WINKEN instance) {} // Nope
} /* Output: (First 7 Lines)
Compiled from "NotClasses.java"
abstract class LikeClasses extends java.lang.Enum{
public static final LikeClasses WINKEN;
public static final LikeClasses BLINKEN;
public static final LikeClasses NOD;
...
*///:~

4
enums/Outcome.java Normal file
View File

@ -0,0 +1,4 @@
//: enums/Outcome.java
// ©2015 MindView LLC: see Copyright.txt
package enums;
public enum Outcome { WIN, LOSE, DRAW } ///:~

View File

@ -0,0 +1,22 @@
//: enums/OverrideConstantSpecific.java
// ©2015 MindView LLC: see Copyright.txt
import static net.mindview.util.Print.*;
public enum OverrideConstantSpecific {
NUT, BOLT,
WASHER {
@Override
void f() { print("Overridden method"); }
};
void f() { print("default behavior"); }
public static void main(String[] args) {
for(OverrideConstantSpecific ocs : values()) {
printnb(ocs + ": ");
ocs.f();
}
}
} /* Output:
NUT: default behavior
BOLT: default behavior
WASHER: Overridden method
*///:~

28
enums/OzWitch.java Normal file
View File

@ -0,0 +1,28 @@
//: enums/OzWitch.java
// ©2015 MindView LLC: see Copyright.txt
// The witches in the land of Oz.
import static net.mindview.util.Print.*;
public enum OzWitch {
// Instances must be defined first, before methods:
WEST("Miss Gulch, aka the Wicked Witch of the West"),
NORTH("Glinda, the Good Witch of the North"),
EAST("Wicked Witch of the East, wearer of the Ruby " +
"Slippers, crushed by Dorothy's house"),
SOUTH("Good by inference, but missing");
private String description;
// Constructor must be package or private access:
private OzWitch(String description) {
this.description = description;
}
public String getDescription() { return description; }
public static void main(String[] args) {
for(OzWitch witch : OzWitch.values())
print(witch + ": " + witch.getDescription());
}
} /* Output:
WEST: Miss Gulch, aka the Wicked Witch of the West
NORTH: Glinda, the Good Witch of the North
EAST: Wicked Witch of the East, wearer of the Ruby Slippers, crushed by Dorothy's house
SOUTH: Good by inference, but missing
*///:~

162
enums/PostOffice.java Normal file
View File

@ -0,0 +1,162 @@
//: enums/PostOffice.java
// ©2015 MindView LLC: see Copyright.txt
// Modeling a post office.
import java.util.*;
import net.mindview.util.*;
import static net.mindview.util.Print.*;
class Mail {
// The NO's lower the probability of random selection:
enum GeneralDelivery {YES,NO1,NO2,NO3,NO4,NO5}
enum Scannability {UNSCANNABLE,YES1,YES2,YES3,YES4}
enum Readability {ILLEGIBLE,YES1,YES2,YES3,YES4}
enum Address {INCORRECT,OK1,OK2,OK3,OK4,OK5,OK6}
enum ReturnAddress {MISSING,OK1,OK2,OK3,OK4,OK5}
GeneralDelivery generalDelivery;
Scannability scannability;
Readability readability;
Address address;
ReturnAddress returnAddress;
static long counter = 0;
long id = counter++;
@Override
public String toString() { return "Mail " + id; }
public String details() {
return toString() +
", General Delivery: " + generalDelivery +
", Address Scanability: " + scannability +
", Address Readability: " + readability +
", Address Address: " + address +
", Return address: " + returnAddress;
}
// Generate test Mail:
public static Mail randomMail() {
Mail m = new Mail();
m.generalDelivery= Enums.random(GeneralDelivery.class);
m.scannability = Enums.random(Scannability.class);
m.readability = Enums.random(Readability.class);
m.address = Enums.random(Address.class);
m.returnAddress = Enums.random(ReturnAddress.class);
return m;
}
public static Iterable<Mail> generator(final int count) {
return new Iterable<Mail>() {
int n = count;
@Override
public Iterator<Mail> iterator() {
return new Iterator<Mail>() {
@Override
public boolean hasNext() { return n-- > 0; }
@Override
public Mail next() { return randomMail(); }
@Override
public void remove() { // Not implemented
throw new UnsupportedOperationException();
}
};
}
};
}
}
public class PostOffice {
enum MailHandler {
GENERAL_DELIVERY {
@Override
boolean handle(Mail m) {
switch(m.generalDelivery) {
case YES:
print("Using general delivery for " + m);
return true;
default: return false;
}
}
},
MACHINE_SCAN {
@Override
boolean handle(Mail m) {
switch(m.scannability) {
case UNSCANNABLE: return false;
default:
switch(m.address) {
case INCORRECT: return false;
default:
print("Delivering "+ m + " automatically");
return true;
}
}
}
},
VISUAL_INSPECTION {
@Override
boolean handle(Mail m) {
switch(m.readability) {
case ILLEGIBLE: return false;
default:
switch(m.address) {
case INCORRECT: return false;
default:
print("Delivering " + m + " normally");
return true;
}
}
}
},
RETURN_TO_SENDER {
@Override
boolean handle(Mail m) {
switch(m.returnAddress) {
case MISSING: return false;
default:
print("Returning " + m + " to sender");
return true;
}
}
};
abstract boolean handle(Mail m);
}
static void handle(Mail m) {
for(MailHandler handler : MailHandler.values())
if(handler.handle(m))
return;
print(m + " is a dead letter");
}
public static void main(String[] args) {
for(Mail mail : Mail.generator(10)) {
print(mail.details());
handle(mail);
print("*****");
}
}
} /* Output:
Mail 0, General Delivery: NO2, Address Scanability: UNSCANNABLE, Address Readability: YES3, Address Address: OK1, Return address: OK1
Delivering Mail 0 normally
*****
Mail 1, General Delivery: NO5, Address Scanability: YES3, Address Readability: ILLEGIBLE, Address Address: OK5, Return address: OK1
Delivering Mail 1 automatically
*****
Mail 2, General Delivery: YES, Address Scanability: YES3, Address Readability: YES1, Address Address: OK1, Return address: OK5
Using general delivery for Mail 2
*****
Mail 3, General Delivery: NO4, Address Scanability: YES3, Address Readability: YES1, Address Address: INCORRECT, Return address: OK4
Returning Mail 3 to sender
*****
Mail 4, General Delivery: NO4, Address Scanability: UNSCANNABLE, Address Readability: YES1, Address Address: INCORRECT, Return address: OK2
Returning Mail 4 to sender
*****
Mail 5, General Delivery: NO3, Address Scanability: YES1, Address Readability: ILLEGIBLE, Address Address: OK4, Return address: OK2
Delivering Mail 5 automatically
*****
Mail 6, General Delivery: YES, Address Scanability: YES4, Address Readability: ILLEGIBLE, Address Address: OK4, Return address: OK4
Using general delivery for Mail 6
*****
Mail 7, General Delivery: YES, Address Scanability: YES3, Address Readability: YES4, Address Address: OK2, Return address: MISSING
Using general delivery for Mail 7
*****
Mail 8, General Delivery: NO3, Address Scanability: YES1, Address Readability: YES3, Address Address: INCORRECT, Return address: MISSING
Mail 8 is a dead letter
*****
Mail 9, General Delivery: NO1, Address Scanability: UNSCANNABLE, Address Readability: YES2, Address Address: OK1, Return address: OK4
Delivering Mail 9 normally
*****
*///:~

15
enums/RandomTest.java Normal file
View File

@ -0,0 +1,15 @@
//: enums/RandomTest.java
// ©2015 MindView LLC: see Copyright.txt
import net.mindview.util.*;
enum Activity { SITTING, LYING, STANDING, HOPPING,
RUNNING, DODGING, JUMPING, FALLING, FLYING }
public class RandomTest {
public static void main(String[] args) {
for(int i = 0; i < 20; i++)
System.out.print(Enums.random(Activity.class) + " ");
}
} /* Output:
STANDING FLYING RUNNING STANDING RUNNING STANDING LYING DODGING SITTING RUNNING HOPPING HOPPING HOPPING RUNNING STANDING LYING FALLING RUNNING FLYING LYING
*///:~

59
enums/Reflection.java Normal file
View File

@ -0,0 +1,59 @@
//: enums/Reflection.java
// ©2015 MindView LLC: see Copyright.txt
// Analyzing enums using reflection.
import java.lang.reflect.*;
import java.util.*;
import net.mindview.util.*;
import static net.mindview.util.Print.*;
enum Explore { HERE, THERE }
public class Reflection {
public static Set<String> analyze(Class<?> enumClass) {
print("----- Analyzing " + enumClass + " -----");
print("Interfaces:");
for(Type t : enumClass.getGenericInterfaces())
print(t);
print("Base: " + enumClass.getSuperclass());
print("Methods: ");
Set<String> methods = new TreeSet<>();
for(Method m : enumClass.getMethods())
methods.add(m.getName());
print(methods);
return methods;
}
public static void main(String[] args) {
Set<String> exploreMethods = analyze(Explore.class);
Set<String> enumMethods = analyze(Enum.class);
print("Explore.containsAll(Enum)? " +
exploreMethods.containsAll(enumMethods));
printnb("Explore.removeAll(Enum): ");
exploreMethods.removeAll(enumMethods);
print(exploreMethods);
// Decompile the code for the enum:
OSExecute.command("javap Explore");
}
} /* Output:
----- Analyzing class Explore -----
Interfaces:
Base: class java.lang.Enum
Methods:
[compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, values, wait]
----- Analyzing class java.lang.Enum -----
Interfaces:
java.lang.Comparable<E>
interface java.io.Serializable
Base: class java.lang.Object
Methods:
[compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, wait]
Explore.containsAll(Enum)? true
Explore.removeAll(Enum): [values]
Compiled from "Reflection.java"
final class Explore extends java.lang.Enum{
public static final Explore HERE;
public static final Explore THERE;
public static Explore[] values();
public static Explore valueOf(java.lang.String);
static {};
}
*///:~

19
enums/RoShamBo.java Normal file
View File

@ -0,0 +1,19 @@
//: enums/RoShamBo.java
// ©2015 MindView LLC: see Copyright.txt
// Common tools for RoShamBo examples.
package enums;
import net.mindview.util.*;
public class RoShamBo {
public static <T extends Competitor<T>>
void match(T a, T b) {
System.out.println(
a + " vs. " + b + ": " + a.compete(b));
}
public static <T extends Enum<T> & Competitor<T>>
void play(Class<T> rsbClass, int size) {
for(int i = 0; i < size; i++)
match(
Enums.random(rsbClass),Enums.random(rsbClass));
}
} ///:~

94
enums/RoShamBo1.java Normal file
View File

@ -0,0 +1,94 @@
//: enums/RoShamBo1.java
// ©2015 MindView LLC: see Copyright.txt
// Demonstration of multiple dispatching.
package enums;
import java.util.*;
import static enums.Outcome.*;
interface Item {
Outcome compete(Item it);
Outcome eval(Paper p);
Outcome eval(Scissors s);
Outcome eval(Rock r);
}
class Paper implements Item {
@Override
public Outcome compete(Item it) { return it.eval(this); }
@Override
public Outcome eval(Paper p) { return DRAW; }
@Override
public Outcome eval(Scissors s) { return WIN; }
@Override
public Outcome eval(Rock r) { return LOSE; }
@Override
public String toString() { return "Paper"; }
}
class Scissors implements Item {
@Override
public Outcome compete(Item it) { return it.eval(this); }
@Override
public Outcome eval(Paper p) { return LOSE; }
@Override
public Outcome eval(Scissors s) { return DRAW; }
@Override
public Outcome eval(Rock r) { return WIN; }
@Override
public String toString() { return "Scissors"; }
}
class Rock implements Item {
@Override
public Outcome compete(Item it) { return it.eval(this); }
@Override
public Outcome eval(Paper p) { return WIN; }
@Override
public Outcome eval(Scissors s) { return LOSE; }
@Override
public Outcome eval(Rock r) { return DRAW; }
@Override
public String toString() { return "Rock"; }
}
public class RoShamBo1 {
static final int SIZE = 20;
private static Random rand = new Random(47);
public static Item newItem() {
switch(rand.nextInt(3)) {
default:
case 0: return new Scissors();
case 1: return new Paper();
case 2: return new Rock();
}
}
public static void match(Item a, Item b) {
System.out.println(
a + " vs. " + b + ": " + a.compete(b));
}
public static void main(String[] args) {
for(int i = 0; i < SIZE; i++)
match(newItem(), newItem());
}
} /* Output:
Rock vs. Rock: DRAW
Paper vs. Rock: WIN
Paper vs. Rock: WIN
Paper vs. Rock: WIN
Scissors vs. Paper: WIN
Scissors vs. Scissors: DRAW
Scissors vs. Paper: WIN
Rock vs. Paper: LOSE
Paper vs. Paper: DRAW
Rock vs. Paper: LOSE
Paper vs. Scissors: LOSE
Paper vs. Scissors: LOSE
Rock vs. Scissors: WIN
Rock vs. Paper: LOSE
Paper vs. Rock: WIN
Scissors vs. Paper: WIN
Paper vs. Scissors: LOSE
Paper vs. Scissors: LOSE
Paper vs. Scissors: LOSE
Paper vs. Scissors: LOSE
*///:~

50
enums/RoShamBo2.java Normal file
View File

@ -0,0 +1,50 @@
//: enums/RoShamBo2.java
// ©2015 MindView LLC: see Copyright.txt
// Switching one enum on another.
package enums;
import static enums.Outcome.*;
public enum RoShamBo2 implements Competitor<RoShamBo2> {
PAPER(DRAW, LOSE, WIN),
SCISSORS(WIN, DRAW, LOSE),
ROCK(LOSE, WIN, DRAW);
private Outcome vPAPER, vSCISSORS, vROCK;
RoShamBo2(Outcome paper,Outcome scissors,Outcome rock) {
this.vPAPER = paper;
this.vSCISSORS = scissors;
this.vROCK = rock;
}
@Override
public Outcome compete(RoShamBo2 it) {
switch(it) {
default:
case PAPER: return vPAPER;
case SCISSORS: return vSCISSORS;
case ROCK: return vROCK;
}
}
public static void main(String[] args) {
RoShamBo.play(RoShamBo2.class, 20);
}
} /* Output:
ROCK vs. ROCK: DRAW
SCISSORS vs. ROCK: LOSE
SCISSORS vs. ROCK: LOSE
SCISSORS vs. ROCK: LOSE
PAPER vs. SCISSORS: LOSE
PAPER vs. PAPER: DRAW
PAPER vs. SCISSORS: LOSE
ROCK vs. SCISSORS: WIN
SCISSORS vs. SCISSORS: DRAW
ROCK vs. SCISSORS: WIN
SCISSORS vs. PAPER: WIN
SCISSORS vs. PAPER: WIN
ROCK vs. PAPER: LOSE
ROCK vs. SCISSORS: WIN
SCISSORS vs. ROCK: LOSE
PAPER vs. SCISSORS: LOSE
SCISSORS vs. PAPER: WIN
SCISSORS vs. PAPER: WIN
SCISSORS vs. PAPER: WIN
SCISSORS vs. PAPER: WIN
*///:~

46
enums/RoShamBo3.java Normal file
View File

@ -0,0 +1,46 @@
//: enums/RoShamBo3.java
// ©2015 MindView LLC: see Copyright.txt
// Using constant-specific methods.
package enums;
import static enums.Outcome.*;
public enum RoShamBo3 implements Competitor<RoShamBo3> {
PAPER {
@Override
public Outcome compete(RoShamBo3 it) {
switch(it) {
default: // To placate the compiler
case PAPER: return DRAW;
case SCISSORS: return LOSE;
case ROCK: return WIN;
}
}
},
SCISSORS {
@Override
public Outcome compete(RoShamBo3 it) {
switch(it) {
default:
case PAPER: return WIN;
case SCISSORS: return DRAW;
case ROCK: return LOSE;
}
}
},
ROCK {
@Override
public Outcome compete(RoShamBo3 it) {
switch(it) {
default:
case PAPER: return LOSE;
case SCISSORS: return WIN;
case ROCK: return DRAW;
}
}
};
@Override
public abstract Outcome compete(RoShamBo3 it);
public static void main(String[] args) {
RoShamBo.play(RoShamBo3.class, 20);
}
} /* Same output as RoShamBo2.java *///:~

32
enums/RoShamBo4.java Normal file
View File

@ -0,0 +1,32 @@
//: enums/RoShamBo4.java
// ©2015 MindView LLC: see Copyright.txt
package enums;
public enum RoShamBo4 implements Competitor<RoShamBo4> {
ROCK {
@Override
public Outcome compete(RoShamBo4 opponent) {
return compete(SCISSORS, opponent);
}
},
SCISSORS {
@Override
public Outcome compete(RoShamBo4 opponent) {
return compete(PAPER, opponent);
}
},
PAPER {
@Override
public Outcome compete(RoShamBo4 opponent) {
return compete(ROCK, opponent);
}
};
Outcome compete(RoShamBo4 loser, RoShamBo4 opponent) {
return ((opponent == this) ? Outcome.DRAW
: ((opponent == loser) ? Outcome.WIN
: Outcome.LOSE));
}
public static void main(String[] args) {
RoShamBo.play(RoShamBo4.class, 20);
}
} /* Same output as RoShamBo2.java *///:~

34
enums/RoShamBo5.java Normal file
View File

@ -0,0 +1,34 @@
//: enums/RoShamBo5.java
// ©2015 MindView LLC: see Copyright.txt
// Multiple dispatching using an EnumMap of EnumMaps.
package enums;
import java.util.*;
import static enums.Outcome.*;
enum RoShamBo5 implements Competitor<RoShamBo5> {
PAPER, SCISSORS, ROCK;
static EnumMap<RoShamBo5,EnumMap<RoShamBo5,Outcome>>
table = new EnumMap<>(RoShamBo5.class);
static {
for(RoShamBo5 it : RoShamBo5.values())
table.put(it, new EnumMap<>(RoShamBo5.class));
initRow(PAPER, DRAW, LOSE, WIN);
initRow(SCISSORS, WIN, DRAW, LOSE);
initRow(ROCK, LOSE, WIN, DRAW);
}
static void initRow(RoShamBo5 it,
Outcome vPAPER, Outcome vSCISSORS, Outcome vROCK) {
EnumMap<RoShamBo5,Outcome> row =
RoShamBo5.table.get(it);
row.put(RoShamBo5.PAPER, vPAPER);
row.put(RoShamBo5.SCISSORS, vSCISSORS);
row.put(RoShamBo5.ROCK, vROCK);
}
@Override
public Outcome compete(RoShamBo5 it) {
return table.get(this).get(it);
}
public static void main(String[] args) {
RoShamBo.play(RoShamBo5.class, 20);
}
} /* Same output as RoShamBo2.java *///:~

21
enums/RoShamBo6.java Normal file
View File

@ -0,0 +1,21 @@
//: enums/RoShamBo6.java
// ©2015 MindView LLC: see Copyright.txt
// Enums using "tables" instead of multiple dispatch.
package enums;
import static enums.Outcome.*;
enum RoShamBo6 implements Competitor<RoShamBo6> {
PAPER, SCISSORS, ROCK;
private static Outcome[][] table = {
{ DRAW, LOSE, WIN }, // PAPER
{ WIN, DRAW, LOSE }, // SCISSORS
{ LOSE, WIN, DRAW }, // ROCK
};
@Override
public Outcome compete(RoShamBo6 other) {
return table[this.ordinal()][other.ordinal()];
}
public static void main(String[] args) {
RoShamBo.play(RoShamBo6.class, 20);
}
} ///:~

View File

@ -0,0 +1,38 @@
//: enums/SecurityCategory.java
// ©2015 MindView LLC: see Copyright.txt
// More succinct subcategorization of enums.
import net.mindview.util.*;
enum SecurityCategory {
STOCK(Security.Stock.class), BOND(Security.Bond.class);
Security[] values;
SecurityCategory(Class<? extends Security> kind) {
values = kind.getEnumConstants();
}
interface Security {
enum Stock implements Security { SHORT, LONG, MARGIN }
enum Bond implements Security { MUNICIPAL, JUNK }
}
public Security randomSelection() {
return Enums.random(values);
}
public static void main(String[] args) {
for(int i = 0; i < 10; i++) {
SecurityCategory category =
Enums.random(SecurityCategory.class);
System.out.println(category + ": " +
category.randomSelection());
}
}
} /* Output:
BOND: MUNICIPAL
BOND: MUNICIPAL
STOCK: MARGIN
STOCK: MARGIN
BOND: JUNK
STOCK: SHORT
STOCK: LONG
STOCK: LONG
BOND: MUNICIPAL
BOND: JUNK
*///:~

23
enums/SpaceShip.java Normal file
View File

@ -0,0 +1,23 @@
//: enums/SpaceShip.java
// ©2015 MindView LLC: see Copyright.txt
public enum SpaceShip {
SCOUT, CARGO, TRANSPORT, CRUISER, BATTLESHIP, MOTHERSHIP;
@Override
public String toString() {
String id = name();
String lower = id.substring(1).toLowerCase();
return id.charAt(0) + lower;
}
public static void main(String[] args) {
for(SpaceShip s : values()) {
System.out.println(s);
}
}
} /* Output:
Scout
Cargo
Transport
Cruiser
Battleship
Mothership
*///:~

7
enums/Spiciness.java Normal file
View File

@ -0,0 +1,7 @@
//: enums/Spiciness.java
// ©2015 MindView LLC: see Copyright.txt
package enums;
public enum Spiciness {
NOT, MILD, MEDIUM, HOT, FLAMING
} ///:~

42
enums/TrafficLight.java Normal file
View File

@ -0,0 +1,42 @@
//: enums/TrafficLight.java
// ©2015 MindView LLC: see Copyright.txt
// Enums in switch statements.
import static net.mindview.util.Print.*;
// Define an enum type:
enum Signal { GREEN, YELLOW, RED, }
public class TrafficLight {
Signal color = Signal.RED;
public void change() {
switch(color) {
// Note that you don't have to say Signal.RED
// in the case statement:
case RED: color = Signal.GREEN;
break;
case GREEN: color = Signal.YELLOW;
break;
case YELLOW: color = Signal.RED;
break;
}
}
@Override
public String toString() {
return "The traffic light is " + color;
}
public static void main(String[] args) {
TrafficLight t = new TrafficLight();
for(int i = 0; i < 7; i++) {
print(t);
t.change();
}
}
} /* Output:
The traffic light is RED
The traffic light is GREEN
The traffic light is YELLOW
The traffic light is RED
The traffic light is GREEN
The traffic light is YELLOW
The traffic light is RED
*///:~

18
enums/UpcastEnum.java Normal file
View File

@ -0,0 +1,18 @@
//: enums/UpcastEnum.java
// ©2015 MindView LLC: see Copyright.txt
// No values() method if you upcast an enum
enum Search { HITHER, YON }
public class UpcastEnum {
public static void main(String[] args) {
Search[] vals = Search.values();
Enum e = Search.HITHER; // Upcast
// e.values(); // No values() in Enum
for(Enum en : e.getClass().getEnumConstants())
System.out.println(en);
}
} /* Output:
HITHER
YON
*///:~

165
enums/VendingMachine.java Normal file
View File

@ -0,0 +1,165 @@
//: enums/VendingMachine.java
// ©2015 MindView LLC: see Copyright.txt
// {Args: VendingMachineInput.txt}
import java.util.*;
import net.mindview.util.*;
import static net.mindview.util.Print.*;
enum Category {
MONEY(Input.NICKEL, Input.DIME,
Input.QUARTER, Input.DOLLAR),
ITEM_SELECTION(Input.TOOTHPASTE, Input.CHIPS,
Input.SODA, Input.SOAP),
QUIT_TRANSACTION(Input.ABORT_TRANSACTION),
SHUT_DOWN(Input.STOP);
private Input[] values;
Category(Input... types) { values = types; }
private static EnumMap<Input,Category> categories =
new EnumMap<>(Input.class);
static {
for(Category c : Category.class.getEnumConstants())
for(Input type : c.values)
categories.put(type, c);
}
public static Category categorize(Input input) {
return categories.get(input);
}
}
public class VendingMachine {
private static State state = State.RESTING;
private static int amount = 0;
private static Input selection = null;
enum StateDuration { TRANSIENT } // Tagging enum
enum State {
RESTING {
@Override
void next(Input input) {
switch(Category.categorize(input)) {
case MONEY:
amount += input.amount();
state = ADDING_MONEY;
break;
case SHUT_DOWN:
state = TERMINAL;
default:
}
}
},
ADDING_MONEY {
@Override
void next(Input input) {
switch(Category.categorize(input)) {
case MONEY:
amount += input.amount();
break;
case ITEM_SELECTION:
selection = input;
if(amount < selection.amount())
print("Insufficient money for " + selection);
else state = DISPENSING;
break;
case QUIT_TRANSACTION:
state = GIVING_CHANGE;
break;
case SHUT_DOWN:
state = TERMINAL;
default:
}
}
},
DISPENSING(StateDuration.TRANSIENT) {
@Override
void next() {
print("here is your " + selection);
amount -= selection.amount();
state = GIVING_CHANGE;
}
},
GIVING_CHANGE(StateDuration.TRANSIENT) {
@Override
void next() {
if(amount > 0) {
print("Your change: " + amount);
amount = 0;
}
state = RESTING;
}
},
TERMINAL {@Override
void output() { print("Halted"); } };
private boolean isTransient = false;
State() {}
State(StateDuration trans) { isTransient = true; }
void next(Input input) {
throw new RuntimeException("Only call " +
"next(Input input) for non-transient states");
}
void next() {
throw new RuntimeException("Only call next() for " +
"StateDuration.TRANSIENT states");
}
void output() { print(amount); }
}
static void run(Generator<Input> gen) {
while(state != State.TERMINAL) {
state.next(gen.next());
while(state.isTransient)
state.next();
state.output();
}
}
public static void main(String[] args) {
Generator<Input> gen = new RandomInputGenerator();
if(args.length == 1)
gen = new FileInputGenerator(args[0]);
run(gen);
}
}
// For a basic sanity check:
class RandomInputGenerator implements Generator<Input> {
@Override
public Input next() { return Input.randomSelection(); }
}
// Create Inputs from a file of ';'-separated strings:
class FileInputGenerator implements Generator<Input> {
private Iterator<String> input;
public FileInputGenerator(String fileName) {
// Skip the comment line in the input file:
input = new TextFile(fileName, ";").listIterator(1);
}
@Override
public Input next() {
if(!input.hasNext())
return null;
return Enum.valueOf(Input.class, input.next().trim());
}
} /* Output:
25
50
75
here is your CHIPS
0
100
200
here is your TOOTHPASTE
0
25
35
Your change: 35
0
25
35
Insufficient money for SODA
35
60
70
75
Insufficient money for SODA
75
Your change: 75
0
Halted
*///:~

View File

@ -0,0 +1,9 @@
//: enums/VendingMachineInput.txt
QUARTER; QUARTER; QUARTER; CHIPS;
DOLLAR; DOLLAR; TOOTHPASTE;
QUARTER; DIME; ABORT_TRANSACTION;
QUARTER; DIME; SODA;
QUARTER; DIME; NICKEL; SODA;
ABORT_TRANSACTION;
STOP;
///:~

40
enums/build.xml Normal file
View File

@ -0,0 +1,40 @@
<?xml version="1.0" ?>
<project default="run">
<property name="chapter" value="enums"/>
<property name="excludedfiles" value=""/>
<import file="../Ant-Common.xml"/>
<import file="../Ant-Clean.xml"/>
<target name="run" description="Compile and run" depends="build">
<jrun cls="BigEnumSet" />
<jrun cls="enums.Burrito" dirpath="../enums" />
<jrun cls="CarWash" />
<jrun cls="ConstantSpecificMethod" />
<jrun cls="EnumClass" />
<jrun cls="enums.EnumMaps" dirpath="../enums" />
<jrun cls="enums.EnumSets" dirpath="../enums" />
<jrun cls="NonEnum" />
<jrun cls="OverrideConstantSpecific" />
<jrun cls="OzWitch" />
<jrun cls="PostOffice" />
<jrun cls="RandomTest" />
<jrun cls="Reflection" />
<jrun cls="enums.RoShamBo1" dirpath="../enums" />
<jrun cls="enums.RoShamBo2" dirpath="../enums" />
<jrun cls="enums.RoShamBo3" dirpath="../enums" />
<jrun cls="enums.RoShamBo4" dirpath="../enums" />
<jrun cls="enums.RoShamBo5" dirpath="../enums" />
<jrun cls="enums.RoShamBo6" dirpath="../enums" />
<jrun cls="SecurityCategory" />
<jrun cls="SpaceShip" />
<jrun cls="TrafficLight" />
<jrun cls="UpcastEnum" />
<jrun cls="VendingMachine" arguments="VendingMachineInput.txt" />
<jrun cls="enums.cartoons.EnumImplementation" dirpath="../enums/cartoons" />
<jrun cls="enums.menu.Meal" dirpath="../enums/menu" />
<jrun cls="enums.menu.Meal2" dirpath="../enums/menu" />
<jrun cls="enums.menu.TypeOfFood" dirpath="../enums/menu" />
</target>
</project>

View File

@ -0,0 +1,30 @@
//: enums/cartoons/EnumImplementation.java
// ©2015 MindView LLC: see Copyright.txt
// An enum can implement an interface
package enums.cartoons;
import java.util.*;
import net.mindview.util.*;
enum CartoonCharacter
implements Generator<CartoonCharacter> {
SLAPPY, SPANKY, PUNCHY, SILLY, BOUNCY, NUTTY, BOB;
private Random rand = new Random(47);
@Override
public CartoonCharacter next() {
return values()[rand.nextInt(values().length)];
}
}
public class EnumImplementation {
public static <T> void printNext(Generator<T> rg) {
System.out.print(rg.next() + ", ");
}
public static void main(String[] args) {
// Choose any instance:
CartoonCharacter cc = CartoonCharacter.BOB;
for(int i = 0; i < 10; i++)
printNext(cc);
}
} /* Output:
BOB, PUNCHY, BOB, SPANKY, NUTTY, PUNCHY, SLAPPY, NUTTY, NUTTY, SLAPPY,
*///:~

18
enums/menu/Course.java Normal file
View File

@ -0,0 +1,18 @@
//: enums/menu/Course.java
// ©2015 MindView LLC: see Copyright.txt
package enums.menu;
import net.mindview.util.*;
public enum Course {
APPETIZER(Food.Appetizer.class),
MAINCOURSE(Food.MainCourse.class),
DESSERT(Food.Dessert.class),
COFFEE(Food.Coffee.class);
private Food[] values;
private Course(Class<? extends Food> kind) {
values = kind.getEnumConstants();
}
public Food randomSelection() {
return Enums.random(values);
}
} ///:~

22
enums/menu/Food.java Normal file
View File

@ -0,0 +1,22 @@
//: enums/menu/Food.java
// ©2015 MindView LLC: see Copyright.txt
// Subcategorization of enums within interfaces.
package enums.menu;
public interface Food {
enum Appetizer implements Food {
SALAD, SOUP, SPRING_ROLLS;
}
enum MainCourse implements Food {
LASAGNE, BURRITO, PAD_THAI,
LENTILS, HUMMOUS, VINDALOO;
}
enum Dessert implements Food {
TIRAMISU, GELATO, BLACK_FOREST_CAKE,
FRUIT, CREME_CARAMEL;
}
enum Coffee implements Food {
BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,
LATTE, CAPPUCCINO, TEA, HERB_TEA;
}
} ///:~

41
enums/menu/Meal.java Normal file
View File

@ -0,0 +1,41 @@
//: enums/menu/Meal.java
// ©2015 MindView LLC: see Copyright.txt
package enums.menu;
public class Meal {
public static void main(String[] args) {
for(int i = 0; i < 5; i++) {
for(Course course : Course.values()) {
Food food = course.randomSelection();
System.out.println(food);
}
System.out.println("---");
}
}
} /* Output:
SPRING_ROLLS
VINDALOO
FRUIT
DECAF_COFFEE
---
SOUP
VINDALOO
FRUIT
TEA
---
SALAD
BURRITO
FRUIT
TEA
---
SALAD
BURRITO
CREME_CARAMEL
LATTE
---
SOUP
BURRITO
TIRAMISU
ESPRESSO
---
*///:~

44
enums/menu/Meal2.java Normal file
View File

@ -0,0 +1,44 @@
//: enums/menu/Meal2.java
// ©2015 MindView LLC: see Copyright.txt
package enums.menu;
import net.mindview.util.*;
public enum Meal2 {
APPETIZER(Food.Appetizer.class),
MAINCOURSE(Food.MainCourse.class),
DESSERT(Food.Dessert.class),
COFFEE(Food.Coffee.class);
private Food[] values;
private Meal2(Class<? extends Food> kind) {
values = kind.getEnumConstants();
}
public interface Food {
enum Appetizer implements Food {
SALAD, SOUP, SPRING_ROLLS;
}
enum MainCourse implements Food {
LASAGNE, BURRITO, PAD_THAI,
LENTILS, HUMMOUS, VINDALOO;
}
enum Dessert implements Food {
TIRAMISU, GELATO, BLACK_FOREST_CAKE,
FRUIT, CREME_CARAMEL;
}
enum Coffee implements Food {
BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,
LATTE, CAPPUCCINO, TEA, HERB_TEA;
}
}
public Food randomSelection() {
return Enums.random(values);
}
public static void main(String[] args) {
for(int i = 0; i < 5; i++) {
for(Meal2 meal : Meal2.values()) {
Food food = meal.randomSelection();
System.out.println(food);
}
System.out.println("---");
}
}
} /* Same output as Meal.java *///:~

View File

@ -0,0 +1,13 @@
//: enums/menu/TypeOfFood.java
// ©2015 MindView LLC: see Copyright.txt
package enums.menu;
import static enums.menu.Food.*;
public class TypeOfFood {
public static void main(String[] args) {
Food food = Appetizer.SALAD;
food = MainCourse.LASAGNE;
food = Dessert.GELATO;
food = Coffee.CAPPUCCINO;
}
} ///:~