Вараги Java не обнаруживают, когда вызывают метод vararg внутри другого метода vararg

Я реализовал методы Java для разрешения условий IN и OR.

Ниже мой код.

public static <T> boolean in(T parameter, T... values) {
    if (null != values) {
        System.out.println("IN values size.. " + values.length);
        return Arrays.asList(values).contains(parameter);
    }
    return false;
}

public static boolean or(boolean... values) {
    System.out.println("OR values size.. " + values.length);
    return in(true, values);
}

public static void main(String[] args) {
    System.out.println(or(false, true, false));
}

Выход:

OR values size.. 3
IN values size.. 1
false

Но я ожидал следующего результата:

OR values size.. 3
IN values size.. 3
true

Я не понимаю, почему размер varargs равен 1 в методе in.


person Chamly Idunil    schedule 08.09.2015    source источник


Ответы (3)


В методе

in(T parameter, T... values) //in(true, values); // values is T

Когда вы передаете логический массив values, весь массив принимается как один элемент T Вот причина его показа 1.

Вы передаете логический массив, а тип приема — T, где каждый элемент рассматривается как массив.

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

person Suresh Atta    schedule 08.09.2015
comment
Благодарю. так какое решение. Я имею в виду зацикливание значений внутри или, если существует истинное условие, вернуть true? - person Chamly Idunil; 08.09.2015
comment
@ChamlyIdunil Кажется, вам это никогда не понадобится в методе. Вы можете написать эту единственную строку в самом методе or. Если вы все еще хотите поддерживать метод, проверьте тип элемента в вашем методе in. Если он имеет тип массива, зациклите этот объект и вернитесь, если contains - person Suresh Atta; 08.09.2015
comment
да. Благодарю. но все же его повторяющаяся вещь. одно и то же в двух местах написали? - person Chamly Idunil; 08.09.2015
comment
но когда он переходит к одному методу, возникает та же проблема. даже я использую return Arrays.asList(values).contains(Boolean.TRUE); и когда я вызываю метод как или (ложь, истина, ложь), он возвращает ложь. - person Chamly Idunil; 08.09.2015
comment
stackoverflow.com/questions/8260881/ - person Suresh Atta; 08.09.2015
comment
@ChamlyIdunil - примитивы - это боль. либо измените or() на or(Boolean...), либо перегрузите in() на in(boolean parameter, boolean... values) - person ZhongYu; 08.09.2015

Когда вы вводите or, параметр boolean... values преобразуется в массив boolean. Затем, когда вы вызываете in(true, values), второй параметр in на самом деле представляет собой массив примитивного типа boolean (то есть одно значение). Настоящая проблема заключается в том, что Java не упаковывает автоматически массив примитивных типов.

public static boolean or(boolean... values) {
    System.out.println("OR values size.. " + values.length);
    // here values is an array of the primitive boolean
    return in(true, values);
}

public static void main(String[] args) {
    System.out.println(or(false, true, false));
}

Вы можете решить эту проблему, упаковав свой boolean в объект Boolean следующим образом:

public static <T> boolean in(T parameter, T... values) {
    if (null != values) {
        System.out.println("IN values size.. " + values.length);
        return Arrays.asList(values).contains(parameter);
    }
    return false;
}

public static boolean or(boolean... values) {
    System.out.println("OR values size.. " + values.length);
    Boolean[] boxedValues = new Boolean[values.length];
    for (int i = 0; i < values.length; i++) {
        boxedValues[i] = values[i];
    }
    return in(true, boxedValues);
}

public static void main(String[] args) {
    System.out.println(or(false, true, false));
}

Обратите внимание, что начиная с Java 7 этот код выдает предупреждение, которое можно отключить с помощью аннотации @SafeVarargs.

person Tunaki    schedule 08.09.2015
comment
Благодарю. так какое решение. Я имею в виду зацикливание значений внутри или, если существует истинное условие, вернуть true? - person Chamly Idunil; 08.09.2015
comment
к сожалению, мы используем Java 1.6. также, поскольку мы зацикливаем значения в стороне ИЛИ, мы можем вернуть true, когда есть истинное значение, вместо того, чтобы иметь другой логический массив и вызывать метод IN. - person Chamly Idunil; 08.09.2015

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

