Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java varags not detect when call vararg method inside another vararg method

I have implemented Java methods to resolve IN and OR condition.

Below is my code.

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));
}

Output is:

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

But I was expecting the following output:

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

I don't understand why varargs size in 1 in in method.

like image 876
Chamly Idunil Avatar asked Sep 08 '15 08:09

Chamly Idunil


2 Answers

In the method

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

When you are passing a boolean array values, the whole array is taking as a single element T That's the reason for showing it 1.

You are passing boolean array and the receiving type is T, where each element considering as an array.

You can print the values inside in method and see what is the result. Youl' see an array object. Not the individual boolean elements.

like image 73
Suresh Atta Avatar answered Oct 22 '22 18:10

Suresh Atta


When you are entering or, the boolean... values parameter gets converted to an array of boolean. Then, when you call in(true, values), the second parameter of in is actually an array of the primitive type boolean (so a single value). The actual problem is that Java does not automatically box array of primitive types.

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));
}

You can tackle this problem by boxing your boolean to a Boolean object like this:

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));
}

Note that beginning with Java 7, this code will emit a warning that you can disable with the @SafeVarargs annotation.

like image 31
Tunaki Avatar answered Oct 22 '22 19:10

Tunaki