2010-12-10 97 views
4

J'utilise Java 6.Est-il possible de créer des énumérations Java en fonction du fichier d'entrée?

Supposons que je dispose d'un fichier availableFruits.txt

APPLE 
ORANGE 
BANANA 

Je veux un Suppose ENUM FruitType qui contient des valeurs figurant dans availableFruits.txt, je serai en mesure de le faire?

+0

Je ne crois pas que cela puisse être fait. Nous verrons si quelqu'un d'autre sait mieux que moi. – duffymo

+0

Pourquoi? Vous avez la réponse à la question que vous avez réellement posée ci-dessous (deux choix, essentiellement: «non» et «oui, mais c'est difficile et je ne peux pas imaginer pourquoi vous voudriez»). Mais vous pourriez envisager de poster une nouvelle question décrivant le problème que vous tentez de résoudre - vous obtiendrez probablement des suggestions utiles sur la façon de l'aborder (il ne s'agit presque certainement pas de générer une énumération au moment de l'exécution). –

+0

@ T.J. Crowder, c'est par curiosité. Je veux mieux connaître Java et ses limites. – Russell

Répondre

3

Vous ne pouvez pas remplir un type d'énumération à l'exécution, non - au moins, pas sans quelque chose comme BCEL, ou en appelant le compilateur Java.

Vous pouvez écrire du code pour créer un fichier source Java, bien sûr, et le créer lorsque vous construisez votre application, si vous n'avez pas besoin de le modifier par la suite. Dans le cas contraire, je créerais simplement une classe wrapper capable de prendre un ensemble de valeurs connues et de les réutiliser. Exactement ce que vous devez faire dépendra de la façon dont vous voulez utiliser l'énumération, bien sûr.

0

Non, sauf si vous générez le fichier source enum à partir du fichier texte.

1

j'attendre à ce qu'il est possible , en écrivant votre propre sous-classe ClassLoader, créant le bytecode pour le ENUM dans un tableau d'octets, et en utilisant defineClass. Dur, peut-être, mais possible. Je pense qu'une fois que vous connaissez la séquence d'octets pour une énumération, il n'est pas si difficile de la générer à partir des informations du JVM spec.

Maintenant, si c'est une bonne idée ... eh bien, je suspecte seulement dans un très petit nombre de cas de bord. (Je ne peux pas penser à un, je veux dire, l'ayant créé, vous devez générer du code utiliser il, non?) Sinon, vous êtes probablement mieux avec un Map ou similaire.

+0

Est-ce que le downvoter se soucierait de partager des commentaires utiles? La question est peut-il être fait, la réponse est oui cela peut * être * fait. Problème? –

0

Comme tout le monde a dit non. Ce n'est pas possible. Votre meilleur coup est d'utiliser le modèle de registre. Lisez les valeurs, stockez-les dans une sorte de carte interrogeable. Un peu comme un Enum.

0

Comme tout le monde l'a souligné, ce n'est pas possible. Cependant, vous pouvez créer un Map où la clé de votre carte serait la valeur que vous lisez dans votre fichier (APPLE, ORANGE, BANANA) et le? serait une valeur associée (int par exemple). De cette façon, vous pourriez atteindre le même objectif sans le type de sécurité, bien sûr.

int i = fruitsMap.get("BANANA") // get the assoicated value 
3

Eh bien le point d'un Enum est de l'utiliser au moment de la compilation. Si vous ne savez pas au moment de la compilation quelles sont les valeurs de votre Enum, alors ce n'est pas un Enum c'est une collection.

Si vous le savez et que vous voulez juste créer une base de fichier de classe sur les valeurs dans le fichier texte, alors oui c'est possible en lisant le txt puis en générant le code source.

0

Vous pouvez avec le code généré dynamiquement. par exemple. Utilisation de l'API du compilateur J'ai écrit un wrapper pour cette API afin que vous puissiez compiler des classes en mémoire. Voir le code ci-dessous. Le problème que vous avez est qu'il n'est pas très utile car vous ne pouvez pas utiliser ces valeurs, sauf dans les classes qui ont été compilées APRÈS la compilation de votre énumération. Vous pouvez utiliser Enum.valueOf() etc. Mais une grande partie de la valeur d'enums est perdue.

Comme d'autres l'ont suggéré, l'utilisation d'une carte serait plus simple et donnerait le même avantage. Je n'utiliserais l'enum si vous avez une bibliothèque doit être passé un Enum. (Ou plan code plus généré)

public static Class generateEnum(String className, List<String> enums) { 
    StringBuilder code = new StringBuilder(); 
    code.append("package enums; public enum enums." + className + " {\n"); 
    for (String s : enums) 
     code.append("\t"+s+",\n"); 
    code.append("}"); 
    return CompilerUtils.CACHED_COMPILER 
      .loadFromJava("enums."+className, code.toString()); 
} 

L'une des choses que je trouve utile avec le texte code généré est que vous pouvez l'écrire dans un fichier et le déboguer même au moment de l'exécution. (La bibliothèque supporte cela) Si vous générez du code octet, il est plus difficile à déboguer.

La bibliothèque s'appelle Essence JCF. (Et cela ne nécessite pas de chargeur de classe personnalisé)

+0

Il vaut probablement la peine de noter qu'un JRE (par opposition à une JVM) peut ne pas avoir de compilateur. http://download.oracle.com/javase/6/docs/api/javax/tools/ToolProvider.html#getSystemJavaCompiler() –

+0

Dans ce cas, vous devrez ajouter tools.jar à votre chemin de classe, comme vous le feriez toute autre bibliothèque. ;) –

0

Comment le feriez-vous dans une langue dynamique comme JavaScript: ce serait juste une chaîne avec une des valeurs: "APPLE", "ORANGE", "BANANA".

Les types Java (classes, interfaces, énumérations) n'existent que pour que le compilateur effectue des optimisations et vérifie les types, pour rendre possible le refactoring, etc. Au moment de l'exécution, vous n'avez besoin ni d'optimisations ni de "string" est OK, comme en JavaScript, chaque objet est un nombre (Double en Java), une chaîne (String en Java) ou un objet complexe (Map in Java) - c'est tout ce dont vous avez besoin pour faire quoi que ce soit Java.