Existe um método de valores na enumeração que é usado para gerar um array na ordem definida pela enumeração, que pode ser usado para percorrer. Todas as nossas classes de enumeração customizadas herdam de java.lang.Enum e têm as seguintes funções em exemplos:
Copie o código do código da seguinte forma:
//: enumerado/EnumClass.java
// Capacidades da classe Enum
importar estático net.mindview.util.Print.*;
enum Arbusto {TERRENO, RASTEJANDO, PENDURADO}
classe pública EnumClass {
public static void main(String[] args) {
for(Arbustos : Arbustos.valores()) {
print(s + " ordinal: " + s.ordinal());
printnb(s.compareTo(Shrubbery.CRAWLING) + " ");
printnb(s.equals(Shrubbery.CRAWLING) + " ");
print(s == Arbustos.CRAWLING);
imprimir(s.getDeclaringClass());
imprimir(s.nome());
imprimir("----------------------");
}
// Produz um valor enum a partir de um nome de string:
for(String s: "PENDURANDO TERRENO DE RASTEJAMENTO".split(" ")) {
Arbusto arbustivo = Enum.valueOf(Shrubbery.class, s);
imprimir(arbusto);
}
}
} /* Saída:
Ordinal TERRA: 0
-1 falso falso
classe Arbusto
Joshua Bloch foi extremamente útil no desenvolvimento deste capítulo.
CHÃO
-----------------------
Ordinal de rastreamento: 1
verdadeiro verdadeiro
classe Arbusto
RASTEJANDO
-----------------------
Ordinal PENDURADO: 2
falso falso
classe Arbusto
PENDURADO
-----------------------
PENDURADO
RASTEJANDO
CHÃO
*///:~
Também podemos usar referências de enumeração estática:
Copie o código do código da seguinte forma:
//: enumerado/Spiciness.java
pacote enumerado;
public enum Picante {NÃO, SUAVE, MÉDIO, QUENTE, FLAMEJANTE} ///:~
//: enumerado/Burrito.java
pacote enumerado;
importar enumerado estático.Spiciness.*;
classe pública Burrito {
Grau de tempero;
burrito público (grau de tempero) { this.degree = grau;}
public String toString() { return "Burrito é "+ grau;}
public static void main(String[] args) {
System.out.println(novo Burrito(NÃO));
System.out.println(novo Burrito(MÉDIO));
System.out.println(novo Burrito(QUENTE));
}
} /* Saída:
Burrito NÃO é
Burrito é MÉDIO
Burrito é QUENTE
*///:~
Além de adicionar métodos a uma enumeração, que não podem ser herdados, a enumeração pode ser tratada como uma classe geral, o que significa que você pode adicionar métodos à enumeração e também definir o método principal na enumeração:
Copie o código do código da seguinte forma:
//: enumerado/OzWitch.java
// As bruxas na terra de Oz.
importar estático net.mindview.util.Print.*;
enum público OzWitch {
// As instâncias devem ser definidas primeiro, antes dos métodos:
OESTE("Senhorita Gulch, também conhecida como Bruxa Má do Oeste"),NORTE("Glinda, a Bruxa Boa do Norte"),LESTE("Bruxa Má do Leste, usuária do Rubi " + "Sapatos, esmagados por Casa de Dorothy"),SOUTH("Boa por inferência, mas faltando");
descrição da string privada;
// O construtor deve ser um pacote ou acesso privado:
private OzWitch(String descrição) {
esta.descrição = descrição;
}
public String getDescription() { retornar descrição }
public static void main(String[] args) {
para (bruxa OzWitch: OzWitch.values())
print(bruxa + ": " + bruxa.getDescription());
}
} /* Saída:
OESTE: Senhorita Gulch, também conhecida como Bruxa Má do Oeste
NORTE: Glinda, a Bruxa Boa do Norte
LESTE: Bruxa Malvada do Leste, usuária dos Chinelos de Rubi, esmagada pela casa de Dorothy
SUL: Bom por inferência, mas ausente
*///:~
Copie o código do código da seguinte forma:
//: enumerado/SpaceShip.java
enum público nave espacial {
SCOUT, CARGA, TRANSPORTE, CRUZADOR, NAVE DE GUERRA, NAVE MÃE;
string pública paraString() {
String id = nome();
String inferior = id.substring(1).toLowerCase();
retornar id.charAt(0) + inferior;
}
public static void main(String[] args) {
for(Nave Espacial : valores()) {
System.out.println(s);
}
}
} /* Saída:
Escoteiro
Carga
Transporte
Cruzador
Encouraçado
Nave mãe
*///:~
Enumerações em instruções switch Uma função importante das enumerações está nas instruções switch. Geralmente, as instruções switch funcionam apenas em valores inteiros, mas há uma ordem interna de números inteiros nas enumerações, portanto, a ordem das instâncias pode ser determinada por algum método. então enums podem ser usados em instruções switch:
Copie o código do código da seguinte forma:
//: enumerado/TrafficLight.java
// Enums em instruções switch.
importar estático net.mindview.util.Print.*;
// Defina um tipo de enum:
enum Sinal {VERDE, AMARELO, VERMELHO,}
classe pública Semáforo {
Cor do sinal = Signal.RED;
alteração pública nula() {
mudar(cor) {
// Observe que você não precisa dizer Signal.RED
// na instrução case:
caso VERMELHO: cor = Signal.GREEN;
quebrar;
caso VERDE: cor = Signal.YELLOW;
quebrar;
caso AMARELO: cor = Signal.RED;
quebrar;
}
}
string pública paraString() {
return "O semáforo está " + cor;
}
public static void main(String[] args) {
Semáforo t = novo Semáforo();
for(int i = 0; i < 7; i++) {
imprimir(t);
t.mudança();
}
}
} /* Saída:
O semáforo está VERMELHO
O semáforo está VERDE
O semáforo está AMARELO
O semáforo está VERMELHO
O semáforo está VERDE
O semáforo está AMARELO
O semáforo está VERMELHO
*///:~
O segredo dos valores() Embora tenhamos usado o método dos valores antes, se olharmos para Enum, não encontramos o método dos valores. Então, existem outros métodos ocultos? Podemos verificar isso com um código de reflexão simples:
Copie o código do código da seguinte forma:
//: enumerado/Reflection.java
// Analisando enums usando reflexão.
importar java.lang.reflect.*;
importar java.util.*;
importar net.mindview.util.*;
importar estático net.mindview.util.Print.*;
enum Explorar { AQUI, LÁ }
classe pública Reflexão {
public static Set<String> analisar(Class<?> enumClass) {
print("----- Analisando " + enumClass + " -----");
imprimir("Interfaces:");
for (Tipo t: enumClass.getGenericInterfaces())
imprimir(t);
print("Base: " + enumClass.getSuperclass());
print("Métodos: ");
Set<String> métodos = new TreeSet<String>();
for (Método m: enumClass.getMethods())
métodos.add(m.getName());
imprimir(métodos);
métodos de retorno;
}
public static void main(String[] args) {
Set<String> exploreMethods = analyze(Explore.class);
Set<String> enumMethods = analisar(Enum.class);
print("Explorar.containsAll(Enum)? " +
exploreMethods.containsAll(enumMethods));
printnb("Explore.removeAll(Enum): ");
exploreMethods.removeAll(enumMethods);
imprimir(explorarMétodos);
// Descompila o código do enum:
OSExecute.command("javap Explorar");
}
} /* Saída:
----- Analisando a classe Explorar -----
Interfaces:
Base: classe java.lang.Enum
Métodos:
[compareTo, equals, getClass, getDeclaringClass, hashCode, nome, notificar, notificarAll, ordinal, toString, valueOf, valores, esperar]
----- Analisando classe java.lang.Enum -----
Interfaces:
java.lang.Comparable<E>
interface java.io.Serializable
Base: classe java.lang.Object
Métodos:
[compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, wait]
Explore.containsAll(Enum)?
Explore.removeAll(Enum): [valores]
Compilado de "Reflection.java"
classe final Explorar estende java.lang.Enum{
final estático público Explore AQUI;
público estático final Explore LÁ;
public static final Explore[] valores();
public static Explorar valueOf(java.lang.String);
estático {};
}
*///:~
Podemos ver que o método de valores é adicionado pelo compilador. O método valueOf também é adicionado pelo compilador ao criar a enumeração, mas também existe um método valueOf na classe Enum, mas este método possui dois parâmetros, enquanto o método valueOf adicionado pelo compilador possui apenas um parâmetro. As enumerações são interpretadas como finais pelo compilador, portanto, as enumerações não podem ser herdadas. Como o método de valores é um método estático adicionado pelo compilador, se você converter a enumeração em Enum, o método de valores não estará disponível, mas há um método getEnumConstants na classe, portanto, embora o método de valores seja não está disponível em Enum , mas você ainda pode obter a instância de enumeração por meio do objeto Class:
Copie o código do código da seguinte forma:
//: enumerado/UpcastEnum.java
// Nenhum métodovalues() se você fizer upcast de um enum
enum Pesquisa { CÁ, YON }
classe pública UpcastEnum {
public static void main(String[] args) {
Pesquisa[] vals = Pesquisa.valores();
Enum e = Search.HITHER;
// e.values(); // Nenhum valor() em Enum
for(Enum en: e.getClass().getEnumConstants())
System.out.println(pt);
}
} /* Saída:
AQUI
VOCÊ
*///:~
Implementação sem herança Como todos os tipos de enumeração que definimos herdam de java.lang.Enum e Java não suporta herança múltipla, as enumerações não são criadas por herança, mas as enumerações podem ser criadas herdando uma ou mais interfaces:
Copie o código do código da seguinte forma:
//: enumerado/cartoons/EnumImplementation.java
// Um enum pode implementar uma interface
pacote enumerado.cartoons;
importar java.util.*;
importar net.mindview.util.*;
enum CartoonCharacter implementa Generator<CartoonCharacter> {
SLAPPY, Spanky, Punchy, Bobo, Saltitante, Noz, Bob;
Rand aleatório privado = novo aleatório (47);
public CartoonCharacter next() {
retornar valores()[rand.nextInt(valores().comprimento)];
}
}
classe pública EnumImplementação {
public static <T> void printNext(Generator<T> rg) {
System.out.print(rg.next() + ", ");
}
public static void main(String[] args) {
// Escolha qualquer instância:
Personagem de desenho animado cc = Personagem de desenho animado.BOB;
para(int i = 0; i < 10; i++)
imprimirPróximo(cc);
}
} /* Saída:
BOB, PUNCHY, BOB, Spanky, Noz, Punchy, SLAPPY, NOZ, NOZ, SLAPPY,
*///:~
Seleção Aleatória Em muitos de nossos exemplos posteriores, selecionaremos objetos aleatoriamente de instâncias de enumeração. Criamos uma classe pública para implementar isso:
Copie o código do código da seguinte forma:
//: net/mindview/util/Enums.java
pacote net.mindview.util;
importar java.util.*;
Enums de classe pública {
privado estático aleatório rand = novo aleatório (47);
public static <T estende Enum<T>> T random(Class<T> ec) {
retornar aleatório(ec.getEnumConstants());
}
public static <T> T aleatório(T[] valores) {
valores de retorno[rand.nextInt(valores.comprimento)];
}
} ///:~
Copie o código do código da seguinte forma:
//: enumerado/RandomTest.java
importar net.mindview.util.*;
enum Activity { SENTAR, MENTIR, EM PÉ, PULTAR, CORRER, ESQUIVAR, SALTAR, CAIR, VOAR }
classe pública RandomTest {
public static void main(String[] args) {
para(int i = 0; i < 20; i++)
System.out.print(Enums.random(Activity.class) + " ");
}
} /* Saída:
EM PÉ, VOANDO, CORRENDO, EM PÉ, CORRENDO, EM PÉ, DEITADO, ESQUIVANDO, SENTADO, CORRINDO, HOPPING, HOPPING, HOPPING, HOPPING, CORRIDA, EM PÉ, DEITADO, CAINDO, CORRIDO, VOANDO, VOANDO DEITADO
*///:~
O uso de interfaces para organizar enumerações não pode ser herdado, o que às vezes nos causa transtornos, pois às vezes queremos expandir o número de enumerações por meio de herança, e às vezes precisamos agrupar enumerações. Para este último, podemos definir enumerações agrupadas dentro da interface e, em seguida, criar a enumeração herdando desta interface. Como segue, temos diferentes categorias de alimentos que precisam ser criadas como enumerações, mas precisamos definir cada categoria como Os tipos. de Alimentos são os seguintes:
Copie o código do código da seguinte forma:
//: enumerado/menu/Food.java
// Subcategorização de enums dentro de interfaces.
pacote enumerado.menu;
interface pública Comida {enum Appetizer implementa Comida {SALAD, SOUP, SPRING_ROLLS;}
enum MainCourse implementa Comida {LASAGNE, BURRITO, PAD_THAI, LENTILS, HUMMOUS, VINDALOO;}
enum Sobremesa implementa Comida {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}
enum Coffee implementa Comida {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
} ///:~
Como cada enumeração é definida como uma implementação de uma interface, cada enumeração é do tipo Food, conforme segue:
Copie o código do código da seguinte forma:
//: enumerado/menu/TypeOfFood.java
pacote enumerado.menu;
importar static enumerated.menu.Food.*;
classe pública TypeOfFood {
public static void main(String[] args) {
Comida comida = Aperitivo.SALADA;
comida = MainCourse.LASAGNE;
comida = Sobremesa.GELATO;
comida = Café.CAPPUCCINO;
}
} ///:~
Mas as interfaces não podem operar em vários tipos, como enumerações, portanto, se você precisar de uma enumeração de enumerações, poderá encapsular uma instância de cada tipo de enumeração em uma enumeração:
Copie o código do código da seguinte forma:
//: enumerado/menu/Course.java
pacote enumerado.menu;
importar net.mindview.util.*;
enum público Curso {
APETIZER(Comida.Aperitivo.classe),PRATO PRINCIPAL(Comida.CursoPrincipal.classe),SOBREMESA(Comida.Dessert.classe),CAFÉ(Comida.Café.classe);
valores alimentares[] privados;
private Course(Class<? extends Food> kind) {
valores=kind.getEnumConstants();
}
comida pública randomSelection() {
retornar Enums.random(valores);
}
} ///:~
Cada enumeração usa o objeto Class como o parâmetro construtor correspondente. Podemos usar getEnumConstants deste parâmetro para obter a instância de enumeração. Esta instância pode ser usada no método randomSelection para gerar refeições aleatórias.
Copie o código do código da seguinte forma:
//: enumerado/menu/Meal.java
pacote enumerado.menu;
classe pública Refeição {
public static void main(String[] args) {
for(int i = 0; i < 5; i++) {
for(Curso curso: Course.values()) {
Comida comida = course.randomSelection();
System.out.println(comida);
}
System.out.println("---");
}
}
} /* Saída:
SPRING_ROLLS
VINDALOO
FRUTA
DECAF_COFFEE
---
SOPA
VINDALOO
FRUTA
CHÁ
---
SALADA
BURRITO
FRUTA
CHÁ
---
SALADA
BURRITO
CREME_CARAMELO
CAFÉ COM LEITE
---
SOPA
BURRITO
TIRAMISÚ
EXPRESSO
---
*///:~
Aqui está uma implementação mais compacta:
Copie o código do código da seguinte forma:
//: enumerado/SecurityCategory.java
// Subcategorização mais sucinta de enums.
importar net.mindview.util.*;
enum SecurityCategory {
ESTOQUE(Security.Stock.class), BOND(Security.Bond.class);
Valores de segurança[];
SecurityCategory(Class<? estende Segurança> tipo) {
valores=kind.getEnumConstants();
}
segurança da interface {
enum Stock implementa segurança { SHORT, LONG, MARGIN }
enum Bond implementa segurança {MUNICIPAL, JUNK}
}
segurança pública randomSelection() {
retornar Enums.random(valores);
}
public static void main(String[] args) {
for(int i = 0; i < 10; i++) {
Categoria SecurityCategory = Enums.random(SecurityCategory.class);
System.out.println(categoria + ": " +
categoria.randomSelection());
}
}
} /* Saída:
VÍNCULO: MUNICIPAL
VÍNCULO: MUNICIPAL
ESTOQUE: MARGEM
ESTOQUE: MARGEM
LIGAÇÃO: LIXO
ESTOQUE: CURTO
ESTOQUE: LONGO
ESTOQUE: LONGO
VÍNCULO: MUNICIPAL
LIGAÇÃO: LIXO
*///:~
Copie o código do código da seguinte forma:
//: enumerado/menu/Meal2.java
pacote enumerado.menu;
importar net.mindview.util.*;
enum público Refeição2 {
APETIZER(Comida.Aperitivo.classe),PRATO PRINCIPAL(Comida.CursoPrincipal.classe),SOBREMESA(Comida.Dessert.classe),CAFÉ(Comida.Café.classe);
valores alimentares[] privados;
private Meal2(Class<? estende Comida> tipo) {
valores=kind.getEnumConstants();
}
interface pública Comida {
enum Appetizer implementa Comida {SALAD, SOUP, SPRING_ROLLS;}
enum MainCourse implementa Comida {LASAGNE, BURRITO, PAD_THAI, LENTILS, HUMMOUS, VINDALOO;}
enum Sobremesa implementa Comida {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}
enum Coffee implementa Comida {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
}
comida pública randomSelection() {
retornar Enums.random(valores);
}
public static void main(String[] args) {
for(int i = 0; i < 5; i++) {
for(Refeição2 refeição: Refeição2.valores()) {
Comida comida = refeição.randomSelection();
System.out.println(comida);
}
System.out.println("---");
}
}
} /* Mesma saída que Meal.java *///:~
Use EnumSet em vez de sinalizadores EnumSet foi adicionado em Java SE5 para combinar enums e Sets para substituir sinalizadores de bits baseados em números inteiros. Flags de bit geralmente são usados para indicar a troca de algum tipo de informação, mas no código, os bits são operados em vez de conceitos significativos, portanto, não são fáceis de entender. EnumSet é mais rápido que flags de bit. Ele usa long internamente para representar um vetor de bits, e então você pode usar uma linguagem mais conceitual para representar a troca de um determinado bit sem se preocupar com eficiência. Os elementos em EnumSet devem vir da mesma enumeração. O seguinte define uma enumeração da posição do alarme:
Copie o código do código da seguinte forma:
//: enumerado/AlarmPoints.java
pacote enumerado;
public enum AlarmPoints {ESTADA1, ESCADA2, LOBBY, ESCRITÓRIO1, ESCRITÓRIO2, ESCRITÓRIO3,ESCRITÓRIO4, BANHEIRO, UTILIDADE, COZINHA} ///:~
Em seguida, use a classe EnumSet para rastrear o status do alarme:
Copie o código do código da seguinte forma:
//: enumerado/EnumSets.java
//Operações em EnumSets
pacote enumerado;
importar java.util.*;
importar estática enumerada.AlarmPoints.*;
importar estático net.mindview.util.Print.*;
classe pública EnumSets {
public static void main(String[] args) {
EnumSet<AlarmPoints> points = EnumSet.noneOf(AlarmPoints.class);
pontos.add(BANHEIRO);
imprimir(pontos);
pontos.addAll(EnumSet.of(ESCADA1, ESCADA2, COZINHA));
imprimir(pontos);
pontos = EnumSet.allOf(AlarmPoints.class);
pontos.removeAll(EnumSet.of(ESCADA1, ESCADA2, COZINHA));
imprimir(pontos);
pontos.removeAll(EnumSet.range(OFFICE1, OFFICE4));
imprimir(pontos);
pontos = EnumSet.complementOf(pontos);
imprimir(pontos);
}
} /* Saída:
[BANHEIRO]
[ESCADA 1, ESCADA 2, BANHEIRO, COZINHA]
[LOBBY, ESCRITÓRIO1, ESCRITÓRIO2, ESCRITÓRIO3, ESCRITÓRIO4, BANHEIRO, UTILIDADE]
[LOBBY, BANHEIRO, UTILIDADE]
[ESCADA1, ESCADA2, ESCRITÓRIO1, ESCRITÓRIO2, ESCRITÓRIO3, ESCRITÓRIO4, COZINHA]
*///:~
EnumSet é construído em tipo longo e tem 64 bits, e se nosso tipo de enumeração exceder esse número?
Copie o código do código da seguinte forma:
//: enumerado/BigEnumSet.java
importar java.util.*;
classe pública BigEnumSet {
enum Grande {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);
}
} /* Saída:
[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]
*///:~
Podemos ver que o programa está rodando normalmente, então é muito provável que um tipo longo tenha sido adicionado internamente para ajudar a acomodar o tipo de enumeração usando EnumMap.
EnumMap é um tipo especial de Mapa. O valor de sua chave só pode ser do tipo na mesma enumeração. Por isso, EnumMap pode ser implementado internamente por meio de um array, o que é muito eficiente.
Copie o código do código da seguinte forma:
//: enumerado/EnumMaps.java
// Noções básicas de EnumMaps.
pacote enumerado;
importar java.util.*;
importar estática enumerada.AlarmPoints.*;
importar estático net.mindview.util.Print.*;
comando de interface { void action();
classe pública EnumMaps {
public static void main(String[] args) {
EnumMap<AlarmPoints,Command> em = new EnumMap<AlarmPoints,Command>(AlarmPoints.class);
em.put(COZINHA, new Command() {
public void action() { print("Incêndio na cozinha!");
});
em.put(BANHEIRO, new Command() {
public void action() { print("Alerta de banheiro!");
});
for(Map.Entry<AlarmPoints,Command> e : em.entrySet()) {
printnb(e.getKey() + ": ");
e.getValue().action();
}
try { // Se não houver valor para uma chave específica:
em.get(UTILIDADE).action();
} catch(Exceção e) {
imprimir(e);
}
}
} /* Saída:
BANHEIRO: Alerta de banheiro!
COZINHA: Fogo na cozinha!
java.lang.NullPointerException
*///:~
Métodos constantes específicos As enumerações Java possuem uma característica muito interessante, ou seja, diferentes comportamentos podem ser definidos para cada instância de enumeração. Para conseguir isso, definimos um ou mais métodos abstratos como parte da enumeração e, em seguida, definimos diferentes comportamentos para cada um. instância de enumeração. Um método de definição de instância de enumeração:
Copie o código do código da seguinte forma:
//: enumerado/ConstantSpecificMethod.java
importar java.util.*;
importar java.texto.*;
public enum ConstantSpecificMethod {
DATE_TIME {String getInfo() {return DateFormat.getDateInstance().format(new Date());}},
CLASSPATH {String getInfo() {return System.getenv("CLASSPATH");}},
VERSÃO {String getInfo() {return System.getProperty("java.version");}};
string abstrata getInfo();
public static void main(String[] args) {
for (ConstantSpecificMethod csm: valores ())
System.out.println(csm.getInfo());
}
} /* (Execute para ver a saída) *///:~
O código acima parece estar preso ao fato de que cada elemento de enumeração é um elemento diferente e todos os elementos herdam da classe base ConstantSpecificMethod, mas não podemos realmente entendê-lo desta forma, porque não podemos tratar os elementos de enumeração como tipos:
Copie o código do código da seguinte forma:
//: enumerado/NotClasses.java
// {Exec: javap -c LikeClasses}
importar estático net.mindview.util.Print.*;
enum LikeClasses {WINKEN { comportamento void() { print("Comportamento1"); },BLINKEN { comportamento void() { print("Comportamento2"); ; } };
comportamento de vazio abstrato();
}
classe pública NotClasses {
// void f1(instância LikeClasses.WINKEN) {} // Não
} /* Saída:
Compilado de "NotClasses.java"
classe abstrata LikeClasses estende java.lang.Enum{
public static final LikeClasses WINKEN;
público estático final LikeClasses BLINKEN;
público estático final LikeClasses NOD;
...
*///:~
Considere outro exemplo. Há um menu de lavagem de carros. Os clientes escolhem serviços diferentes com base em menus diferentes. Você pode usar métodos constantes específicos para associar o menu aos serviços e usar EnumSet para manter as escolhas do cliente, como segue:
Copie o código do código da seguinte forma:
//: enumerado/CarWash.java
importar java.util.*;
importar estático net.mindview.util.Print.*;
classe pública Lava-jato {
public enum Cycle {UNDERBODY {void action() { print("Pulverizando a parte inferior do corpo" }},
WHEELWASH {void action() { print("Lavando as rodas" }},
PRÉ-LAVAGEM {void action() { print("Afrouxando a sujeira" }},
BASIC {void action() { print("A lavagem básica" }},
HOTWAX {void action() { print("Aplicando cera quente" }},
ENXAGUAR {void action() { print("Enxaguando" }},
BLOWDRY {void action() { print("Secar" }};
ação nula abstrata();
}
EnumSet<Ciclo> ciclos = EnumSet.of(Cycle.BASIC, Cycle.RINSE);
public void add(Ciclo ciclo) {cycles.add(ciclo });
public void washCar() {
para (Ciclo c: ciclos)
c.ação();
}
public String toString() { return ciclos.toString() };
public static void main(String[] args) {
Lavagem de Carro = new Lavagem de Carro();
imprimir(lavar);
lavar.lavarCarro();
// A ordem de adição não é importante:
lavar.add(Ciclo.BLOWDRY);
wash.add(Cycle.BLOWDRY); // Duplicatas ignoradas
lavar.adicionar(Ciclo.RINSE);
lavar.add(Ciclo.CERA QUENTE);
imprimir(lavar);
lavar.lavarCarro();
}
} /* Saída:
[BÁSICO, ENXAGUAR]
A lavagem básica
Lavagem
[BÁSICO, CERA QUENTE, ENXAGUAR, SECAR]
A lavagem básica
Aplicando cera quente
Lavagem
Secar
*///:~
Também podemos substituir os métodos constantes específicos padrão em vez de usar métodos abstratos herdados, como segue:
Copie o código do código da seguinte forma:
//: enumerado/OverrideConstantSpecific.java
importar estático net.mindview.util.Print.*;
enum público OverrideConstantSpecific {
PORCA, PARAFUSO, ARRUELA {void f() { print("Método substituído" }};
void f() { print("comportamento padrão");
public static void main(String[] args) {
for(OverrideConstantSpecific ocs: valores()) {
printnb(ocs + ": ");
ocs.f();
}
}
} /* Saída:
PORCA: comportamento padrão
PARAFUSO: comportamento padrão
LAVADORA: método substituído
*///:~
Às vezes, queremos passar solicitações específicas na cadeia. Saber que um objeto na cadeia pode lidar com a solicitação pode ser facilmente alcançado usando métodos constantes específicos.
Copie o código do código da seguinte forma:
//: enumerado/PostOffice.java
// Modelando uma agência postal.
Tipos Enumerados 743
importar java.util.*;
importar net.mindview.util.*;
importar estático net.mindview.util.Print.*;
classe Correio {
// Os NÃO diminuem a probabilidade de seleção aleatória:
enum GeneralDelivery {SIM,NO1,NO2,NO3,NO4,NO5}
enum Scannability {UNSCANNABLE,YES1,YES2,YES3,YES4}
Legibilidade enum {ILEGÍVEL, SIM1, SIM2, SIM3, SIM4}
Endereço enum {INCORRETO,OK1,OK2,OK3,OK4,OK5,OK6}
enum ReturnAddress {FALTA, OK1, OK2, OK3, OK4, OK5}
GeralEntrega geralEntrega;
Escaneabilidade;
Legibilidade legibilidade;
Endereço de endereço;
ReturnAddress returnAddress;
contador longo estático = 0;
id longo = contador++;
public String toString() { return "Correio" + id };
detalhes da string pública() {
return toString() + ", Entrega Geral: " + generalDelivery + ", Escaneabilidade de endereço: " + escaneabilidade + ", Legibilidade de endereço: " + legibilidade +
", Endereço Endereço: " + endereço + ", Endereço de retorno: " + returnAddress;
}
//Gerar e-mail de teste:
correio estático público randomMail() {
Correio m = novo Correio();
m.generalDelivery=Enums.random(GeneralDelivery.class);
m.scannability = Enums.random(Scannability.class);
m.readability = Enums.random(Legibilidade.class);
m.address = Enums.random(Address.class);
m.returnAddress = Enums.random(ReturnAddress.class);
retornar m;
}
public static Iterable<Mail> gerador(contagem final int) {
return new Iterable<Mail>() {
int n = contagem;
public Iterator<Mail> iterator() {
return new Iterator<Mail>() {
public boolean hasNext() { return n-- > 0 };
correio público next() { return randomMail() };
public void remove() { // Não implementado
lançar new UnsupportedOperationException();
}
};
}
};
}
}
classe pública Correios {
enum MailHandler{
GENERAL_DELIVERY {
identificador booleano (Correio m) {
switch(m.generalDelivery) {
caso SIM:
print("Usando entrega geral para " + m);
retornar verdadeiro;
padrão: retornar falso;
}
}
},
MÁQUINA_SCAN {
identificador booleano (Correio m) {
switch(m.scanabilidade) {
caso NÃO ESCANÁVEL: retorne falso;
padrão:
switch(m.endereço) {
case INCORRETO: retorna falso;
padrão:
print("Entrega "+ m + " automaticamente");
retornar verdadeiro;
}
}
}
},
INSPEÇÃO_VISUAL {
identificador booleano (Correio m) {
switch (m. legibilidade) {
case ILEGÍVEL: retorne falso;
padrão:
switch(m.endereço) {
case INCORRETO: retorna falso;
padrão:
print("Entregando " + m + " normalmente");
retornar verdadeiro;
}
}
}
},
RETURN_TO_SENDER {
identificador booleano (Correio m) {
switch(m.returnAddress) {
case MISSING: retorne falso;
padrão:
print("Retornando " + m + " ao remetente");
retornar verdadeiro;
}
}
};
identificador booleano abstrato (Mail m);
}
identificador vazio estático (Correio m) {
for (manipulador MailHandler: MailHandler.values())
if(manipulador.handle(m))
retornar;
print(m + "é letra morta");
}
public static void main(String[] args) {
for(Correio: Mail.generator(10)) {
imprimir(mail.detalhes());
lidar(correio);
imprimir("*****");
}
}
} /* Saída:
Correio 0, entrega geral: NO2, capacidade de digitalização de endereço: UNSCANNABLE, legibilidade de endereço: YES3, endereço de endereço: OK1, endereço de retorno: OK1
Entregando Mail 0 normalmente
*****
Correio 1, entrega geral: NO5, capacidade de digitalização de endereço: SIM3, legibilidade de endereço: ILEGÍVEL, endereço: OK5, endereço de retorno: OK1
Entregando Mail 1 automaticamente
*****
Correio 2, entrega geral: SIM, capacidade de digitalização de endereço: SIM3, legibilidade de endereço: SIM1, endereço de endereço: OK1, endereço de retorno: OK5
Usando entrega geral para Mail 2
*****
Correio 3, entrega geral: NO4, capacidade de digitalização de endereço: SIM3, legibilidade de endereço: SIM1, endereço: INCORRETO, endereço de retorno: OK4
Devolvendo o Mail 3 ao remetente
*****
Correio 4, Entrega Geral: NO4, Capacidade de Escaneamento de Endereço: INESQUECÍVEL, Legibilidade de Endereço: SIM1, Endereço: INCORRETO, Endereço de retorno: OK2
Devolvendo o Mail 4 ao remetente
*****
Correio 5, entrega geral: NO3, capacidade de digitalização de endereço: SIM1, legibilidade de endereço: ILEGÍVEL, endereço: OK4, endereço de retorno: OK2
Entregando Mail 5 automaticamente
*****
Correio 6, entrega geral: SIM, capacidade de digitalização de endereço: SIM4, legibilidade de endereço: ILEGÍVEL, endereço: OK4, endereço de retorno: OK4
Usando entrega geral para Mail 6
*****
Correio 7, entrega geral: SIM, capacidade de digitalização de endereço: SIM3, legibilidade de endereço: SIM4, endereço de endereço: OK2, endereço de retorno: MISSING
Usando entrega geral para Mail 7
*****
Correio 8, entrega geral: NO3, capacidade de digitalização de endereço: SIM1, legibilidade de endereço: SIM3, endereço: INCORRETO, endereço de retorno: FALTA
Mail 8 é letra morta
*****
Correio 9, entrega geral: NO1, capacidade de digitalização de endereço: UNSCANNABLE, legibilidade de endereço: YES2, endereço de endereço: OK1, endereço de retorno: OK4
Entregando Mail 9 normalmente
*****
*///:~
O tipo de enumeração também é um tipo ideal para criar uma máquina de estado. Uma máquina de estado pode mover-se entre um número limitado de estados de acordo com a entrada e, em seguida, encerrar o trabalho após um determinado estado ser atingido. saída correspondente. Uma máquina de venda automática é um exemplo de máquina de estado típica onde definimos diferentes entradas dentro de uma enumeração:
Copie o código do código da seguinte forma:
//: enumerado/Input.java
pacote enumerado;
importar java.util.*;
entrada de enum público {
NÍQUEL (5), DIME (10), QUARTER (25), DÓLAR (100), PASTA DE DENTE (200), CHIPS (75), SODA (100), SABÃO (50), ABORT_TRANSACTION {
public int amount() { // Não permitir
lançar new RuntimeException("ABORT.amount()");
}
},
STOP { // Esta deve ser a última instância.
public int amount() { // Não permitir
lançar new RuntimeException("SHUT_DOWN.amount()");
}
};
valor interno // Em centavos
Entrada(int valor) { this.value = valor };
Entrada() {}
int quantidade() { valor de retorno };
Rand aleatório estático = novo aleatório (47);
entrada estática pública randomSelection() {
// Não inclua STOP:
retornar valores()[rand.nextInt(valores().comprimento - 1)];
}
} ///:~
VendingMachine é usado para responder à entrada. Primeiro, ele classifica a entrada por meio da enumeração de categoria e, em seguida, usa a instrução switch:
Copie o código do código da seguinte forma:
//: enumerado/VendingMachine.java
// {Args: VendingMachineInput.txt}
pacote enumerado;
importar java.util.*;
importar net.mindview.util.*;
importar enumerado estático.Input.*;
importar estático net.mindview.util.Print.*;
enum Categoria {
DINHEIRO(NÍQUEL, DIME, QUARTER, DOLLAR),ITEM_SELECTION(PASTA DE DENTE, CHIPS, REFRIGERANTE, SABÃO),QUIT_TRANSACTION(ABORT_TRANSACTION),SHUT_DOWN(STOP);
valores de entrada[] privados;
Categoria(Entrada... tipos) { valores = tipos };
private static EnumMap<Input,Category> categorias = new EnumMap<Input,Category>(Input.class);
estático {
for (Categoria c: Categoria.class.getEnumConstants())
for (tipo de entrada: c.valores)
categorias.put(tipo, c);
}
categoria estática pública categorizar (entrada de entrada) {
retornar categorias.get(entrada);
}
}
classe pública Máquina de Vendas {
Estado estático privado estado = State.RESTING;
quantidade int estática privada = 0;
seleção de entrada estática privada = null;
enum StateDuration {TRANSIENT} //Marcando enum
Estado enum {
DESCANSO {
void próximo(Entrada entrada) {
switch(Categoria.categorize(entrada)) {
caso DINHEIRO:
quantidade += input.quantidade();
estado = ADICIONANDO_MONEY;
quebrar;
caso SHUT_DOWN:
estado = TERMINAL;
padrão:
}
}
},
ADDING_MONEY {
void próximo(Entrada entrada) {
switch(Categoria.categorize(entrada)) {
caso DINHEIRO:
quantidade += input.quantidade();
quebrar;
caso ITEM_SELECTION:
seleção = entrada;
if(quantidade < seleção.quantidade())
print("Dinheiro insuficiente para " + seleção);
senão estado = DISPENSANDO;
quebrar;
caso QUIT_TRANSACTION:
estado=GIVING_CHANGE;
quebrar;
caso SHUT_DOWN:
estado = TERMINAL;
padrão:
}
}
},
DISPENSING(StateDuration.TRANSIENT) {
void próximo() {
print("aqui está sua " + seleção);
quantidade -= seleção.quantidade();
estado=GIVING_CHANGE;
}
},
GIVING_CHANGE(EstadoDuration.TRANSIENT) {
void próximo() {
if(quantidade > 0) {
print("Seu troco: " + valor);
quantidade = 0;
}
estado = DESCASCANDO;
}
},
TERMINAL { void saída() { print("Parado");
booleano privado isTransient = false;
Estado() {}
State(StateDuration trans) { isTransient = true };
void próximo(Entrada entrada) {
throw new RuntimeException("Somente chamada " + "next(Entrada) para estados não transitórios");
}
void próximo() {
throw new RuntimeException("Chame next() apenas para estados " + "StateDuration.TRANSIENT");
}
void saída() { imprimir(quantidade });
}
static void run(Generator<Input>gen) {
while(estado! = Estado.TERMINAL) {
estado.next(gen.next());
enquanto(estado.isTransient)
estado.próximo();
estado.saída();
}
}
public static void main(String[] args) {
Generator<Input> gen = new RandomInputGenerator();
if(args.comprimento == 1)
gen = novo FileInputGenerator(args[0]);
executar(gen);
}
}
// Para uma verificação básica de integridade:
class RandomInputGenerator implementa Generator<Input> {
entrada pública next() { return Input.randomSelection();
}
// Cria entradas a partir de um arquivo de strings separadas por ';':
class FileInputGenerator implementa Generator<Input> {
entrada privada Iterator<String>;
public FileInputGenerator(String nomeArquivo) {
input = new TextFile(fileName, ";").iterator();
}
entrada pública próximo() {
if(!input.hasNext())
retornar nulo;
return Enum.valueOf(Input.class, input.next().trim());
}
} /* Saída:
aqui estão seus CHIPS
aqui está sua pasta de dentes
Sua mudança: 35
Dinheiro insuficiente para SODA
Dinheiro insuficiente para SODA
Sua mudança: 75
Parado
*///:~
Aqui estão os dados de teste usados para gerar a saída acima:
Copie o código do código da seguinte forma:
TRIMESTRE; TRIMESTRE;
DÓLAR; DÓLAR;
TRIMESTRE;
QUARTO;
QUARTO; NÍQUEL;
ABORT_TRANSACTION;
PARAR;
///:~
Descompactação múltipla Ao lidar com interações entre vários tipos, o código provavelmente ficará confuso, como Number.plush(Number), Number.mutiply(Number), etc. Number é apenas uma classe base da família, então quando você chama Quando a.plus(b), você não conhece o tipo de a nem o tipo de b, então como garantir que a interação entre eles esteja correta? Java só pode realizar descompactação única, ou seja, se uma ou mais operações de vários tipos desconhecidos forem executadas, Java só poderá realizar um mecanismo de ligação dinâmica em um dos tipos, o que não pode resolver o problema de que falamos acima, então você tem. para escrever manualmente o código de ligação dinâmica.
A solução é usar multibinding. O polimorfismo só pode ocorrer ao chamar um método, portanto, se você precisar de descompactar vários, deverá chamar vários métodos. Com desembrulhamento múltiplo, você deve ter um método virtual que chame o método de cada tipo para desembrulhar. O exemplo a seguir é um exemplo de pedra-papel-tesoura:
Copie o código do código da seguinte forma:
//: enumerado/Outcome.java
pacote enumerado;
Public enum Resultado { GANHAR, PERDER, DRAW } ///:~
//: enumerado/RoShamBo1.java
// Demonstração de despacho múltiplo.
pacote enumerado;
importar java.util.*;
importar enumerado estático.Resultado.*;
item de interface {
Resultado competir(Item it);
Avaliação do resultado (Artigo p);
Avaliação de resultado (Tesoura);
Avaliação do resultado (Rock r);
}
classe Papel implementa Item {
Resultado público compete (Item it) { return it.eval (this });
avaliação de resultado público (artigo p) { return DRAW }
avaliação de resultado público (tesoura) { return WIN };
avaliação de resultado público (Rock r) { return PERDER };
public String toString() { return "Papel" };
}
class Tesoura implementa Item {
Resultado público compete (Item it) { return it.eval (this });
avaliação de resultado público (artigo p) { return PERDER };
avaliação de resultado público (tesoura) { return DRAW }
avaliação de resultado público (Rock r) { return WIN };
public String toString() { return "Tesoura";
}
classe Rock implementa Item {
Resultado público compete (Item it) { return it.eval (this });
avaliação de resultado público (artigo p) { return WIN };
avaliação de resultado público (Tesoura s) { return PERDER };
avaliação de resultado público (Rock r) { return DRAW }
public String toString() { return "Rocha" };
}
classe pública RoShamBo1 {
Tamanho final estático de int = 20;
Rand aleatório estático privado = novo aleatório (47);
Item estático público newItem () {
Switch (Rand.NextInt (3)) {
padrão:
Caso 0: Return New Scissors ();
Caso 1: Retorne New Paper ();
Caso 2: Retorne 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 <tamanho; i ++)
match (newItem (), newItem ());
}
} /* Saída:
Rock vs. Rock: Draw
Papel vs. Rock: Win
Papel vs. Rock: Win
Papel vs. Rock: Win
Tesoura vs. papel: vencer
Tesoura vs. tesoura: desenhar
Tesoura vs. papel: vencer
Rock vs. Paper: Perca
Papel vs. Papel: Desenho
Rock vs. Paper: Perca
Papel vs. tesoura: perder
Papel vs. tesoura: perder
Rock vs. Scissors: Win
Rock vs. Paper: Perca
Papel vs. Rock: Win
Tesoura vs. papel: vencer
Papel vs. tesoura: perder
Papel vs. tesoura: perder
Papel vs. tesoura: perder
Papel vs. tesoura: perder
*///: ~
Utilizamos muitos métodos para obter múltiplas descompactos, mas o que obtivemos foi uma boa estrutura de código. O maior problema ao usar uma solução de enumeração para implementar o código acima é que a instância de enumeração não é um tipo; portanto, a instância de enumeração não pode ser usada como o tipo de parâmetro. Mas ainda podemos ter outras maneiras de contornar esse obstáculo.
Copie o código do código da seguinte forma:
//: enumerado/roshambo2.java
// alternar um enumeração em outro.
pacote enumerado;
importar enumerado estático.outcome.*;
Public Enum Roshambo2 implementa o concorrente <Roshambo2> {
Papel (desenhar, perder, ganhar), tesoura (vencer, empatar, perder), rock (perder, ganhar, empatar);
Resultado privado VPAPAR, VSCISSSOR, VROCK;
Roshambo2 (papel de resultado, tesouras de resultado, resultado rock) {
this.vpaper = papel;
this.vscisSors = tesoura;
this.vrock = rock;
}
Resultado público Compete (Roshambo2 It) {
Switch (it) {
padrão:
Papel de caixa: retornar VPAPER;
Tesoura de caso: retornar Vscissors;
Case Rock: Return Vrock;
}
}
public static void main(String[] args) {
Roshambo.Play (Roshambo2.class, 20);
}
} /* Saída:
Rock vs. Rock: Draw
Tesoura vs. Rock: Lose
Tesoura vs. Rock: Lose
Tipos enumerados 753
Tesoura vs. Rock: Lose
Papel vs. tesoura: perder
Papel vs. Papel: Desenho
Papel vs. tesoura: perder
Rock vs. Scissors: Win
Tesoura vs. tesoura: desenhar
Rock vs. Scissors: Win
Tesoura vs. papel: vencer
Tesoura vs. papel: vencer
Rock vs. Paper: Perca
Rock vs. Scissors: Win
Tesoura vs. Rock: Lose
Papel vs. tesoura: perder
Tesoura vs. papel: vencer
Tesoura vs. papel: vencer
Tesoura vs. papel: vencer
Tesoura vs. papel: vencer
*///: ~
Copie o código do código da seguinte forma:
//: enumerado/competitor.java
// alternar um enumeração em outro.
pacote enumerado;
Public Interface Contester <T estende o concorrente <T>> {
RESULTADO COMPETO (CO CONCEITOR);
} ///: ~
Copie o código do código da seguinte forma:
//: enumerado/roshambo.java
// Ferramentas comuns para exemplos de Roshambo.
pacote enumerado;
importação net.mindview.util.*;
classe pública Roshambo {
public static <t estende o concorrente <T>> Void Match (t a, t b) {
System.out.println (a + "vs." + b + ":" + a.compete (b));
}
public static <t estende enum <t> & concorrente <t>> void play (classe <T> rsbclass, int size) {
for (int i = 0; i <tamanho; i ++)
match (enums.random (rsbclass), enums.random (rsbclass));
}
} ///: ~
Como a formulação de métodos estáticos pode fornecer métodos diferentes para cada tipo de enumeração, parece ser uma boa solução para obter múltiplas descompacções, mas ainda enfrentamos o problema de que a instância de enumeração não é um tipo, então tudo o que podemos fazer é adicionar uma instrução Switch :
Copie o código do código da seguinte forma:
//: enumerado/roshambo3.java
// usando métodos específicos constantes.
pacote enumerado;
importar enumerado estático.outcome.*;
Public Enum Roshambo3 implementa o concorrente <Roshambo3> {
PAPEL {
Resultado público Compete (Roshambo3 It) {
Switch (it) {
padrão: // para colocar o compilador
Papel de caixa: Desenho de retorno;
Tesoura de caso: Retornar Lose;
Case Rock: Win Return Win;
}
}
},
TESOURA {
Resultado público Compete (Roshambo3 It) {
Switch (it) {
padrão:
Papel de caso: retornar a vitória;
Tesoura de caso: Return Draw;
Case Rock: Return Lose;
}
}
},
PEDRA {
Resultado público Compete (Roshambo3 It) {
Switch (it) {
padrão:
papel de caso: retornar perca;
Tesoura de caso: Win Return Win;
Case Rock: Draw Return Draw;
}
}
};
Resumo do Público Resumo Compete (Roshambo3 IT);
public static void main(String[] args) {
Roshambo.Play (Roshambo3.class, 20);
}
}/ * Mesma saída que Roshambo2.java * ///: ~
O código a seguir é um método de implementação mais conciso:
Copie o código do código da seguinte forma:
//: enumerado/roshambo4.java
pacote enumerado;
Public Enum Roshambo4 implementa o concorrente <Roshambo4> {
PEDRA {
Resultado público Compete (oponente Roshambo4) {
Return Compete (tesoura, oponente);
}
},
TESOURA {
Resultado público Compete (oponente Roshambo4) {
Return Compete (papel, oponente);
}
},
PAPEL {
Resultado público Compete (oponente Roshambo4) {
Return Compete (Rock, oponente);
}
};
Competição de resultado (Loser de Roshambo4, oponente Roshambo4) {
return ((oponente == this)? Resultado.draw: ((oponente == perdedor)? Resultado.win: outcome.lose));
}
public static void main(String[] args) {
Roshambo.Play (Roshambo4.class, 20);
}
}/ * Mesma saída que Roshambo2.java * ///: ~
A classe Enummap parece ser uma boa maneira de realmente implementar vários descompactadores:
Copie o código do código da seguinte forma:
//: enumerado/roshambo5.java
// Despacho múltiplo usando um enummap de enummaps.
pacote enumerado;
importar java.util.*;
importar enumerado estático.outcome.*;
Enum Roshambo5 implementa o concorrente <Roshambo5> {
Papel, tesoura, rocha;
estático enummap <roshambo5, enummap <roshambo5, resultado >> tabela = new Enummap <roshambo5, enummap <roshambo5, resultado >> (roshambo5.class);
estático {
para (Roshambo5 It: Roshambo5.Values ())
tabela.put (it, new enummap <roshambo5, resultado> (roshambo5.class));
initrow (papel, desenhar, perder, ganhar);
initrow (tesoura, ganha, empate, perde);
initrow (rock, perder, ganhar, empatar);
}
estático void initrow (roshambo5 it, resultado vpaper, resultado vscissors, resultado vrock) {
Enummap <roshambo5, resultado> linha = roshambo5.table.get (it);
row.put (Roshambo5.Paper, Vpaper);
row.put (roshambo5.scisssors, vscissors);
row.put (roshambo5.rock, vrock);
}
Resultado público Compete (Roshambo5 it) {
retornar tabela.get (this) .get (it);
}
public static void main(String[] args) {
Roshambo.Play (Roshambo5.class, 20);
}
}/ * Mesma saída que Roshambo2.java * ///: ~
Também podemos usar o recurso de instâncias de enumeração com valores fixos para usar os dados para o método de implementação mais simples.
Copie o código do código da seguinte forma:
//: enumerado/roshambo6.java
// enums usando "tabelas" em vez de despacho múltiplo.
pacote enumerado;
importar enumerado estático.outcome.*;
Enum Roshambo6 implementa o concorrente <Roshambo6> {
Papel, tesoura, rocha;
Resultado estático privado [] [] tabela = {
{Desenhar, perder, vencer}, // papel
{Win, Draw, Lose}, // tesoura
{Lose, Win, Draw}, // Rock
};
Resultado público Compete (Roshambo6 Outros) {
tabela de retorno [this.ordinal ()] [OUTRO.ORDINAL ()];
}
public static void main(String[] args) {
Roshambo.Play (Roshambo6.class, 20);
}
} ///: ~