J'ai peur des varargs. Je ne sais pas comment les utiliser.
De plus, il est dangereux de laisser les gens passer autant d'arguments qu'ils le souhaitent.
Quel est un exemple de contexte qui serait un bon endroit pour les utiliser?
J'ai peur des varargs. Je ne sais pas comment les utiliser.
De plus, il est dangereux de laisser les gens passer autant d'arguments qu'ils le souhaitent.
Quel est un exemple de contexte qui serait un bon endroit pour les utiliser?
Réponses:
Les Varargs sont utiles pour toute méthode qui doit traiter un nombre indéterminé d'objets . Un bon exemple est String.format
. La chaîne de format peut accepter n'importe quel nombre de paramètres, vous avez donc besoin d'un mécanisme pour transmettre n'importe quel nombre d'objets.
String.format("This is an integer: %d", myInt);
String.format("This is an integer: %d and a string: %s", myInt, myString);
Une bonne règle d'or serait:
"Utilisez varargs pour toute méthode (ou constructeur) qui a besoin d'un tableau de T (quel que soit le type T) comme entrée".
Cela facilitera les appels à ces méthodes (inutile de le faire new T[]{...}
).
Vous pouvez étendre cette règle pour inclure des méthodes avec un List<T>
argument, à condition que cet argument soit uniquement pour l'entrée (c'est-à-dire que la liste n'est pas modifiée par la méthode).
De plus, je m'abstiendrai d'utiliser f(Object... args)
parce que cela glisse vers une méthode de programmation avec des API peu claires.
En termes d'exemples, je l'ai utilisé dans DesignGridLayout , où je peux ajouter plusieurs JComponent
s en un seul appel:
layout.row().grid(new JLabel("Label")).add(field1, field2, field3);
Dans le code ci-dessus, la méthode add () est définie comme add(JComponent... components)
.
Enfin, l'implémentation de telles méthodes doit prendre en compte le fait qu'elle peut être appelée avec un vararg vide! Si vous souhaitez imposer au moins un argument, vous devez utiliser une astuce moche telle que:
void f(T arg1, T... args) {...}
Je considère cette astuce moche car la mise en œuvre de la méthode sera moins simple que de l'avoir juste T... args
dans sa liste d'arguments.
Espère que cela aide à clarifier le point sur les varargs.
if (args.length == 0) throw new RuntimeException("foo");
plutôt envisagé d'ajouter une vérification des conditions préalables ? (Puisque l'appelant violait le contrat)
void f(T arg1, T... args)
cela garantit toujours qu'elle n'est jamais appelée sans argument, sans avoir besoin d'attendre l'exécution.
J'utilise fréquemment des varargs pour la sortie dans les journaux à des fins de débogage.
Presque toutes les classes de mon application ont une méthode debugPrint ():
private void debugPrint(Object... msg) {
for (Object item : msg) System.out.print(item);
System.out.println();
}
Ensuite, dans les méthodes de la classe, j'ai des appels comme celui-ci:
debugPrint("for assignment ", hwId, ", student ", studentId, ", question ",
serialNo, ", the grade is ", grade);
Lorsque je suis convaincu que mon code fonctionne, je commente le code dans la méthode debugPrint () afin que les journaux ne contiennent pas trop d'informations superflues et indésirables, mais je peux laisser les appels individuels à debugPrint () sans commentaire. Plus tard, si je trouve un bogue, je décommente simplement le code debugPrint () et tous mes appels à debugPrint () sont réactivés.
Bien sûr, je pourrais tout aussi facilement éviter les varargs et faire ce qui suit à la place:
private void debugPrint(String msg) {
System.out.println(msg);
}
debugPrint("for assignment " + hwId + ", student " + studentId + ", question "
+ serialNo + ", the grade is " + grade);
Cependant, dans ce cas, lorsque je commente le code debugPrint (), le serveur doit encore se donner la peine de concaténer toutes les variables à chaque appel à debugPrint (), même si rien n'est fait avec la chaîne résultante. Si j'utilise des varargs, cependant, le serveur n'a qu'à les mettre dans un tableau avant de se rendre compte qu'il n'en a pas besoin. Beaucoup de temps est économisé.
Varargs peut être utilisé lorsque nous ne sommes pas sûrs du nombre d'arguments à passer dans une méthode. Il crée un tableau de paramètres de longueur non spécifiée en arrière-plan et un tel paramètre peut être traité comme un tableau à l'exécution.
Si nous avons une méthode surchargée pour accepter un nombre différent de paramètres, alors au lieu de surcharger la méthode plusieurs fois, nous pouvons simplement utiliser le concept varargs.
De même, lorsque le type des paramètres variera, l'utilisation de "Object ... test" simplifiera beaucoup le code.
Par exemple:
public int calculate(int...list) {
int sum = 0;
for (int item : list) {
sum += item;
}
return sum;
}
Ici indirectement un tableau de type int (liste) est passé en paramètre et est traité comme un tableau dans le code.
Pour une meilleure compréhension suivez ce lien (cela m'a beaucoup aidé à comprendre clairement ce concept): http://www.javadb.com/using-varargs-in-java
PS: Même moi, j'avais peur d'utiliser des varargs quand je ne le savais pas. Mais maintenant j'y suis habitué. Comme il est dit: "Nous nous accrochons au connu, peur de l'inconnu", alors utilisez-le autant que vous le pouvez et vous aussi commencerez à l'aimer :)
Varargs est la fonctionnalité ajoutée dans la version java 1.5.
Pourquoi utiliser ça?
Comment ça marche?
Il crée un tableau avec les arguments donnés et passe le tableau à la méthode.
Exemple :
public class Solution {
public static void main(String[] args) {
add(5,7);
add(5,7,9);
}
public static void add(int... s){
System.out.println(s.length);
int sum=0;
for(int num:s)
sum=sum+num;
System.out.println("sum is "+sum );
}
}
Production :
2
la somme est de 12
3
la somme est 21
J'ai aussi une peur liée aux varargs:
Si l'appelant passe un tableau explicite à la méthode (par opposition à plusieurs paramètres), vous recevrez une référence partagée à ce tableau.
Si vous avez besoin de stocker ce tableau en interne, vous souhaiterez peut-être le cloner d'abord pour éviter que l'appelant ne puisse le modifier ultérieurement.
Object[] args = new Object[] { 1, 2, 3} ;
varArgMethod(args); // not varArgMethod(1,2,3);
args[2] = "something else"; // this could have unexpected side-effects
Bien que ce ne soit pas vraiment différent du passage de tout type d'objet dont l'état pourrait changer plus tard, puisque le tableau est généralement (dans le cas d'un appel avec plusieurs arguments au lieu d'un tableau) un nouveau créé par le compilateur en interne que vous pouvez en toute sécurité utilisation, c'est certainement un comportement inattendu.
J'utilise fréquemment varargs pour les constructeurs qui peuvent prendre une sorte d'objet filtre. Par exemple, une grande partie de notre système basé sur Hadoop est basé sur un mappeur qui gère la sérialisation et la désérialisation des éléments vers JSON, et applique un certain nombre de processeurs qui prennent chacun un élément de contenu et le modifient et le renvoient, ou retournent null rejeter.
Dans la documentation Java de Var-Args, l'utilisation de var args est assez claire:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/varargs.html
à propos de l'utilisation, il dit:
"Alors, quand devriez-vous utiliser varargs? En tant que client, vous devriez en profiter chaque fois que l'API les propose. Les principales utilisations des API principales incluent la réflexion, la mise en forme des messages et la nouvelle fonction printf. En tant que concepteur d'API, vous devez les utiliser avec parcimonie, seulement lorsque l'avantage est vraiment convaincant. En règle générale, vous ne devez pas surcharger une méthode varargs, sinon il sera difficile pour les programmeurs de déterminer quelle surcharge est appelée. "