Я могу передать массив как аргументы методу с аргументами переменной в Java?

Я хотел бы смочь создать функцию как:

class A {
  private String extraVar;
  public String myFormat(String format, Object ... args){
    return String.format(format, extraVar, args);
  }
}

Проблема здесь - это args рассматривается как Object[] в методе myFormat, и таким образом отдельный аргумент к String.format, в то время как я хотел бы каждый Object в args быть переданным как новый аргумент. С тех пор String.format также метод с аргументами переменной, это должно быть возможно.

Если это не возможно, там метод как String.format(String format, Object[] args)? В этом случае я мог предварительно ожидать extraVar кому: args использование нового массива и передачи это к тому методу.

255
задан jasonmp85 27 May 2010 в 21:53
поделиться

4 ответа

Базовый тип вариативного метода function(Object... args) is function(Object[] args). Sun добавила varargs таким образом, чтобы сохранить обратную совместимость.

Поэтому вы должны быть в состоянии просто добавить extraVar к args и вызвать String.format(format, args).

170
ответ дан 23 November 2019 в 02:46
поделиться

Передавать массив - это нормально - на самом деле это то же самое

String.format("%s %s", "hello", "world!");

то же самое, что

String.format("%s %s", new Object[] { "hello", "world!"});

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

См.

22
ответ дан 23 November 2019 в 02:46
поделиться

jasonmp85 прав насчет передачи другого массива в String.format. Размер массива нельзя изменить после его создания, поэтому вам придется передать новый массив, а не модифицировать существующий.

Object newArgs = new Object[args.length+1];
System.arraycopy(args, 0, newArgs, 1, args.length);
newArgs[0] = extraVar; 
String.format(format, extraVar, args);
4
ответ дан 23 November 2019 в 02:46
поделиться

Да, T... - это только синтаксический сахар для T[].

JLS 8.4.1 Формальные параметры

Последний формальный параметр в списке является специальным; он может быть параметром переменной степени сложности, на что указывает элипсис после типа.

Если последний формальный параметр является параметром переменной четкости типа T, то считается, что он определяет формальный параметр типа T[]. Тогда метод является методом переменной четкости. В противном случае это метод фиксированной четкости. Вызовы метода переменной четкости могут содержать больше фактических выражений аргументов, чем формальных параметров. Все фактические выражения аргументов, которые не соответствуют формальным параметрам, предшествующим параметру переменной четкости, будут оценены и результаты сохранены в массив, который будет передан в вызов метода.

Вот пример для иллюстрации:

public static String ezFormat(Object... args) {
    String format = new String(new char[args.length])
        .replace("\0", "[ %s ]");
    return String.format(format, args);
}
public static void main(String... args) {
    System.out.println(ezFormat("A", "B", "C"));
    // prints "[ A ][ B ][ C ]"
}

И да, приведенный выше метод main является корректным, поскольку, опять же, String... - это просто String[]. Кроме того, поскольку массивы ковариантны, String[] является Object[], поэтому вы также можете вызвать ezFormat(args) в любом случае.

См. также


Varargs gotchas #1: passing null

То, как разрешаются varargs, довольно сложно, и иногда это делает вещи, которые могут вас удивить.

Рассмотрим этот пример:

static void count(Object... objs) {
    System.out.println(objs.length);
}

count(null, null, null); // prints "3"
count(null, null); // prints "2"
count(null); // throws java.lang.NullPointerException!!!

Из-за того, как разрешаются варарги, последнее утверждение вызывает objs = null, что, конечно, вызовет NullPointerException с objs.length. Если вы хотите передать один null аргумент параметру varargs, вы можете сделать одно из следующих действий:

count(new Object[] { null }); // prints "1"
count((Object) null); // prints "1"

Похожие вопросы

Ниже приведена выборка некоторых вопросов, которые люди задавали при работе с varargs:


Vararg gotchas #2: добавление дополнительных аргументов

Как вы уже выяснили, следующее не "работает":

    String[] myArgs = { "A", "B", "C" };
    System.out.println(ezFormat(myArgs, "Z"));
    // prints "[ [Ljava.lang.String;@13c5982 ][ Z ]"

Из-за того, как работают varargs, ezFormat фактически получает 2 аргумента, первый - String[], второй - String. Если вы передаете массив в varargs и хотите, чтобы его элементы распознавались как отдельные аргументы, а также вам нужно добавить дополнительный аргумент, то у вас нет другого выбора, кроме как создать другой массив, который вместит дополнительный элемент.

Вот несколько полезных вспомогательных методов:

static <T> T[] append(T[] arr, T lastElement) {
    final int N = arr.length;
    arr = java.util.Arrays.copyOf(arr, N+1);
    arr[N] = lastElement;
    return arr;
}
static <T> T[] prepend(T[] arr, T firstElement) {
    final int N = arr.length;
    arr = java.util.Arrays.copyOf(arr, N+1);
    System.arraycopy(arr, 0, arr, 1, N);
    arr[0] = firstElement;
    return arr;
}

Теперь вы можете сделать следующее:

    String[] myArgs = { "A", "B", "C" };
    System.out.println(ezFormat(append(myArgs, "Z")));
    // prints "[ A ][ B ][ C ][ Z ]"

    System.out.println(ezFormat(prepend(myArgs, "Z")));
    // prints "[ Z ][ A ][ B ][ C ]"

Ошибки Varargs #3: передача массива примитивов

Это не "работает":

    int[] myNumbers = { 1, 2, 3 };
    System.out.println(ezFormat(myNumbers));
    // prints "[ [I@13c5982 ]"

Varargs работает только со ссылочными типами. Автобоксинг не применяется к массивам примитивов. Работает следующее:

    Integer[] myNumbers = { 1, 2, 3 };
    System.out.println(ezFormat(myNumbers));
    // prints "[ 1 ][ 2 ][ 3 ]"
300
ответ дан 23 November 2019 в 02:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: