JAVA basics: Use enumeration in Java again

Source: Internet
Author: User
JAVA basics: Let's talk about how to use enumeration in Java-general Linux technology-Linux programming and kernel information. The following is a detailed description. Programmers from C ++ to Java always complained a lot at the beginning, but not enumeration is a very prominent problem. Why does Java not support enumeration? From the perspective of programming language, what does enumeration support mean? Can we find a way to meet the requirements of C ++ programmers for enumeration? Now let's discuss this issue together.

Enumerated Types)

Let's take a look at the following small program:

Enum Day {SUNDAY, MONDAY, TUESDAY,
WEDNESDAY, THURSDAY, FRIDAY, SATURDAY };



This statement provides a user-friendly way to define variables that enumerate all possible values of this data type, from Monday to Sunday. Aside from the specific programming language, the core functions of enumeration should be:


Type Safety)


Compact, Efficient Declaration of Enumerated Values)


Seamless interaction with other parts of the Program (Seamless integration with other language features)


Runtime efficiency)

Now let's discuss these features one by one.

1. type security

The enumerated statement creates a new type. It is different from other existing types, including the original type (integer, floating point number, etc.) and other enumeration types in the current Scope. When you assign values to function parameters, the integer type and enumeration type are not interchangeable (unless you explicitly convert the type), and the compiler will force this. For example, define a function using the enumerated values stated above:

Public void foo (Day );



If you use an integer to call this function, the compiler will give an error.

Foo (4); // compilation error



According to this standard, Pascal, Ada, and C ++ support enumeration strictly, whereas C does not.

2. compact and effective enumeration value definitions

It should be easy to define a huge program. For example, in Java, we have such a "quasi-enumeration" definition method:

Public static final int SUNDAY = 0;
Public static final int MONDAY = 1;
Public static final int TUESDAY = 2;
Public static final int WEDNESDAY = 3;
Public static final int THURSDAY = 4;
Public static final int FRIDAY = 5;
Public static final int SATURDAY = 6;



This definition does not seem concise. This is especially important if a large amount of data needs to be defined, and you will feel more deeply. Although this is not as important as the other three, we always hope that the statement can be as concise as possible.

3. seamless interaction with other parts of the program

Language operators, such as value assignment, equal, greater than, or less than must support enumeration. Enumeration should also support array subscript and switch/case statements to control flow operations. For example:

For (Day d = SUNDAY; d <= SATURDAY; ++ d ){
Switch (d ){
Case MONDAY :...;
Break;
Case TUESDAY :...;
Break;
Case WEDNESDAY :...;
Break;
Case THURSDAY :...;
Break;
Case FRIDAY :...;
Break;
Case SATURDAY:
Case SUNDAY :...;
}
}



To allow this program to work, the enumeration must be an integer constant rather than an object (objects ). In Java, you can use equals () or compareTo () functions to compare objects. However, they do not support array subscript and switch statements.

4. High Operating Efficiency

The operating efficiency of enumeration should be the same as that of the original Integer type. During running, the performance should not be lower than that of integers due to enumeration.

If a language meets these four requirements, we can say that this language truly supports enumeration. For example, Pascal, Ada, and C ++. Obviously, Java is not.

The founder of Java, James Gosling, is a senior C ++ programmer who knows exactly what enumeration is. However, it seems that he intentionally deleted Java's enumeration capabilities. The reason is unknown. He may want to emphasize and encourage the use of polymorphism (polymorphism), rather than multiple branches. Multiple branches are often used together with enumeration. Regardless of his original intention, we still need to enumerate in Java.

Several "quasi-enumeration" types in Java

Although Java does not directly support user-defined enumeration. However, in practice, we still find some alternatives to enumeration.

The first alternative can be interpreted as "integer constant enumeration ". As follows:

Public static final int SUNDAY = 0;
Public static final int MONDAY = 1;
Public static final int TUESDAY = 2;
Public static final int WEDNESDAY = 3;
Public static final int THURSDAY = 4;
Public static final int FRIDAY = 5;
Public static final int SATURDAY = 6;



