J'ai deux méthodes telles que celles suivantes
private List<Long> getIds(String name, List<T> objects) {
List<Long> ids = new ArrayList<>();
for (T object : objects) {
if (object.getName().equals(name)) ids.add(object.getId());
}
return ids;
}
7 Réponses :
Vous devez utiliser une API de réflexion, si vous ne pouvez pas modifier les classes de chat et de chien. Sinon, utilisez l'animal d'interface (ou la coulée de type) p>
Dans le cas où une super-classe n'est pas possible, je pense que c'est le seul moyen. Mais comme il se trouve, ce n'est pas beaucoup plus qu'un commentaire. Pourriez-vous ajouter du code?
Vous devez définir une interface commune pour que vous pouvez passer une liste chat code> et chien code>, par exemple animal code>. p>.
OP dit Ici Cat and Dog est des classes Java intégrées. En conséquence, je ne peux pas effectuer l'héritage et fournir un animal de super classe pour eux avec nom et identifiant comme variables de données. Code>
Je modifie ma réponse pour vous montrer une autre approche possible
@Vinayveluri ah .. j'ai raté de voir ça
Salut .. je sais une sorte de cette approche .. Mais j'aimerais éviter de changer de chat ou de classe de chien.
John, regarde ma solution de réflexion. J'espère que ça va aider
Pouvez-vous simplement faire une interface pour le chien et le chat? Ensuite, votre méthode deviendrait P> public class Log4jEvent extends EventWrapper {
LoggingEvent event;
public Log4jEvent(LoggingEvent event) {
this.event = event;
}
@Override
public String getFormattedMessage() {
if (event.getMessage() != null) {
return event.getMessage().toString();
} else {
return null;
}
}
}
Je ne peux pas faire ça. Je ne peux pas éditer les cours de chat ou de chien
Je l'ai vu, vous pouvez simplement les envelopper dans votre classe d'enveloppe personnalisée. Bien..Je ajouter un échantillon de mon expérience.
@ 이승진 intéressant. créant ainsi de nouvelles classes extension des classes de chat et de chien et de mettre en œuvre l'interface animal?
J'ai posté un exemple de mon expérience, très similaire à l'affaire de l'auteur.
La solution la plus facile à laquelle je puisse penser (maintenir l'héritage de côté) vérifie si l'objet est de type chien ou chat. Voici le code de la méthode: -
private List getIds(String name, List objects) {
List<Long> ids = new ArrayList<>();
for (Object obj : objects) {
if (obj instanceof Dog) {
Dog d = (Dog) obj;
if (d.getName().equals(name)) {
ids.add(d.getId());
}
} else if (obj instanceof Cat) {
Cat c = (Cat) obj;
if (c.getName().equals(name)) {
ids.add(c.getId());
}
}
}
return ids;
}
Non Non Non. Cela impliquerait que je peux transmettre la liste
Cela ne réduit pas du tout de la duplication de code. Vous venez de négocier deux méthodes de 7 lignes chacune pour une méthode de 18 lignes.
Si ce n'est aucun problème avec des lignes supplémentaires dans la méthode. Qu'en est-il de cela? Une approche plus générique serait la suivante: p>
Bien que cela puisse faire le travail, cela ouvre la fonction pour passer quelque chose comme la liste des
Oui, mais cela ne fournira rien de mal à d'autres types. Vous pouvez ajouter une valeur de retour nul ou une exception en cas de types inattendus.
Pas mal techniquement mais qu'en est-il de la complexité du temps .. vous finissez par itération de toute la collection entièrement juste pour renvoyer une liste vide
Pour être franc, j'essaie d'optimiser le code. Cela signifierait un code de nettoyage avec une meilleure efficacité et un nombre moins élevé de LOC. Donc, je ne préférerais pas utiliser l'instance code> et une deuxième approche à coup sûr.
OK, j'ai que vous ne pouvez utiliser aucun type d'héritage. Voici une solution courte avec API de réflexion alors:
private static List<Long> getIds(String name, List<?> objects) {
List<Long> ids = new ArrayList<>();
for (Object object : objects) {
try {
Method getName = null;
Method getId = null;
for (Method method : object.getClass().getMethods()) {
if (method.getName().equals("getName") && method.getReturnType().equals(String.class) && method.getParameterTypes().length == 0) {
getName = method;
}
if (method.getName().equals("getId") && method.getReturnType().equals(Long.class) && method.getParameterTypes().length == 0) {
getId = method;
}
if (getName != null && getId != null && getName.invoke(object).equals(name)) {
ids.add((Long) getId.invoke(object));
break;
}
}
} catch (Exception e) {
System.out.println(e);
}
}
return ids;
}
Quelques suggestions: utilisez égale code> pour comparer les chaînes et augmenter un illegalargumentException code> au cas où la classe n'a pas cet attribut. En outre, list > code>.
merci pour des égaux - mon erreur, écrivit ce code trop vite)
De plus, pouvez-vous me fournir l'exemple, où toute instance de la liste d'objets d'entrée n'aurait pas accessible Méthode d'équivalence? Ça a l'air intéressant
Avec cette approche, comment puis-je savoir (si je veux appeler getids code>) que les objets de la liste que je donne doivent avoir au moins deux méthodes chaîne publique getname () code> et Public Long Getid () Code>?
Vous ne pouvez pas savoir avec certitude, quelle est la liste et quelles méthodes il a. C'est pourquoi une exception "Noschmethod" peut être produite et doit être prise (voir la clause "Catch"). Je peux écrire un exemple plus softisé, mais il n'y a pas de moyen idéal pour résoudre le problème de l'auteur sans interface - vous devez effectuer des compromis pour faire face à la duplication de code dans cette situation :)
Et c'est exactement ce qui me dérange de cette solution. Il existe une solution idéale (coffre-fort), voir la réponse de TOBIAS_K.
Sa solution pour Java 8 est bonne, mais pas idéale aussi - vous devez traiter tous les groupes d'instances dans la liste d'objets d'entrée par une méthode d'appel d'approche spécifique comme: getids ("Quelqu'un", listofcats, chat :: getname, chat :: getname) ; getids ("Quelques noms", ListOfdogs, Chien :: getName, Dog :: getid); etc. Et que si nous avons une liste d'entrée de tous les objets? Non seulement les chats et les chiens - pas même des animaux. Mon appel de méthode est très simple: getids (nom, INPUTLIST_THINS)
Pour être franc, j'essaie d'optimiser le code. Cela signifierait un code de nettoyage avec une meilleure efficacité et un nombre moins élevé de LOC. L'approche que vous m'avez montré ci-dessus est assez bonne. Mais cela ne réduit pas considérablement le nombre de lignes.
J'aimerais avoir quelque chose de petit et concis comme @tobias_k's réponse, mais avec Java 7.
@Philipjohn pour être honnête, personnellement, j'irais avec cette réponse, à l'exception que je lancerais aussi un illegalargumentException code> au cas où la méthode ne peut pas être trouvée, au lieu d'ignorer silencieusement les éléments qui n'ont pas de méthodes. Je crains que cela soit aussi proche que possible de Typage de canard à Java
Au fait, j'ai fixé le code des exceptions nosuchmethod inutiles (peut être lent pour le traitement des listes massives) et ajouté une certaine filtration par signature de méthode (plus confiante, qu'est-ce que nous essayons exactement d'invoquer). Mais je ne sais pas le moyen de rendre ce code de réflexion plus concis dans Java 7 :( et la seule alternative - Tools de génération de code - Effectue encore pire
Une autre possibilité: Si vous utilisez Java 8, vous pouvez transmettre les méthodes getter pour nom et identifiant comme paramètres supplémentaires dans la méthode. Ceci est sûr de type et ne nécessite ni de réflexion ni de modifications aux classes d'origine.
private List<Long> getIds(String name, List<?> objects) {
if (objects.size() == 0) {
return Collections.emptyList();
}
if (objects.get(0) instanceof Cat) {
return getIds(name, (List<Cat>) objects, Cat::getName, Cat::getId);
}
if (objects.get(0) instanceof Dog) {
...
}
throw new IllegalArgumentException("List containing unsupported type!");
}
C'était une très bonne approche. Mais mon projet actuel doit être à Java 7. Et le client veut que ce soit Java 7. :-)
faire une interface animal contenant getname. mettre en œuvre cela dans le chat et le chien. Dans votre méthode Getids, changez-vous? étend son animal
Vous voudrez peut-être aussi consulter ce Recette de davon en tapant de Wikipedia ...