Я боюся вараг. Я не знаю, для чого їх використовувати.
Плюс до цього, небезпечно дозволяти людям передавати стільки аргументів, скільки їм хочеться.
Що є прикладом контексту, який би був хорошим місцем для їх використання?
Я боюся вараг. Я не знаю, для чого їх використовувати.
Плюс до цього, небезпечно дозволяти людям передавати стільки аргументів, скільки їм хочеться.
Що є прикладом контексту, який би був хорошим місцем для їх використання?
Відповіді:
Вараги є корисними для будь-якого методу, якому потрібно мати справу з невизначеною кількістю об'єктів . Один хороший приклад - це String.format
. Рядок формату може приймати будь-яку кількість параметрів, тому вам потрібен механізм передачі будь-якої кількості об'єктів.
String.format("This is an integer: %d", myInt);
String.format("This is an integer: %d and a string: %s", myInt, myString);
Хорошим правилом було б:
"Використовувати varargs для будь-якого методу (або конструктора), який потребує масиву T (незалежно від типу T) як вхідного даних".
Це полегшить дзвінки до цих методів (робити це не потрібно new T[]{...}
).
Ви можете розширити це правило, включаючи методи з List<T>
аргументом, за умови, що цей аргумент призначений лише для введення даних (тобто список не змінюється методом).
Крім того, я б утримався від використання, f(Object... args)
оскільки його ковзання у напрямку програмування з незрозумілими API.
З точки зору прикладів, я використовував це в DesignGridLayout , де я можу додати кілька JComponent
s за один виклик:
layout.row().grid(new JLabel("Label")).add(field1, field2, field3);
У коді вище метод add () визначається як add(JComponent... components)
.
Нарешті, реалізація таких методів повинна подбати про те, щоб його можна було викликати з порожнім вараггом! Якщо ви хочете нав'язати хоча б один аргумент, вам доведеться скористатися некрасивою хитрістю, наприклад:
void f(T arg1, T... args) {...}
Я вважаю цей трюк потворним, оскільки реалізація методу буде менш простою, ніж просто T... args
у списку аргументів.
Сподіваємось, що це допоможе з’ясувати пункт про вараги.
if (args.length == 0) throw new RuntimeException("foo");
замість цього додати перевірку передумов ? (Оскільки абонент порушив договір)
void f(T arg1, T... args)
цього завжди гарантує, що вона ніколи не викликається без аргументів, не потрібно чекати часу виконання.
Я часто використовую varargs для виведення в журнали для налагодження.
Практично кожен клас у моєму додатку має метод debugPrint ():
private void debugPrint(Object... msg) {
for (Object item : msg) System.out.print(item);
System.out.println();
}
Тоді в межах методів класу у мене є такі дзвінки:
debugPrint("for assignment ", hwId, ", student ", studentId, ", question ",
serialNo, ", the grade is ", grade);
Коли я впевнений, що мій код працює, я коментую його в методі debugPrint (), щоб журнали не містили занадто багато сторонньої та небажаної інформації, але я можу залишити окремі дзвінки на debugPrint () без коментарів. Пізніше, якщо я знайду помилку, я просто відкидаю код debugPrint (), і всі мої дзвінки на debugPrint () повторно активуються.
Звичайно, я міг би так само легко ухилятися від варагів і робити наступні дії:
private void debugPrint(String msg) {
System.out.println(msg);
}
debugPrint("for assignment " + hwId + ", student " + studentId + ", question "
+ serialNo + ", the grade is " + grade);
Однак у цьому випадку, коли я коментую код debugPrint (), сервер все ще повинен зазнати проблеми з об'єднанням всіх змінних у кожному виклику до debugPrint (), хоча нічого не робиться з отриманим рядком. Якщо я використовую varargs, сервер повинен лише помістити їх у масив до того, як він зрозуміє, що вони їм не потрібні. Зберігається багато часу.
Вараги можна використовувати, коли ми не впевнені в кількості аргументів, які потрібно передавати методом. Він створює масив параметрів невизначеної довжини на задньому плані, і такий параметр може трактуватися як масив під час виконання.
Якщо у нас є метод, який перевантажений для прийняття різної кількості параметрів, то замість того, щоб перевантажувати метод у різні часи, ми можемо просто використовувати концепцію varargs.
Крім того, коли тип параметрів буде змінюватися, використання "Тест об'єкта ..." значно спростить код.
Наприклад:
public int calculate(int...list) {
int sum = 0;
for (int item : list) {
sum += item;
}
return sum;
}
Тут опосередковано масив типу (список) int передається як параметр і трактується як масив у коді.
Для кращого розуміння перейдіть за цим посиланням (це мені дуже допомогло зрозуміти цю концепцію): http://www.javadb.com/using-varargs-in-java
PS: Навіть я боявся використовувати вараги, коли не знав цього. Але зараз я звик до цього. Як сказано: "Ми чіпляємось за відоме, боїмося невідомого", тому просто використовуйте його, наскільки можете, і вам теж почнуть подобатися :)
Varargs - це функція, додана у версії 1.5 Java.
Навіщо це використовувати?
Як це працює?
Він створює масив із заданими аргументами та передає масив методу.
Приклад:
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 );
}
}
Вихід:
2
сума - 12
3
сума - 21
У мене теж страх, пов'язаний з вараггами:
Якщо абонент передає методу явний масив (на відміну від декількох параметрів), ви отримаєте спільну посилання на цей масив.
Якщо вам потрібно зберегти цей масив внутрішньо, ви можете спершу його клонувати, щоб уникнути того, що абонент зможе його змінити пізніше.
Object[] args = new Object[] { 1, 2, 3} ;
varArgMethod(args); // not varArgMethod(1,2,3);
args[2] = "something else"; // this could have unexpected side-effects
Хоча це насправді не відрізняється від передачі будь-якого виду об’єктів, стан якого може змінитися згодом, оскільки масив зазвичай (у випадку виклику з декількома аргументами замість масиву) свіжий, створений компілятором внутрішньо, що ви можете безпечно використання, це, безумовно, несподівана поведінка.
Я часто використовую varargs для конструкторів, які можуть приймати якийсь об’єкт фільтра. Наприклад, значна частина нашої системи на базі Hadoop базується на Mapper, який обробляє серіалізацію та десеріалізацію елементів у JSON, і застосовує ряд процесорів, які кожен беруть елемент вмісту і змінюють, і повертають його, або повертають null відхилити.
У Java-документі Var-Args цілком зрозуміло використання var args:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/varargs.html
про використання він говорить:
"Отже, коли ви повинні використовувати varargs? Як клієнт, ви повинні користуватися ними, коли API пропонує їх. Важливими напрямами використання основних API є відображення, форматування повідомлень та новий інструмент printf. Як дизайнер API ви повинні використовувати їх щадно, лише тоді, коли користь справді переконлива. Взагалі кажучи, ви не повинні перевантажувати метод varargs, інакше програмістам буде складно зрозуміти, на яку виклик перезавантаження ".