2

О Varargs, могу ли я повторить аргументы в группе?Varargs в группе?

Например, я хочу, чтобы позволить пользователям проходить в:

myFunc(1, "one"); 
myFunc(1, "one", 2, "two"); 
myFunc(1, "one", 2, "two", 3, "three"); 

Это кажется невозможным. Но, как упоминалось в docs, varargs на самом деле является массивом в старой реализации. Я хотел был бы знать как был людей делают до varargs изобретатель. Это может вдохновить нас на то, как достичь вышеуказанного сценария. Мы можем рассматривать мой сценарий как {int, String}..., повторяющий afterall.

Спасибо за любой вход :-)

Edit:

Спасибо за все ваши входы!

Таким образом, он звонит myFunc(new wrap(1, "one"), new wrap(2, "two"), new wrap(3, "three")); является старый метод?

Редакция 2:

Ну, нет. Это моя ошибка беспорядка.

Для

myFunc(1); 
myFunc(1, 2); 
myFunc(1, 2, 3); 

старый путь должен быть

myFunc(new int[]{1}); 
myFunc(new int[]{1, 2}); 
myFunc(new int[]{1, 2, 3}); 

Насколько я могу видеть, как повторяющиеся аргументы образуют в массив. Все его аргументы должны быть одного типа. Невозможно достичь вышеуказанных вызовов простым способом. Для любопытства я начинаю думать о возможности перегрузки оператора ... (?)

ответ

3

В этом случае мне кажется, что для создания «пары» целесообразно создать структуру данных, а затем использовать этот тип как vararg аргумент вашему методу.

public void myFunc(Pair... pairs) {} 

Вы также можете использовать Object..., но я не вижу каких-либо преимуществ в этом случае, так как аргументы всегда приходят парами.

Как примечание стороны, я очень скучаю по Scala кортежи для такого рода стриктур данных ...

+0

Спасибо @NilsH. Однако при использовании пользователи должны делать «myFunc» (новая пара (1, «одна»), новая пара (2, «два»), новая пара (3, «три»), ', разве это? сокращенно? Или используйте более удобным способом? – midnite

+0

Да, вам нужно было бы это сделать. Если вы этого не хотите, вам придется использовать «Object ...», а затем проверить и отбросить аргументы внутри вашего метода Но это откроет для неправильного использования вашего метода, поэтому я бы не рекомендовал это делать. – NilsH

+0

yup действительно и с помощью 'Object ...' не может защитить число аргументов, чтобы быть четным, правильно? – midnite

2

насчет создания класса-оболочки, который оборачивает эти два параметра вместе?

public class TwoParameter 
{ 
    private int intValue; 
    private String stringValue; 

    public TwoParameter(int intValue, String stringValue) 
    { 
     this.intValue = intValue; 
     this.stringValue = stringValue; 
    } 

    // getters and setters 
} 

, а затем использовать его как:

myFunc(new TwoParameter(1, "one"), new TwoParameter(2, "two")); 

Сигнатура метода было бы что-то вроде этого: были введены

public void myFunc(TwoParameter... params){...} 
+0

Спасибо @ Eng.Fouad. Я больше всего беспокоюсь, когда звоню: myFunc (новый TwoParameter (1, «один»), новый TwoParameter (2, «two»)), «кажется« длинным »и сложным. – midnite

1

Var арг, чтобы позволить вам отправить произвольное число аргументов функции. Люди были взломаны с другими коллекциями/массивами, прежде чем они появились.

Вы можете достичь того, чего хотите, с помощью настраиваемой структуры. Детали структуры будут зависеть от того, что должна достичь пара значений имени. Вот общее решение для любой пары NameValue.

пар имя

class NameValuePair<K,V> 
{ 
    private K key; 
    private V value; 
    public K getKey() 
    { 
     return key; 
    } 
    public void setKey(K key) 
    { 
     this.key = key; 
    } 
    public V getValue() 
    { 
     return value; 
    } 
    public void setValue(V value) 
    { 
     this.value = value; 
    } 
} 

Использование

private <K,V> void method(NameValuePair<K, V>... pairs) 
{ 
    for (NameValuePair<K, V> nameValuePair : pairs) 
    { 
     K key = nameValuePair.getKey(); 
     V value = nameValuePair.getValue(); 
     // logic goes here 
    } 
} 
+0

Спасибо @Deepak Bala. Хотя мои пользователи библиотеки используют его, им все равно придется делать 'NameValuePair nvp = new NameValuePair(); nvp.setKey (1); nvp.s etValue ("один"); метод (nvp, nvp, nvp); ', не так ли? Можно ли написать меньше кода и позволить пользователям вызывать 'метод', как пример в моем вопросе? - Это кажется более удобным для пользователя. – midnite

+0

Java строго типизирован, поэтому единственный способ добиться того, что вы хотите, это использовать «Object ... args». Хотя это хорошо работает для вызывающего, реализация метода будет выглядеть грязной, так как для определения типа потребуется экземпляр 'instanceof'. Я бы посоветовал сделать это немного сложнее для вызывающего, вместо того, чтобы писать грязный код с 'instanceof'. –

+0

я вижу. и спасибо. Это действительно хорошее соображение. – midnite

1

Есть веские причины использовать другие решения, но все они привносят немного беспорядка (чтобы создать все эти объекты), вы, возможно, не хотят подвергать пользователей вашей библиотеки.

Вы можете переложить беспорядок на внутренней стороне вашего метода следующим образом:

public void example(final Object... args) { 
    if (args.length % 2 != 0) 
     throw new IllegalArgumentException("int, String pairs are required, but there seems to be an odd one out"); 

    for (int i = 0; i < args.length; i += 2) { 
     int a = (Integer) args[i]; 
     String b = (String) args[i + 1]; 

     System.out.printf("%d: %s\n", a, b); 
    } 
} 

example(1, "Hello", 2, "Goodbye", 25, "Raptors will eat you!"); будет производить следующий вывод:

1: Hello 
2: Goodbye 
25: Raptors will eat you!