Странность обработки объектов Varags - PullRequest
3 голосов
/ 16 февраля 2011

Не думаю, что я понимаю, как varargs обрабатывает передаваемые объекты:

public class NoSense {

public static void someMethod(String a, Object... things) {

    System.err.println("a->" + a);

    System.err.println(things.getClass().getName());

    for (Object object : things) {
        System.err.println("thing->" + object);
    }


}


public static void main(String[] args) {
    String[] x = new String[] { "what", "is", "up?" };
    NoSense.someMethod("1", x);
    NoSense.someMethod("2", x, "extra");
}

}

Результаты:

a->1
[Ljava.lang.String;
thing->what
thing->is
thing->up?
a->2
[Ljava.lang.Object;
thing->[Ljava.lang.String;@4d20a47e
thing->extra

Зачем этотрактовать первый набор как массив строк, а второй как ссылку на массив объектов?

Ответы [ 3 ]

2 голосов
/ 16 февраля 2011

Для обеспечения обратной совместимости, varargs - последнее, что компилятор пытается разрешить вызов метода. Поскольку вызов NoSense.someMethod("1", x); может быть разрешен как someMethod(String a, Object[] things), он разрешается как таковой. Это можно сделать, потому что типы массивов ковариантны.

Однако вызов NoSense.someMethod("2", x, "extra"); не может быть разрешен как someMethod(String a, Object[] things), и поэтому использует varargs для создания new Object[]{x, "extra"}, который затем передается в качестве параметра вещи.

1 голос
/ 16 февраля 2011

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

Случай 1: В varargs объекта передается только одно значение[].Это значение String [].Java рассматривает его как особый случай и передает массив напрямую.

Случай 2: Два значения передаются в переменные Object [].Первое значение имеет тип String [], а второе имеет тип String.Поскольку передается более одного значения, это , а не особый случай.Таким образом, параметр vargargs - это Object [] (как вы его определили), где первый элемент - это переданный строковый массив, а второй элемент - строка.

1 голос
/ 16 февраля 2011

Поскольку ссылка String[] неявно преобразуется в Object[] через ковариацию массива.Компилятору не нужно использовать varargs, поэтому он не делает этого.

Чтобы принудительно заставил его использовать varargs, мы можем просто привести к Object:

    NoSense.someMethod("1", (Object) x);

Теперь Object неявно не преобразуется в Object[], поэтому компилятор обернет его в массив.

Из раздела 15.12.4.2 JLS:

Если m вызывается с фактическими аргументами k! = N или, если m вызывается с фактическими аргументами k == n, а тип выражения аргумента k не является присваиванием, совместимым с T [], тосписок аргументов (e1, ... , en-1, en, ...ek) оценивается так, как если бы он был записан как (e1, ..., en-1, new T[]{en, ..., ek}).

...