обзор
Перечисление в Java является более мощным, чем многие другие языки, что может привести к неожиданному использованию.
В этой статье я расскажу об отдельных особенностях enum в Java и соберу их вместе, чтобы сформировать конечный автомат.
Enum для класса Singleton и Utility
Вы можете использовать enum как Singleton или Utility очень просто.
1
2
3
4
5
6
|
enum Singleton { INSTANCE; } enum Utility { ; // no instances } |
Enum для реализации интерфейса
Вы также можете реализовать интерфейс в перечислении.
01
02
03
04
05
06
07
08
09
10
|
interface Named { public String name(); public int order(); } enum Planets implements Named { Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune; // name() is implemented automagically. public int order() { return ordinal()+ 1 ; } } |
Каждый экземпляр Enum — это отдельный подкласс
Вы можете переопределить поведение экземпляра. Это эффективно дает экземпляру другой подкласс перечисления с его собственной реализацией.
01
02
03
04
05
06
07
08
09
10
|
// from http://download.oracle.com/javase/1,5.0/docs/guide/language/enums.html public enum Operation { PLUS { double eval( double x, double y) { return x + y; } }, MINUS { double eval( double x, double y) { return x - y; } }, TIMES { double eval( double x, double y) { return x * y; } }, DIVIDE { double eval( double x, double y) { return x / y; } }; // Do arithmetic op represented by this constant abstract double eval( double x, double y); } |
Использование перечисления в качестве конечного автомата
Что вы можете сделать со всеми этими методами, так это создать оператор на основе перечисления.
В этом коротком примере конечный автомат синтаксического анализатора обрабатывает необработанный XML из ByteBuffer. Каждое состояние имеет свой собственный метод процесса, и если данных недостаточно, конечный автомат может вернуться для получения дополнительных данных. Каждый переход между состояниями четко определен, и код для всех состояний находится в одном перечислении .
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
interface Context { ByteBuffer buffer(); State state(); void state(State state); } interface State { /** * @return true to keep processing, false to read more data. */ boolean process(Context context); } enum States implements State { XML { public boolean process(Context context) { if (context.buffer().remaining() < 16 ) return false ; // read header if (headerComplete) context.state(States.ROOT); return true ; } }, ROOT { public boolean process(Context context) { if (context.buffer().remaining() < 8 ) return false ; // read root tag if (rootComplete) context.state(States.IN_ROOT); return true ; } } } public void process(Context context) { socket.read(context.buffer()); while (context.state().process(context)); } |
Используя этот подход, можно написать синтаксический анализатор XML, который может обрабатывать пакеты за 10 микросекунд. Это так эффективно, как вам нужно в большинстве случаев.
Ссылка: Java Secret: Использование enum для создания конечного автомата от нашего партнера по JCG Питера Лоури из Vanilla Java .