Enums de Java são ótimas. O mesmo acontece com os genéricos. É claro que todos sabemos as limitações deste último por causa do apagamento de tipo. Mas há uma coisa que não entendo: por que não consigo criar uma enumeração como esta:
public enum MyEnum<T> {
LITERAL1<String>,
LITERAL2<Integer>,
LITERAL3<Object>;
}
Esse parâmetro de tipo genérico, <T>
por sua vez, pode ser útil em vários locais. Imagine um parâmetro de tipo genérico para um método:
public <T> T getValue(MyEnum<T> param);
Ou mesmo na própria classe enum:
public T convert(Object o);
Exemplo mais concreto nº 1
Como o exemplo acima pode parecer abstrato demais para alguns, aqui está um exemplo mais real do porquê eu quero fazer isso. Neste exemplo eu quero usar
- Enums, porque então eu posso enumerar um conjunto finito de chaves de propriedade
- Genéricos, porque então eu posso ter segurança de tipo no nível do método para armazenar propriedades
public interface MyProperties {
public <T> void put(MyEnum<T> key, T value);
public <T> T get(MyEnum<T> key);
}
Exemplo mais concreto # 2
Eu tenho uma enumeração de tipos de dados:
public interface DataType<T> {}
public enum SQLDataType<T> implements DataType<T> {
TINYINT<Byte>,
SMALLINT<Short>,
INT<Integer>,
BIGINT<Long>,
CLOB<String>,
VARCHAR<String>,
...
}
Cada literal de enumeração obviamente teria propriedades adicionais baseadas no tipo genérico <T>
, enquanto ao mesmo tempo seria uma enumeração (imutável, singleton, enumerável, etc. etc.)
Questão:
Ninguém pensou nisso? Isso é uma limitação relacionada ao compilador? Considerando o fato de que a palavra-chave " enum " é implementada como açúcar sintático, representando o código gerado para a JVM, não entendo essa limitação.
Quem pode me explicar isso? Antes de responder, considere o seguinte:
- Eu sei que tipos genéricos são apagados :-)
- Eu sei que existem soluções alternativas usando objetos de classe. Eles são soluções alternativas.
- Tipos genéricos resultam em transmissões de tipos gerados pelo compilador sempre que aplicável (por exemplo, ao chamar o método convert ()
- O tipo genérico <T> estaria na enumeração. Portanto, ele é vinculado por cada um dos literais da enumeração. Portanto, o compilador saberia qual tipo aplicar ao escrever algo como
String string = LITERAL1.convert(myObject); Integer integer = LITERAL2.convert(myObject);
- O mesmo se aplica ao parâmetro de tipo genérico no
T getvalue()
método O compilador pode aplicar a conversão de tipo ao chamarString string = someClass.getValue(LITERAL1)
enum
idioma em "typesafe enum" que usamos antes do Java 1.5. De repente, você pode ter seus membros da enum parametrizados. Provavelmente é o que vou fazer agora.