2012-02-25 3 views
3

Je travaille sur une application Java. Il s'agit d'un modèle de classe abstraite et de 2 classes dérivées Model 1 et Model 2. Model1 et Model2 se comportent différemment, donc je veux permettre à l'utilisateur de sélectionner un modèle parmi les deux. Il peut être mis en œuvre comme:Java, liste des types de classes

Model model; 
If(response==1){ 
    model = new Model1(); 
}else if(response==2){ 
    model = new Model2(); 
} 

Maintenant, le problème avec ceci est que si j'ajoute une nouvelle classe Model3, je dois réécrire le code. Je pourrais créer une liste, où j'ajouterais une instance de chaque classe, puis j'ajouterais une méthode statique, qui retournerait une nouvelle instance de la classe, mais j'espère que cela peut être fait avec un peu plus de style.

Est-il possible de créer une liste, pour contenir le type de chaque classe. À partir de cette liste, je pourrais créer un menu pour sélectionner un modèle, puis utiliser le type pour créer la classe dont l'utilisateur a besoin.

Alors, est-il possible de créer un List<Class>, puis d'utiliser l'objet Class en tant que constructeur pour créer une instance de la classe donnée?

Répondre

4

Vous pouvez créer une liste de suppliers:

static final List<Supplier<Model>> MODEL_MAKERS = ImmutableList.of(
    new Supplier<Model>() { public Model get() { return new Model1(); } }, 
    new Supplier<Model>() { public Model get() { return new Model2(); } }, 
    new Supplier<Model>() { public Model get() { return new Model3(); } } 
); 

Vous pouvez muck autour de la réflexion, mais il faut marcher en dehors des mécanismes de gestion des exceptions normales de Java, exige public constructeurs sans argument et public classes qui limite comment le code peut changer sous la maintenance d'une manière qui n'est pas vérifiée par javac, et n'est tout simplement pas nécessaire dans ce cas.

+0

+1 pour ne pas utiliser de réflexion.Parfois, vous devez, cependant (si vous ne connaissez pas la classe au moment de la compilation, par exemple) –

+0

@StevenSchlansker, je suis d'accord qu'il existe des utilisations pour la réflexion. Je préfère le limiter aux frontières entre les systèmes d'objets Java et d'autres systèmes - le système de fichiers, les ORM, les langages de script intégrés. Si vous travaillez entièrement en Java, il existe souvent une meilleure façon de l'utiliser qui n'affecte pas la capacité des mainteneurs à refactoriser le code, suivre le déroulement du programme, etc. –

1

Si vous êtes sûr qu'il aura un constructeur public non-args, vous pouvez utiliser Class.newInstance()

Pour des utilisations plus complexes, vous pouvez trouver un objet Constructor avec Class.getConstructor(s) puis invoquez cette façon.

Une fois que vous avez cela, il est relativement facile de coller votre Class es dans un Map ou quelque chose à faire des recherches et créer des instances.

+0

N'utilisez pas 'newInstance'. Le [javadoc] (http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#newInstance%28%29) avertit explicitement: "Notez que cette méthode propage toute exception lancée par le constructeur nullaire, y compris une exception vérifiée.L'utilisation de cette méthode contourne effectivement la vérification d'exception de compilation qui serait autrement effectuée par le compilateur. " –

+0

Dans certains cas, c'est exactement ce que vous voulez. Il vaut certainement la peine de noter, cependant. –

0

Oui, vous pouvez utiliser la méthode newInstance() sur Class pour en construire un. Il doit cependant avoir un constructeur sans-args.

+0

N'utilisez pas 'newInstance'. Le [javadoc] (http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#newInstance%28%29) avertit explicitement: "Notez que cette méthode propage toute exception lancée par le constructeur nullaire, y compris une exception vérifiée.L'utilisation de cette méthode contourne effectivement la vérification d'exception de compilation qui serait autrement effectuée par le compilateur. " –

+0

C'est bon si vous êtes sûr que le constructeur ne lancera pas d'exception. Si vous n'avez jamais appelé quoi que ce soit qui pourrait déclencher une exception, vous n'obtiendrez jamais de codage ... :-) –

+0

c'est bien si vous êtes sûr que le constructeur ne lancera pas une exception ** maintenant et en maintenance **. –

Questions connexes