/**
 * Can rebox a boxed primitive array into its Object form.
 *
 * Generally I HATE using instanceof because using it is usually an indication that your hierarchy is completely wrong.
 *
 * Reboxing - however - is an area I am ok using it.
 *
 * Generally, if a primitive array is passed to a varargs it is wrapped up as the first and only component of an Object[].
 *
 * E.g.
 *
 * public void f(T... t) {}; f(new int[]{1,2});
 *
 * actually ends up calling f with t an Object[1] and t[0] the int[].
 *
 * This unwraps it and returns the correct reboxed version.
 *
 * In the above example it will return an Integer[].
 *
 * Any other array types will be returned unchanged.
 *
 * @author OldCurmudgeon
 */
public static class Rebox {

    public static <T> T[] rebox(T[] it) {
        // Default to return it unchanged.
        T[] result = it;
        // Special case length 1 and it[0] is primitive array.
        if (it.length == 1 && it[0].getClass().isArray()) {
            // Which primitive array is it?
            if (it[0] instanceof int[]) {
                result = rebox((int[]) it[0]);
            } else if (it[0] instanceof long[]) {
                result = rebox((long[]) it[0]);
            } else if (it[0] instanceof float[]) {
                result = rebox((float[]) it[0]);
            } else if (it[0] instanceof double[]) {
                result = rebox((double[]) it[0]);
            } else if (it[0] instanceof char[]) {
                result = rebox((char[]) it[0]);
            } else if (it[0] instanceof byte[]) {
                result = rebox((byte[]) it[0]);
            } else if (it[0] instanceof short[]) {
                result = rebox((short[]) it[0]);
            } else if (it[0] instanceof boolean[]) {
                result = rebox((boolean[]) it[0]);
            }
        }
        return result;
    }

    // Rebox each one separately.
    private static <T> T[] rebox(int[] it) {
        T[] boxed = makeTArray(it.length);
        for (int i = 0; i < it.length; i++) {
            boxed[i] = (T) Integer.valueOf(it[i]);
        }
        return boxed;
    }

    private static <T> T[] rebox(long[] it) {
        T[] boxed = makeTArray(it.length);
        for (int i = 0; i < it.length; i++) {
            boxed[i] = (T) Long.valueOf(it[i]);
        }
        return boxed;
    }

    private static <T> T[] rebox(float[] it) {
        T[] boxed = makeTArray(it.length);
        for (int i = 0; i < it.length; i++) {
            boxed[i] = (T) Float.valueOf(it[i]);
        }
        return boxed;
    }

    private static <T> T[] rebox(double[] it) {
        T[] boxed = makeTArray(it.length);
        for (int i = 0; i < it.length; i++) {
            boxed[i] = (T) Double.valueOf(it[i]);
        }
        return boxed;
    }

    private static <T> T[] rebox(char[] it) {
        T[] boxed = makeTArray(it.length);
        for (int i = 0; i < it.length; i++) {
            boxed[i] = (T) Character.valueOf(it[i]);
        }
        return boxed;
    }

    private static <T> T[] rebox(byte[] it) {
        T[] boxed = makeTArray(it.length);
        for (int i = 0; i < it.length; i++) {
            boxed[i] = (T) Byte.valueOf(it[i]);
        }
        return boxed;
    }

    private static <T> T[] rebox(short[] it) {
        T[] boxed = makeTArray(it.length);
        for (int i = 0; i < it.length; i++) {
            boxed[i] = (T) Short.valueOf(it[i]);
        }
        return boxed;
    }

    private static <T> T[] rebox(boolean[] it) {
        T[] boxed = makeTArray(it.length);
        for (int i = 0; i < it.length; i++) {
            boxed[i] = (T) Boolean.valueOf(it[i]);
        }
        return boxed;
    }

    // Trick to make a T[] of any length.
    // Do not pass any parameter for `dummy`.
    // public because this is potentially re-useable.
    public static <T> T[] makeTArray(int length, T... dummy) {
        return Arrays.copyOf(dummy, length);
    }
}

public static <T> boolean in(T parameter, T... values) {
    if (null != values) {
        System.out.println("IN values size.. " + values.length);
        return Arrays.asList(values).contains(parameter);
    }
    return false;
}

public static boolean or(boolean... values) {
    System.out.println("OR values size.. " + values.length);
    return in(true, Rebox.rebox(values));
}

public void test() {
    System.out.println(or(false, true, false));
}

Это печатает:

OR values size.. 3
IN values size.. 3
true

как вам требуется.

person OldCurmudgeon    schedule 08.09.2015