Подтвердить что ты не робот

Java два varargs одним способом

Есть ли какой-либо способ в java, чтобы создать метод, который ожидает два разных varargs? Я знаю, что с тем же видом объекта это невозможно, потому что компилятор не знает, с чего начать или до конца. Но почему это также невозможно с разными типами объектов?

Например:

public void doSomething(String... s, int... i){
    //...
    //...
}

Есть ли способ создать такой метод? Спасибо!

4b9b3361

Ответ 1

Только один вараг, извините. Но использование asList() делает его почти удобным:

 public void myMethod(List<Integer> args1, List<Integer> args2) {
   ...
 }

 -----------

 import static java.util.Arrays.asList;
 myMethod(asList(1,2,3), asList(4,5,6));

Ответ 2

В Java допускается только один аргумент varargs, и он должен быть последним параметром подписи.

Но все равно он преобразует его в массив, так что вам нужно просто сделать ваши два параметра явными массивами:

public void doSomething(String[] s, int[] i){

Ответ 3

Возможная конструкция API, в которой код вызова выглядит как

    doSomething("a", "b").with(1,2);

через "свободный" API

public Intermediary doSomething(String... strings)
{
    return new Intermediary(strings);
}

class Intermediary
{
    ...
    public void with(int... ints)
    {
        reallyDoSomething(strings, ints);
    }
}

void reallyDoSomething(String[] strings, int[] ints)
{
    ...
}

Опасность заключается в том, что программист забыл называть with(...)

    doSomething("a", "b");  // nothing is done

Может быть, это немного лучше

    with("a", "b").and(1, 2).doSomething();

Ответ 4

Разрешен только один vararg. Это связано с тем, что несколько аргументов vararg неоднозначны. Например, что, если вы передали два varargs одного класса?

public void doSomething(String...args1, String...args2);

Где заканчивается args1 end и args2? Или как насчет чего-то более запутанного здесь.

class SuperClass{}
class ChildClass extends SuperClass{}
public void doSomething(SuperClass...args1, ChildClass...args2);

ChildClass расширяет SuperClass, и, следовательно, может существовать законно в args1 или args2. Эта путаница заключается в том, что разрешено использовать только один varargs.

varargs также должен появиться в конце объявления метода.

Просто объявите конкретный тип вместо 2 массивов.

Ответ 5

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

Если два списка связаны вообще, вы, вероятно, хотите создать класс-оболочку для двух разных списков и передать в оболочку. Обертки вокруг коллекций - почти всегда хорошая идея - они дают вам место для добавления кода, относящегося к коллекции.

Если это способ инициализации данных, проанализируйте его из строки. Например, "abc, 123: def, 456: jhi, 789" почти смутно легко разделить с помощью двух разделенных операторов и цикла (2-3 строки кода). Вы даже можете создать небольшой пользовательский класс парсера, который анализирует такую ​​строку в структуре, которую вы подаете в свой метод.

Хмм - честно соглашайтесь с инициализацией данных, я даже не знаю, почему вы хотели бы сделать это в любом случае, в любом другом случае, и я ожидаю, что вы пройдете в 2 сборниках и не будете интересоваться varags at все.

Ответ 6

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

public void doSomething(Object... stringOrIntValues) {
    ...
    ...
}

И используйте этот метод следующим образом:

doSomething(stringValue1, stringValue2, intValue1, intValue2,         
    intValue3);

Ответ 7

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

Решение, которое я нашел, не очень аккуратно, но оно работает. Я создал отдельный класс для тяжелого подъема. У него есть только две переменные, которые мне нужны, и их геттеры. Конструктор самостоятельно обрабатывает установленные методы.

Мне нужно было передать объекты направления и соответствующий объект Data. Это также решает возможную проблему неравных пар данных, но это, вероятно, только для моих нужд использования.

public class DataDirectionPair{

    Data dat;
    Directions dir;

    public DataDirectionPair(Data dat, Directions dir) {
        super();
        this.dat = dat;
        this.dir = dir;
    }

    /**
     * @return the node
     */
    public Node getNode() {
        return node;
    }

    /**
     * @return the direction
     */
    public Directions getDir() {
        return dir;
    }
}

Я бы просто передал этот класс как vararg для метода

public void method(DataDirectionPair... ndPair){
    for(DataDirectionPair temp : ndPair){
        this.node = temp.getNode();
        this.direction = temp.getDir();
        //or use it however you want
    }
}

Ответ 8

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

Вместо того, чтобы заставить разработчика обернуть параметр ввода в List или Array, будет полезно использовать подход "карри" или лучше шаблон построения.

Рассмотрим следующий код:

/**
 * Just a trivial implementation
 */
public class JavaWithCurry {

    private List<Integer> numbers = new ArrayList<Integer>();
    private List<String> strings = new ArrayList<String>();

    public JavaWithCurry doSomething(int n) {

        numbers.add(n);

        return this;
    }

    public JavaWithCurry doSomething(String s) {

        strings.add(s);

        return this;

    }

    public void result() {

        int sum = -1;

        for (int n : numbers) {
            sum += n;
        }


        StringBuilder out = new StringBuilder();

        for (String s : strings) {

            out.append(s).append(" ");

        }

        System.out.println(out.toString() + sum);

    }

    public static void main(String[] args) {

        JavaWithCurry jwc = new JavaWithCurry();

        jwc.doSomething(1)
                .doSomething(2)
                .doSomething(3)
                .doSomething(4)
                .doSomething(5)
                .doSomething("a")
                .doSomething("b")
                .doSomething("c")
                .result();

    }

}

Как вы можете видеть вас таким образом, вы можете добавить новые элементы, которые вам нужны, когда вам нужно.

Вся реализация завершена.

Ответ 9

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

public void doSomething(int... i){
    doSomething(new String[0], i);
}
public void doSomething(String s, int... i){
    doSomething(new String[]{ s }, i);
}
public void doSomething(String s1, String s2, int... i){
    doSomething(new String[]{ s1, s2 }, i);
}
public void doSomething(String s1, String s2, String s3, int... i){
    doSomething(new String[]{ s1, s2, s3 }, i);
}
public void doSomething(String[] s, int... i) {
    // ...
    // ...
}

Ответ 10

follwing на Лемуэля Адане (не могу прокомментировать сообщение, из-за отсутствия репутации:))

если вы используете

public void f(Object... args){}

то вы можете использовать цикл Как определить класс объекта (на Java)?

например,

{
   int i = 0;
   while(i< args.length && args[i] instanceof String){
         System.out.println((String) args[i]);
         i++ ;
   }
   int sum = 0;
   while(i< args.length){
         sum += (int) args[i];
         i++ ;
   }
   System.out.println(sum);
}

или все, что вы намереваетесь сделать.

Ответ 11

Вы можете преобразовать ваши varargs в массивы

public void doSomething(String[] s, int[] i) {
    ...
}

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

public static int[] intsAsArray(int... ints) {
    return ints;
}

public static <T> T[] asArray(T... ts) {
    return ts;
}

Затем вы можете использовать эти вспомогательные методы для преобразования ваших переменных.

doSomething(asArray("a", "b", "c", "d"), intsAsArray(1, 2, 3));