Java DIY (2 Part Series)
1 Create your ENUM (yes from Java’)
2 Java StringBuilder Demystified
If you are always in awe of the simple yet powerful Enums in java, follow along 😉
In Java, enum
data type internally inherits from java.lang.Enum
class.
Use cases to consider:
- should have methods
name(), ordinal()
asfinal
which no one can override - always maintain singleton status for each enum value
- you shouldn’t be able to access enum constructor (make it private)
- should have ordinal (consider sequential numbering idea)
- the enum should have a
values()
which returns all enum values.
I wrote a simple yet fairly complete implementation, so I welcome any feedback.
<span>import</span> <span>java.util.List</span><span>;</span><span>abstract</span> <span>class</span> <span>EnumBase</span> <span>implements</span> <span>Comparable</span><span><</span><span>EnumBase</span><span>>,</span> <span>Serializable</span> <span>{</span><span>private</span> <span>final</span> <span>int</span> <span>ordinal</span><span>;</span><span>private</span> <span>final</span> <span>String</span> <span>name</span><span>;</span><span>protected</span> <span>EnumBase</span><span>(</span><span>int</span> <span>ordinal</span><span>,</span> <span>String</span> <span>name</span><span>)</span> <span>{</span><span>this</span><span>.</span><span>ordinal</span> <span>=</span> <span>ordinal</span><span>;</span><span>this</span><span>.</span><span>name</span> <span>=</span> <span>name</span><span>;</span><span>}</span><span>public</span> <span>final</span> <span>int</span> <span>ordinal</span><span>()</span> <span>{</span><span>return</span> <span>ordinal</span><span>;</span><span>}</span><span>/** * non overridable * * @return always gives ENUM Constant name */</span><span>public</span> <span>final</span> <span>String</span> <span>name</span><span>()</span> <span>{</span><span>return</span> <span>name</span><span>;</span><span>}</span><span>/** * It is desired to be overloaded * * @return default to enum constant name */</span><span>@Override</span><span>public</span> <span>String</span> <span>toString</span><span>()</span> <span>{</span><span>return</span> <span>name</span><span>;</span><span>}</span><span>@Override</span><span>public</span> <span>final</span> <span>boolean</span> <span>equals</span><span>(</span><span>Object</span> <span>o</span><span>)</span> <span>{</span><span>return</span> <span>o</span> <span>==</span> <span>this</span><span>;</span> <span>// as singleton always yield true</span><span>}</span><span>@Override</span><span>public</span> <span>final</span> <span>int</span> <span>hashCode</span><span>()</span> <span>{</span><span>return</span> <span>super</span><span>.</span><span>hashCode</span><span>();</span> <span>// don't need it as there can only be ONE instance on an Enum</span><span>}</span><span>@Override</span><span>public</span> <span>final</span> <span>int</span> <span>compareTo</span><span>(</span><span>EnumBase</span> <span>o</span><span>)</span> <span>{</span><span>return</span> <span>Integer</span><span>.</span><span>compare</span><span>(</span><span>o</span><span>.</span><span>ordinal</span><span>,</span> <span>ordinal</span><span>);</span><span>}</span><span>/** * This guarantees that enums are never cloned, which is necessary * to preserve their "singleton" status. */</span><span>protected</span> <span>final</span> <span>Object</span> <span>clone</span><span>()</span> <span>throws</span> <span>CloneNotSupportedException</span> <span>{</span><span>throw</span> <span>new</span> <span>CloneNotSupportedException</span><span>();</span><span>}</span><span>/** * prevent default deserialization */</span><span>private</span> <span>void</span> <span>readObject</span><span>(</span><span>ObjectInputStream</span> <span>in</span><span>)</span> <span>throws</span> <span>IOException</span><span>,</span><span>ClassNotFoundException</span> <span>{</span><span>throw</span> <span>new</span> <span>InvalidObjectException</span><span>(</span><span>"can't deserialize enum"</span><span>);</span><span>}</span><span>private</span> <span>void</span> <span>readObjectNoData</span><span>()</span> <span>throws</span> <span>ObjectStreamException</span> <span>{</span><span>throw</span> <span>new</span> <span>InvalidObjectException</span><span>(</span><span>"can't deserialize enum"</span><span>);</span><span>}</span><span>}</span><span>public</span> <span>class</span> <span>MyEnum</span> <span>{</span><span>private</span> <span>static</span> <span>int</span> <span>ordinalCounter</span> <span>=</span> <span>0</span><span>;</span><span>/** * Utility class where we fix the ordinal as sequential integers */</span><span>private</span> <span>abstract</span> <span>static</span> <span>class</span> <span>AbstractEnum</span> <span>extends</span> <span>EnumBase</span> <span>{</span><span>private</span> <span>AbstractEnum</span><span>(</span><span>String</span> <span>name</span><span>)</span> <span>{</span><span>super</span><span>(++</span><span>ordinalCounter</span><span>,</span> <span>name</span><span>);</span><span>}</span><span>}</span><span>// singleton instance</span><span>public</span> <span>static</span> <span>final</span> <span>FIRST</span> <span>FIRST</span> <span>=</span> <span>new</span> <span>FIRST</span><span>();</span><span>static</span> <span>class</span> <span>FIRST</span> <span>extends</span> <span>AbstractEnum</span> <span>{</span><span>private</span> <span>FIRST</span><span>()</span> <span>{</span><span>super</span><span>(</span><span>FIRST</span><span>.</span><span>class</span><span>.</span><span>getSimpleName</span><span>());</span><span>}</span><span>}</span><span>public</span> <span>static</span> <span>final</span> <span>SECOND</span> <span>SECOND</span> <span>=</span> <span>new</span> <span>SECOND</span><span>();</span><span>static</span> <span>class</span> <span>SECOND</span> <span>extends</span> <span>AbstractEnum</span> <span>{</span><span>private</span> <span>SECOND</span><span>()</span> <span>{</span><span>super</span><span>(</span><span>SECOND</span><span>.</span><span>class</span><span>.</span><span>getSimpleName</span><span>());</span><span>}</span><span>}</span><span>public</span> <span>static</span> <span>List</span><span><</span><span>EnumBase</span><span>></span> <span>values</span><span>()</span> <span>{</span><span>return</span> <span>List</span><span>.</span><span>of</span><span>(</span><span>FIRST</span><span>,</span> <span>SECOND</span><span>);</span><span>}</span><span>}</span><span>class</span> <span>MyEnumDriver</span> <span>{</span><span>public</span> <span>static</span> <span>void</span> <span>main</span><span>(</span><span>String</span><span>[]</span> <span>args</span><span>)</span> <span>{</span><span>// FIRST 1</span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>MyEnum</span><span>.</span><span>FIRST</span><span>.</span><span>name</span><span>()</span> <span>+</span> <span>" "</span> <span>+</span> <span>MyEnum</span><span>.</span><span>FIRST</span><span>.</span><span>ordinal</span><span>());</span><span>// true</span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>MyEnum</span><span>.</span><span>FIRST</span> <span>==</span> <span>MyEnum</span><span>.</span><span>FIRST</span><span>);</span><span>// FIRST 2</span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>MyEnum</span><span>.</span><span>SECOND</span><span>.</span><span>name</span><span>()</span> <span>+</span> <span>" "</span> <span>+</span> <span>MyEnum</span><span>.</span><span>SECOND</span><span>.</span><span>ordinal</span><span>());</span><span>// values</span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>MyEnum</span><span>.</span><span>values</span><span>());</span><span>}</span><span>}</span><span>import</span> <span>java.util.List</span><span>;</span> <span>abstract</span> <span>class</span> <span>EnumBase</span> <span>implements</span> <span>Comparable</span><span><</span><span>EnumBase</span><span>>,</span> <span>Serializable</span> <span>{</span> <span>private</span> <span>final</span> <span>int</span> <span>ordinal</span><span>;</span> <span>private</span> <span>final</span> <span>String</span> <span>name</span><span>;</span> <span>protected</span> <span>EnumBase</span><span>(</span><span>int</span> <span>ordinal</span><span>,</span> <span>String</span> <span>name</span><span>)</span> <span>{</span> <span>this</span><span>.</span><span>ordinal</span> <span>=</span> <span>ordinal</span><span>;</span> <span>this</span><span>.</span><span>name</span> <span>=</span> <span>name</span><span>;</span> <span>}</span> <span>public</span> <span>final</span> <span>int</span> <span>ordinal</span><span>()</span> <span>{</span> <span>return</span> <span>ordinal</span><span>;</span> <span>}</span> <span>/** * non overridable * * @return always gives ENUM Constant name */</span> <span>public</span> <span>final</span> <span>String</span> <span>name</span><span>()</span> <span>{</span> <span>return</span> <span>name</span><span>;</span> <span>}</span> <span>/** * It is desired to be overloaded * * @return default to enum constant name */</span> <span>@Override</span> <span>public</span> <span>String</span> <span>toString</span><span>()</span> <span>{</span> <span>return</span> <span>name</span><span>;</span> <span>}</span> <span>@Override</span> <span>public</span> <span>final</span> <span>boolean</span> <span>equals</span><span>(</span><span>Object</span> <span>o</span><span>)</span> <span>{</span> <span>return</span> <span>o</span> <span>==</span> <span>this</span><span>;</span> <span>// as singleton always yield true</span> <span>}</span> <span>@Override</span> <span>public</span> <span>final</span> <span>int</span> <span>hashCode</span><span>()</span> <span>{</span> <span>return</span> <span>super</span><span>.</span><span>hashCode</span><span>();</span> <span>// don't need it as there can only be ONE instance on an Enum</span> <span>}</span> <span>@Override</span> <span>public</span> <span>final</span> <span>int</span> <span>compareTo</span><span>(</span><span>EnumBase</span> <span>o</span><span>)</span> <span>{</span> <span>return</span> <span>Integer</span><span>.</span><span>compare</span><span>(</span><span>o</span><span>.</span><span>ordinal</span><span>,</span> <span>ordinal</span><span>);</span> <span>}</span> <span>/** * This guarantees that enums are never cloned, which is necessary * to preserve their "singleton" status. */</span> <span>protected</span> <span>final</span> <span>Object</span> <span>clone</span><span>()</span> <span>throws</span> <span>CloneNotSupportedException</span> <span>{</span> <span>throw</span> <span>new</span> <span>CloneNotSupportedException</span><span>();</span> <span>}</span> <span>/** * prevent default deserialization */</span> <span>private</span> <span>void</span> <span>readObject</span><span>(</span><span>ObjectInputStream</span> <span>in</span><span>)</span> <span>throws</span> <span>IOException</span><span>,</span> <span>ClassNotFoundException</span> <span>{</span> <span>throw</span> <span>new</span> <span>InvalidObjectException</span><span>(</span><span>"can't deserialize enum"</span><span>);</span> <span>}</span> <span>private</span> <span>void</span> <span>readObjectNoData</span><span>()</span> <span>throws</span> <span>ObjectStreamException</span> <span>{</span> <span>throw</span> <span>new</span> <span>InvalidObjectException</span><span>(</span><span>"can't deserialize enum"</span><span>);</span> <span>}</span> <span>}</span> <span>public</span> <span>class</span> <span>MyEnum</span> <span>{</span> <span>private</span> <span>static</span> <span>int</span> <span>ordinalCounter</span> <span>=</span> <span>0</span><span>;</span> <span>/** * Utility class where we fix the ordinal as sequential integers */</span> <span>private</span> <span>abstract</span> <span>static</span> <span>class</span> <span>AbstractEnum</span> <span>extends</span> <span>EnumBase</span> <span>{</span> <span>private</span> <span>AbstractEnum</span><span>(</span><span>String</span> <span>name</span><span>)</span> <span>{</span> <span>super</span><span>(++</span><span>ordinalCounter</span><span>,</span> <span>name</span><span>);</span> <span>}</span> <span>}</span> <span>// singleton instance</span> <span>public</span> <span>static</span> <span>final</span> <span>FIRST</span> <span>FIRST</span> <span>=</span> <span>new</span> <span>FIRST</span><span>();</span> <span>static</span> <span>class</span> <span>FIRST</span> <span>extends</span> <span>AbstractEnum</span> <span>{</span> <span>private</span> <span>FIRST</span><span>()</span> <span>{</span> <span>super</span><span>(</span><span>FIRST</span><span>.</span><span>class</span><span>.</span><span>getSimpleName</span><span>());</span> <span>}</span> <span>}</span> <span>public</span> <span>static</span> <span>final</span> <span>SECOND</span> <span>SECOND</span> <span>=</span> <span>new</span> <span>SECOND</span><span>();</span> <span>static</span> <span>class</span> <span>SECOND</span> <span>extends</span> <span>AbstractEnum</span> <span>{</span> <span>private</span> <span>SECOND</span><span>()</span> <span>{</span> <span>super</span><span>(</span><span>SECOND</span><span>.</span><span>class</span><span>.</span><span>getSimpleName</span><span>());</span> <span>}</span> <span>}</span> <span>public</span> <span>static</span> <span>List</span><span><</span><span>EnumBase</span><span>></span> <span>values</span><span>()</span> <span>{</span> <span>return</span> <span>List</span><span>.</span><span>of</span><span>(</span><span>FIRST</span><span>,</span> <span>SECOND</span><span>);</span> <span>}</span> <span>}</span> <span>class</span> <span>MyEnumDriver</span> <span>{</span> <span>public</span> <span>static</span> <span>void</span> <span>main</span><span>(</span><span>String</span><span>[]</span> <span>args</span><span>)</span> <span>{</span> <span>// FIRST 1</span> <span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>MyEnum</span><span>.</span><span>FIRST</span><span>.</span><span>name</span><span>()</span> <span>+</span> <span>" "</span> <span>+</span> <span>MyEnum</span><span>.</span><span>FIRST</span><span>.</span><span>ordinal</span><span>());</span> <span>// true</span> <span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>MyEnum</span><span>.</span><span>FIRST</span> <span>==</span> <span>MyEnum</span><span>.</span><span>FIRST</span><span>);</span> <span>// FIRST 2</span> <span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>MyEnum</span><span>.</span><span>SECOND</span><span>.</span><span>name</span><span>()</span> <span>+</span> <span>" "</span> <span>+</span> <span>MyEnum</span><span>.</span><span>SECOND</span><span>.</span><span>ordinal</span><span>());</span> <span>// values</span> <span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>MyEnum</span><span>.</span><span>values</span><span>());</span> <span>}</span> <span>}</span>import java.util.List; abstract class EnumBase implements Comparable<EnumBase>, Serializable { private final int ordinal; private final String name; protected EnumBase(int ordinal, String name) { this.ordinal = ordinal; this.name = name; } public final int ordinal() { return ordinal; } /** * non overridable * * @return always gives ENUM Constant name */ public final String name() { return name; } /** * It is desired to be overloaded * * @return default to enum constant name */ @Override public String toString() { return name; } @Override public final boolean equals(Object o) { return o == this; // as singleton always yield true } @Override public final int hashCode() { return super.hashCode(); // don't need it as there can only be ONE instance on an Enum } @Override public final int compareTo(EnumBase o) { return Integer.compare(o.ordinal, ordinal); } /** * This guarantees that enums are never cloned, which is necessary * to preserve their "singleton" status. */ protected final Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } /** * prevent default deserialization */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new InvalidObjectException("can't deserialize enum"); } private void readObjectNoData() throws ObjectStreamException { throw new InvalidObjectException("can't deserialize enum"); } } public class MyEnum { private static int ordinalCounter = 0; /** * Utility class where we fix the ordinal as sequential integers */ private abstract static class AbstractEnum extends EnumBase { private AbstractEnum(String name) { super(++ordinalCounter, name); } } // singleton instance public static final FIRST FIRST = new FIRST(); static class FIRST extends AbstractEnum { private FIRST() { super(FIRST.class.getSimpleName()); } } public static final SECOND SECOND = new SECOND(); static class SECOND extends AbstractEnum { private SECOND() { super(SECOND.class.getSimpleName()); } } public static List<EnumBase> values() { return List.of(FIRST, SECOND); } } class MyEnumDriver { public static void main(String[] args) { // FIRST 1 System.out.println(MyEnum.FIRST.name() + " " + MyEnum.FIRST.ordinal()); // true System.out.println(MyEnum.FIRST == MyEnum.FIRST); // FIRST 2 System.out.println(MyEnum.SECOND.name() + " " + MyEnum.SECOND.ordinal()); // values System.out.println(MyEnum.values()); } }
Enter fullscreen mode Exit fullscreen mode
Java DIY (2 Part Series)
1 Create your ENUM (yes from Java’)
2 Java StringBuilder Demystified
© 版权声明
THE END
暂无评论内容