This method allows us to use a more meaningful variable name instead of a naked integer. This makes the source program more readable and maintainability. These definitions can be placed in any class. It can be mixed with other variables and methods. You can also put it in a separate class. If you choose to put it in a separate class, pay attention to the syntax When referencing it. For example, "Day. MONDAY .". If you want to save some time when referencing, you can put it in an interface. Other classes only need to declare the implementation (implement) and it can be easily referenced. For example, use MONDAY directly. For the purpose of using Java interfaces, this usage is somewhat biased!

This method obviously satisfies conditions 3 and 4, that is, the language integration and execution efficiency (enumeration is an integer, there is no efficiency loss ). But he cannot meet conditions 1 and 2. What is its definition ?? Close ?? Plaque? Ne? How can I step on a bucket? What kind of yellow slice Can I copy to the address? Java programmers use it, but it is not a good alternative to enumeration.

The second method is frequently mentioned by some famous experts. We can call it "Object enumeration ". Create a class for the enumeration, and then use the public class object to express the value of each enumeration. As follows:

Import java. util. Map;
Import java. util. HashMap;
Import java. util. Iterator;
Import java. io. Serializable;
Import java. io. InvalidObjectException;
Public final class Day implements Comparable, Serializable {
Private static int size = 0;
Private static int nextOrd = 0;
Private static Map nameMap = new HashMap (10 );
Private static Day first = null;
Private static Day last = null;
Private final int ord;
Private final String label;
Private Day prev;
Private Day next;
Public static final Day SUNDAY = new Day ("SUNDAY ");
Public static final Day MONDAY = new Day ("MONDAY ");
Public static final Day TUESDAY = new Day ("TUESDAY ");
Public static final Day WEDNESDAY = new Day ("WEDNESDAY ");
Public static final Day THURSDAY = new Day ("THURSDAY ");
Public static final Day FRIDAY = new Day ("FRIDAY ");
Public static final Day SATURDAY = new Day ("SATURDAY ");
/**
* Create a new day with the given tag.
* (Uses default value for ord .)
*/
Private Day (String label ){
This (label, nextOrd );
}
/**
* Constructs a new Day with its label and ord value.
*/
Private Day (String label, int ord ){
This. label = label;
This. ord = ord;
++ Size;
NextOrd = ord + 1;
NameMap. put (label, this );
If (first = null)
First = this;
If (last! = Null ){
This. prev = last;
Last. next = this;
}
Last = this;
}
/**
* Compares two Day objects based on their ordinal values.
* Satisfies requirements of interface java. lang. Comparable.
*/
Public int compareTo (Object obj ){
Return ord-(Day) obj). ord;
}
/**
* Compares two Day objects for equality. Returns true
* Only if the specified Day is equal to this one.
*/
Public boolean equals (Object obj ){
Return super. equals (obj );
}
/**
* Returns a hash code value for this Day.
*/
Public int hashCode (){
Return super. hashCode ();
}
/**
* Resolves deserialized Day objects.
* @ Throws InvalidObjectException if deserialization fails.
*/
Private Object readResolve () throws InvalidObjectException {
Day d = get (label );
If (d! = Null)
Return d;
Else {
String msg = "invalid deserialized object: label = ";
Throw new InvalidObjectException (msg + label );
}
}
/**
* Returns Day with the specified label.
* Returns null if not found.
*/
Public static Day get (String label ){
Return (Day) nameMap. get (label );
}
/**
* Returns the label for this Day.
*/
Public String toString (){
Return label;
}
/**
* Always throws CloneNotSupportedException; guarantees that
* Day objects are never cloned.
*
* @ Return (never returns)
*/
Protected Object clone () throws CloneNotSupportedException {
Throw new CloneNotSupportedException ();
}
/**
* Returns an iterator over all Day objects in declared order.
*/
Public static Iterator iterator (){
// Anonymous inner class
Return new Iterator ()
{
Private Day current = first;
Public boolean hasNext (){
Return current! = Null;
}
Public Object next (){
Day d = current;
Current = current. next ();
Return d;
}
Public void remove (){
Throw new UnsupportedOperationException ();
}
};
}
/**
* Returns the ordinal value of this Day.
*/
Public int ord (){
Return this. ord;
}
/**
* Returns the number of declared Day objects.
*/
Public static int size (){
Return size;
}
/**
* Returns the first declared Day.
*/
Public static Day first (){
Return first;
}
/**
* Returns the last declared Day.
*/
Public static Day last (){
Return last;
}
/**
* Returns the previous Day before this one in declared order.
* Returns null for the first declared Day.
*/
Public Day prev (){
Return this. prev;
}
/**
* Returns the next Day after this one in declared order.
* Returns null for the last declared Day.
*/
Public Day next (){
Return this. next;
}
}



