Everything comes clear when you decompile an enum, and see the
generated methods, and the inner classes for each enum constant.
Most of the quirkiness of enum comes from the quirkiness of anonymous
inner classes.
here is a simple enum that involves no inner classes.
package com.mindprod.htmlmacros;
import java.util.EnumSet;
/**
* DO NOT SORT. THE ENUM ORDER IS SIGNIFICANT!! enum of possible
Windows OSes.
* May be used freely for any purpose but military.
*
* @author Roedy Green copyright 2005 Canadian Mind Products
*/
public enum OS {
/**
* Windows 95
*/
WIN95("W95", "Windows 95"),
/**
* Windows 98
*/
WIN98("W98", "Windows 98"),
/**
* Windows Me
*/
WINME("Me", "Windows Me"),
/**
* Windows NT
*/
WINNT("NT", "Windows NT"),
/**
* Windows 2000
*/
WIN2K("W2K", "Windows 2000"),
/**
* Windows XP
*/
WINXP("WXP", "Windows XP"),
/**
* Windows 2003
*/
WIN2K3("W2K3", "Windows 2003"),
/**
* Linux
*/
LINUX("Linux", "Linux"),
/**
* Mac OS/0
*/
CLASSICMAC("OS9", "classic MacIntosh OS/9"),
/**
* Mac OS X
*/
MAC("OSX", "MacIntosh OS X");
private String shortName;
private String longName;
private static boolean DEBUGGING = true;
/**
* Enum constant constructor that captures two extra facts about
the enum.
*
* @param shortName
* name for the os e.g. Me
* @param longName
* name of the OS e.g. "Windows XP"
*/
OS( String shortName, String longName )
{
this.shortName = shortName;
this.longName = longName;
}
/**
* @return short name
*/
public String getShortName ()
{
return this.shortName;
}
/**
* @return long name
*/
public String getLongName ()
{
return this.longName;
}
/**
* Static method to construct a string mentioning multiple OSes,
by slashes.
*
* @param choices
* EnumSet of just the oses you want included
* @return a String of the form "Windows 95/98/Me"
*/
public static String slashList ( EnumSet<OS> choices )
{
StringBuilder sb = new StringBuilder( 40 );
for ( OS o : choices )
{
sb.append( '/' );
sb.append( o.shortName );
}
if ( sb.length() == 0 )
{
return "";
}
else
{
// chop lead /
return sb.toString().substring( 1 );
}
}
/**
* test harness
*
* @param args
* not used
*/
public static void main ( String [ ] args )
{
if ( DEBUGGING )
{
// You don't use a constructor to create EnumSet objects.
EnumSet<OS> justThese = EnumSet.of( WIN2K, WINXP, WINME );
// prints "Me/W2K/XP"
// note they come out in proper order.
System.out.println( OS.slashList( justThese ) );
}
}
}
---------------------------------------------------------
decompilation.
note generated valueOf, values, static finals for each enum constant,
$VALUES array for indexing the constants, two hidden parms to each
enum constant constructor, its name and ordinal.
package com.mindprod.htmlmacros;
import java.io.PrintStream;
import java.util.EnumSet;
import java.util.Iterator;
public final class OS extends Enum
{
public static final OS[] values()
{
return (OS[])$VALUES.clone();
}
public static OS valueOf(String s)
{
return (OS)Enum.valueOf(com/mindprod/htmlmacros/OS, s);
}
private OS(String s, int i, String s1, String s2)
{
super(s, i);
shortName = s1;
longName = s2;
}
public String getShortName()
{
return shortName;
}
public String getLongName()
{
return longName;
}
public static String slashList(EnumSet enumset)
{
StringBuilder stringbuilder = new StringBuilder(40);
OS os;
for(Iterator iterator = enumset.iterator();
iterator.hasNext(); stringbuilder.append(os.shortName))
{
os = (OS)iterator.next();
stringbuilder.append('/');
}
if(stringbuilder.length() == 0)
return "";
else
return stringbuilder.toString().substring(1);
}
public static void main(String args[])
{
if(DEBUGGING)
{
EnumSet enumset = EnumSet.of(WIN2K, WINXP, WINME);
System.out.println(slashList(enumset));
}
}
public static final OS WIN95;
public static final OS WIN98;
public static final OS WINME;
public static final OS WINNT;
public static final OS WIN2K;
public static final OS WINXP;
public static final OS WIN2K3;
public static final OS LINUX;
public static final OS CLASSICMAC;
public static final OS MAC;
private String shortName;
private String longName;
private static boolean DEBUGGING = true;
private static final OS $VALUES[];
static
{
WIN95 = new OS("WIN95", 0, "W95", "Windows 95");
WIN98 = new OS("WIN98", 1, "W98", "Windows 98");
WINME = new OS("WINME", 2, "Me", "Windows Me");
WINNT = new OS("WINNT", 3, "NT", "Windows NT");
WIN2K = new OS("WIN2K", 4, "W2K", "Windows 2000");
WINXP = new OS("WINXP", 5, "WXP", "Windows XP");
WIN2K3 = new OS("WIN2K3", 6, "W2K3", "Windows 2003");
LINUX = new OS("LINUX", 7, "Linux", "Linux");
CLASSICMAC = new OS("CLASSICMAC", 8, "OS9", "classic MacIntosh
OS/9");
MAC = new OS("MAC", 9, "OSX", "MacIntosh OS X");
$VALUES = (new OS[] {
WIN95, WIN98, WINME, WINNT, WIN2K, WINXP, WIN2K3, LINUX,
CLASSICMAC, MAC
});
}
}
--------------------------------------------------------------
Here is a more complicated enum with inner classes. Because this enum
relies on static variables you can't have two of these beasts working
independently. On my todo list is writing an essay on enums that will
have to tackle how you would rewrite this avoiding that problem. One
step at a time.
Each enum constant implements the abstract how method a different way:
package com.mindprod.stomp;
/**
* @author Roedy Green
*
* track current state of CD directory so we don't emit needless CD
commands.
*/
public enum InDir {
/** we are in the project directory */
INPROJECT() {
String how ()
{
return "c:\ncd " + projectDir + "\n";
}
},
/** we are in the root */
INROOT() {
String how ()
{
return "c:\ncd \\\n";
}
},
/** we don't know (or care) which directory we are in */
UNKNOWN() {
String how ()
{
return "";
}
};
/**
* which directory we are in now
*/
private static InDir currentState = UNKNOWN;
/**
* the fully qualified project directory. It cannot be private or
* enum constants can't see it.
*/
static String projectDir;
/**
* how you get to this directory
*
* @return possibly empty string of commands to get
* to this directory
*/
abstract String how ();
/**
* no arg constructor
*/
private InDir( )
{
}
/**
* generate code to go to the given directory.
* If we are already there, generates an empty string.
*
* @param wanted which directory we want go to next
* @return commands to take us to that directory.
*/
public static String _cd ( InDir wanted )
{
if ( wanted == currentState )
{
return "";
}
currentState = wanted;
return wanted.how();
}
/**
* @param projectDir
* fully qualified project directory
*/
public static void setProject ( String projectDir )
{
InDir.projectDir = projectDir;
}
}
-----------------------------------------------------
Here is the decompilation. Note how there are three places you can
store information:
1. in the statics for the entire enum
2. in the instance variables used by all enum constants, each with
their own copy.
3. in the anonymous inner class instance variables, specific to each
enum constant.
Note that because enum constants are anonymous inner classes, they are
not allowed to have their own statics.
package com.mindprod.stomp;
public abstract class InDir extends Enum
{
public static final InDir[] values()
{
return (InDir[])$VALUES.clone();
}
public static InDir valueOf(String s)
{
return (InDir)Enum.valueOf(com/mindprod/stomp/InDir, s);
}
abstract String how();
private InDir(String s, int i)
{
super(s, i);
}
public static String _cd(InDir indir)
{
if(indir == currentState)
{
return "";
} else
{
currentState = indir;
return indir.how();
}
}
public static void setProject(String s)
{
projectDir = s;
}
public static final InDir INPROJECT;
public static final InDir INROOT;
public static final InDir UNKNOWN;
private static InDir currentState;
static String projectDir;
private static final InDir $VALUES[];
static
{
INPROJECT = new InDir("INPROJECT", 0) {
String how()
{
return (new StringBuilder()).append("c:\ncd
").append(projectDir).append("\n").toString();
}
};
INROOT = new InDir("INROOT", 1) {
String how()
{
return "c:\ncd \\\n";
}
};
UNKNOWN = new InDir("UNKNOWN", 2) {
String how()
{
return "";
}
};
$VALUES = (new InDir[] {
INPROJECT, INROOT, UNKNOWN
});
currentState = UNKNOWN;
}
}
----------------------------------------------------------
one of the anonymous inner classes looks like this:
package com.mindprod.stomp;
// Referenced classes of package com.mindprod.stomp:
// InDir
static final class InDir$1 extends InDir
{
String how()
{
return (new StringBuilder()).append("c:\ncd
").append(projectDir).append("\n").toString();
}
InDir$1(String s, int i)
{
super(s, i, null);
}
}
--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm
Canadian Mind Products, Roedy Green.
See
http://mindprod.com/iraq.html photos of Bush's war crimes