Gli enumerati Java sono fantastici. Lo sono anche i generici. Naturalmente conosciamo tutti i limiti di quest'ultimo a causa della cancellazione del tipo. Ma c'è una cosa che non capisco, perché non posso creare un enum come questo:
public enum MyEnum<T> {
LITERAL1<String>,
LITERAL2<Integer>,
LITERAL3<Object>;
}
Questo parametro di tipo generico <T>
a sua volta potrebbe quindi essere utile in vari punti. Immagina un parametro di tipo generico in un metodo:
public <T> T getValue(MyEnum<T> param);
O anche nella stessa classe enum:
public T convert(Object o);
Esempio più concreto n. 1
Poiché l'esempio sopra potrebbe sembrare troppo astratto per alcuni, ecco un esempio più reale del perché voglio farlo. In questo esempio voglio usare
- Enum, perché poi posso enumerare un set finito di chiavi di proprietà
- Generici, perché allora posso avere una sicurezza del tipo a livello di metodo per la memorizzazione delle proprietà
public interface MyProperties {
public <T> void put(MyEnum<T> key, T value);
public <T> T get(MyEnum<T> key);
}
Esempio più concreto n. 2
Ho un elenco di tipi di dati:
public interface DataType<T> {}
public enum SQLDataType<T> implements DataType<T> {
TINYINT<Byte>,
SMALLINT<Short>,
INT<Integer>,
BIGINT<Long>,
CLOB<String>,
VARCHAR<String>,
...
}
Ogni enum letterale avrebbe ovviamente proprietà aggiuntive basate sul tipo generico <T>
, mentre allo stesso tempo sarebbe un enum (immutabile, singleton, enumerabile, ecc. Ecc.)
Domanda:
Nessuno ci ha pensato? Si tratta di una limitazione relativa al compilatore? Considerando il fatto che la parola chiave " enum " è implementata come zucchero sintattico, che rappresenta il codice generato per la JVM, non capisco questa limitazione.
Chi può spiegarmelo? Prima di rispondere, considera questo:
- So che i tipi generici vengono cancellati :-)
- So che ci sono soluzioni alternative usando gli oggetti Class. Sono soluzioni alternative.
- I tipi generici generano cast di tipi generati dal compilatore ove applicabile (ad es. Quando si chiama il metodo convert ()
- Il tipo generico <T> sarebbe sull'enum. Quindi è vincolato da ciascuno dei letterali dell'enum. Quindi il compilatore saprebbe quale tipo applicare per scrivere qualcosa di simile
String string = LITERAL1.convert(myObject); Integer integer = LITERAL2.convert(myObject);
- Lo stesso vale per il parametro di tipo generico nel
T getvalue()
metodo. Il compilatore può applicare il cast di tipo durante la chiamataString string = someClass.getValue(LITERAL1)
enum
linguaggio in un linguaggio "typesafe enum" che abbiamo usato prima di Java 1.5. All'improvviso, puoi far parametrizzare i tuoi membri enum. Questo è probabilmente quello che farò ora.