The enumerated value is defined as a public static object ). In addition, this class contains private constructor; An Iterator is used to traverse all values; some common functions in Java, such as toString (), equals () and compareTo (), and some functions that are convenient for the customer program to call, such as ord (), prev (), next (), first () and last ().

This implementation method provides good type security and operational efficiency (conditions 1 and 4 ). However, conditions 2 and 3 are not met. First, its definition is cumbersome. Most programmers may not use it because of this. At the same time, it cannot be used as an array subscript or a switch/case statement. To some extent, this reduces the extensiveness of his use.

It seems that no alternative is ideal. Although we do not have the right to modify the Java language, we may find some ways to overcome the disadvantages of "Object enumeration" and make it a qualified enumeration alternative.
AMini-Language for Enums)

Suppose I create a micro language (jEnum) dedicated to enumeration, which is used to declare enumeration. Then I use a special "Translation" program to convert the enumeration defined in this language into the corresponding "Object enumeration" definition, does that solve the complicated definition of "Object enumeration. Of course, we can easily make this "Translation" program do more work. For example, add a Package Declaration and Program annotation to describe the integer and the string Tag Name of the object. Let's look at the following example:

Package com. softmoore. util;
/**
* Various USA coins
*/
Enum Coin {PENNY ("penny") = 1, NICKEL ("nickel") = 5, DIME ("dime") = 10,
QUARTER ("quarter") = 25, HALF_DOLLAR ("half dollar") = 50 };



Although "integer constant enumeration" has significant advantages in some cases. However, in general, the type security provided by "Object enumeration" is even more important. In comparison, the shortcomings are still less important. Let's take a rough look at jEnum. With it, we can get a compact and effective enumeration statement, that is, condition 2 we mentioned earlier.

A friend familiar with compilers may be more likely to understand the following jEnum microlanguage.

CompilationUnit = (packageDecl )? (DocComment )? EnumTypeDecl.
PackageDecl = "package" packagePath ";".
PackagePath = packageName ("." packageName )*.
DocComment = "/**" commentChars "*/".
EnumTypeDecl = "enum" enumTypeName "{" enumList "}"";".
EnumList = enumDecl ("," enumDecl )*.
EnumDecl = enumLiteral ("(" stringLiteral ")")? ("=" IntLiteral )? .
PackageName = identifier.
EnumTypeName = identifier.
EnumLiteral = identifier.
CommentChars = any-char-sequence-character T -"*/"



This syntax allows you to declare the package at the beginning, which looks quite like the Java language. You can add some javadoc annotations. Of course this is not necessary. The Declaration of the enumeration type starts with the keyword "enum". The enumerated values are placed in braces {}. Multiple values are separated by commas. The declaration of each value includes a standard Java variable name, an optional string tag, an optional equal sign (=) and an integer.

If you omit the string tag, the enumerated variable name will be used. If you omit the equal sign and the following integer, it will automatically assign values to your enumeration in order, if no value is used, it increases gradually from scratch (step 1 ). The string tag is part of the return value of the toString () method, while the integer is the return value of the ord () method. As stated below:

Enum Color {RED ("Red") = 2, WHITE ("White") = 4, BLUE };




The RED label is "Red" and the value is 2;


The WHITE label is "White" and the value is 4;


The BLUE Label is "BLUE" and the value is 5.

Note that the Reserved Words in Java are also reserved in jEnum. For example, you cannot use this as the package name or for as the enumerated variable name. The name of the enumerated variable and the string tag must be different, and the integer value must be strictly increased. The following statement is incorrect because its string tag is not unique.

Enum Color {RED ("Red"), WHITE ("BLUE"), BLUE };



The statement below is also incorrect, because WHITE will be automatically assigned a value of 2, which is in conflict with BLUE.

Enum Color {RED = 1, WHITE, BLUE = 2 };



