As enum
represent a fixed set of values in a more or less self-documented. Make code more explicit, more readable, and less vulnerable to programming errors.
A common alternative is to use String
or int
for constant values. The enum
bring some advantages in relation to these types:
Compiler does not allow typographical errors, as can happen with string literals.
The compiler does not allow values that are outside the enumerated set, which is a consequence of the enumerations being guys themselves.
No need to write preconditions, or manual testing to ensure that the argument of a method is within the accepted range of values.
The type invariant is free, again because the enumerations are types, and define in the beginning the valid values.
Enumerations can define demeanor (methods) for their constants, as in any usual class.
The constants of an enumeration may specify their behavior: each constant may have its own definition of a method.
The virtual machine guarantees thread Safety when loading the enumeration.
Can also be used in switch
.
There are still some creative uses of enumerations, such as state machines, as seen on this blog.
Let’s take a practical example of these advantages. Imagine a program that receives two colors and tries to combine them, according to the RGB system.
Using int
public static final int
VERMELHO = 1,
AZUL = 2,
VERDE = 4,
AMARELO = 5,
CIANO = 6,
ROXO = 3,
BRANCO = 7;
/**
* @pre cor1 == VERMELHO || cor1 == AZUL || cor1 == VERDE ||
* cor1 == CIANO || cor1 == AMARELO || cor1 == ROXO || cor1 == BRANCO;
* @pre cor2 == VERMELHO || cor2 == AZUL || cor2 == VERDE ||
* cor2 == CIANO || cor2 == AMARELO || cor2 == ROXO || cor2 == BRANCO;
* @post cor1 == VERMELHO && cor2 == VERDE => return == AMARELO;
* @post ...
*/
public static int combina(int cor1, int cor2) {
if (!corValida(cor1)) return -1;
if (!corValida(cor2)) return -1;
return cor1 | cor2;
}
private boolean corValida(int cor) {
return cor == VERMELHO || cor == VERDE || cor == AZUL ||
cor == AMARELO || cor == CIANO || cor == ROXO || cor == BRANCO;
}
public static void main(String[] args) {
int cor = combina(1, 2);
// O que acontece quando VERMELHO e AZUL deixam de ser 1 ou 2?
assert cor == ROXO;
}
Using enum
/*
* Os codigos numéricos não fazem qualquer falta.
* Seria possível resolver com switch, mas ficaria muito extenso para exemplo.
* Contudo, um caso real deveria retirar os códigos,
* para maiores garantias de que não há erro humano.
*/
public static enum Cor {
VERMELHO(1), AZUL(2), VERDE(4), AMARELO(5), CIANO(6), ROXO(3), BRANCO(7);
private final int codigo;
Cor(int codigo) { this.codigo = codigo; }
int codigo() { return codigo; }
public static Cor porCodigo(int codigo) {
for (Cor cor: Cor.values()) {
if (codigo == cor.codigo()) return cor;
}
throw new IllegalArgumentException("codigo invalido");
}
}
/**
* @pre cor1 != null && cor2 != null;
* @post cor1 == Cor.VERMELHO && cor2 == Cor.VERDE => return == Cor.AMARELO;
* @post ...
*/
public static int combina(Cor cor1, Cor cor2) {
int combinado = cor1.codigo() | cor2.codigo();
return Cor.porCodigo(combinado);
}
public static void main(String[] args) {
Cor cor = combina(Cor.VERMELHO, Cor.AZUL);
assert cor == Cor.ROXO;
}
I really liked the answer! However, considering that she asks a question from the point of view of someone who is beginner in language, I think it would be interesting to add some examples of code. :)
– Luiz Vieira
@Luizvieira Thank you so much for the tip! I added an example using
int
and the same example withenum
, to mark the difference between the two. :)– afsantos