The following is a specific example. It will be used by the "Translation" program to convert it into a Java source program that we enumerate and declare as compiled.

Package com. softmoore. jEnum;
/**
* This class encapsulates the symbols (a.k. a. token types)
* Of a language token.
*/
Enum Symbol {
Identifier,
EnumRW ("Reserved Word: enum "),
AbstractRW ("Reserved Word: abstract "),
AssertRW ("Reserved Word: assert "),
BooleanRW ("Reserved Word: boolean "),
BreakRW ("Reserved Word: break "),
ByteRW ("Reserved Word: byte "),
CaseRW ("Reserved Word: case "),
CatchRW ("Reserved Word: catch "),
CharRW ("Reserved Word: char "),
ClassRW ("Reserved Word: class "),
ConstRW ("Reserved Word: const "),
ContinueRW ("Reserved Word: continue "),
DefaultRW ("Reserved Word: default "),
DoRW ("Reserved Word: do "),
DoubleRW ("Reserved Word: double "),
ElseRW ("Reserved Word: else "),
ExtendsRW ("Reserved Word: extends "),
FinalRW ("Reserved Word: final "),
FinallyRW ("Reserved Word: finally "),
FloatRW ("Reserved Word: float "),
ForRW ("Reserved Word: "),
GotoRW ("Reserved Word: goto "),
IfRW ("Reserved Word: if "),
ImplementsRW ("Reserved Word: implements "),
ImportRW ("Reserved Word: import "),
InstanceOfRW ("Reserved Word: instanceOf "),
IntRW ("Reserved Word: int "),
InterfaceRW ("Reserved Word: interface "),
LongRW ("Reserved Word: long "),
NativeRW ("Reserved Word: native "),
NewRW ("Reserved Word: new "),
NullRW ("Reserved Word: null "),
PackageRW ("Reserved Word: package "),
PrivateRW ("Reserved Word: private "),
ProtectedRW ("Reserved Word: protected "),
PublicRW ("Reserved Word: public "),
ReturnRW ("Reserved Word: return "),
ShortRW ("Reserved Word: short "),
StaticRW ("Reserved Word: static "),
StrictfpRW ("Reserved Word: strictfp "),
SuperRW ("Reserved Word: super "),
SwitchRW ("Reserved Word: switch "),
SynchronizedRW ("Reserved Word: synchronized "),
ThisRW ("Reserved Word: this "),
ThrowRW ("Reserved Word: throw "),
ThrowsRW ("Reserved Word: throws "),
TransientRW ("Reserved Word: transient "),
TryRW ("Reserved Word: try "),
VoidRW ("Reserved Word: void "),
VolatileRW ("Reserved Word: volatile "),
WhileRW ("Reserved Word: while "),
Equals ("= "),
LeftParen ("("),
RightParen (")"),
LeftBrace ("{"),
RightBrace ("}"),
Comma (","),
Semicolon (";"),
Period ("."),
IntLiteral,
StringLiteral,
DocComment,
EOF,
Unknown
};



If the Day enumeration statement is stored in the Day. enum file, we can translate the file into a Java source program.

$ Java-jar jEnum. jar Day. enum



The translation result is the Day. javaJava source program. The content is the same as what we mentioned earlier, and includes program comments and other content. If you want to save some trouble, you can write the above long command into a batch processing file or a shell script on Unix or Linux, so it will be simpler to use later, for example:

$ Jec Day. enum



There are four precautions for jEnum.

1. The file name is not necessarily suffixed with ". enum.". Other valid file suffixes are acceptable.

2. if the file suffix is not ". enum. ", the translation program will first search by the given file name. If not, it is assumed that the given file name is omitted ". enum. "suffix. Commands like this are acceptable:

$ Java-jar jEnum. jar Day



3. The generated Java source program file name is obtained according to the definition in the declarative file, rather than the declarative file name.

4. The translation program also accepts the following switches:

-O generates "Object enumeration" class enumeration, which is the default value

-C generates "integer constant enumeration" class enumeration, which is implemented by class

-I generate the "integer constant enumeration" class enumeration, which is implemented using interfaces.

Although the-C switch generates an "integer constant enumeration", it also provides methods in "Object enumeration", such as first (), last (), toString (int n), prev (int n), and next (int n ).

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.