可变长度参数列表将泛型和泛型数组作为参数传递 - Java

时间:2018-05-07 16:03:13

标签: java generics arguments variable-length

我正在尝试编写辅助打印方法,因此我可以使用更少的代码以更简单的方式将项目打印到控制台。

然而,我遇到了打印传递到我的方法中的数组的问题,因为我无法循环遍历常规泛型变量(E),但是我没有看到修复它的方法而不会重载方法。

当我检查变量是泛型类型的数组时,为什么循环在我的实例中不起作用?我觉得这应该至少允许一个数组的转换(这是评论代码现在显示的内容),但是也失败了,这让我觉得从Java到E [E]的转换是不可能的。

这是我的代码:

@SafeVarargs@SuppressWarnings("unchecked")//SAFE
public static <E> void print(E... toPrint){
    //USED TO ENHANCE SYSTEM.OUT.PRINTLN AND MAKE EASIER TO TYPE
    E[] itemArray;
    for(E item: toPrint){
        if(item.getClass().isArray()){//IS ARRAY
            //System.out.println(item.getClass());
            //itemArray = (E[]) item;//WILL NOT WORK, CANNOT CONVERT
            ////IF LOOP ITEM ERROR NOT ITERABLE, BUT IT IS ARRAY?
            //for(E innerItem: itemArray)
                //System.out.println(innerItem);
        }else{
            System.out.println(item);
        }
    }
}

根据@ Sweeper的建议更新代码:

@SafeVarargs//SAFE
public static <E> void print(E... toPrint){
    //USED TO ENHANCE SYSTEM.OUT.PRINTLN AND MAKE EASIER TO TYPE

    for(E item: toPrint){
        if(item.getClass().isArray()){//IF IS ARRAY
            printHelperForArrays(item);//MUST CHECK IF PRIMITIVE[] OR OBJECT[] 
        }else if (item instanceof List){//IF ITEM IS LIST
            String[] stringArray = item.toString()
                    .replace("[","")//REMOVE [
                    .replace("]","")//REMOVE ]
                    .split(", ");//TURN TO ARRAY
            for(String innerItem: stringArray)
                System.out.println(innerItem);//NOW PRINT EVERYTHING OUT
        }else{
            System.out.println(item);
        }
    }//END FOR
}

@SuppressWarnings("unchecked")//SAFE
public static <E> void printHelperForArrays(E item){
    //USED TO PRINT OUT ARRAY ELEMENTS
    if(item.getClass() == int[].class){//IS INT[]

        String[] stringArray = Arrays.toString((int[])item)
             .replace("[","")//REMOVE [
             .replace("]","")//REMOVE ]
            .split(", ");//TURN TO ARRAY

        for(String innerItem: stringArray)
            System.out.println(innerItem);//NOW PRINT EVERYTHING

    }else if(item.getClass() == double[].class){//IS DOUBLE[]

         String[] stringArray = Arrays.toString((double[])item)
            .replace("[","")//REMOVE [
            .replace("]","")//REMOVE ]
            .split(", ");//TURN TO ARRAY

            for(String innerItem: stringArray)
                System.out.println(innerItem);//NOW PRINT EVERYTHING OUT

    }else if(item.getClass() == float[].class){//IS FLOAT[]

        String[] stringArray = Arrays.toString((float[])item)
            .replace("[","")//REMOVE [
            .replace("]","")//REMOVE ]
            .split(", ");//TURN TO ARRAY

        for(String innerItem: stringArray)
            System.out.println(innerItem);//NOW PRINT EVERYTHING OUT

    }else if(item.getClass() == char[].class){//IS CHAR[]

        String[] stringArray = Arrays.toString((char[])item)
            .replace("[","")//REMOVE [
            .replace("]","")//REMOVE ]
            .split(", ");//TURN TO ARRAY

        for(String innerItem: stringArray)
            System.out.println(innerItem);//NOW PRINT EVERYTHING OUT

    }else if(item.getClass() == boolean[].class){//IS BOOLEAN[]

        String[] stringArray = Arrays.toString((boolean[])item)
            .replace("[","")//REMOVE [
            .replace("]","")//REMOVE ]
            .split(", ");//TURN TO ARRAY

        for(String innerItem: stringArray)
            System.out.println(innerItem);//NOW PRINT EVERYTHING OUT

    }else if(item.getClass() == byte[].class){//IS BYTE[]

        String[] stringArray = Arrays.toString((byte[])item)
            .replace("[","")//REMOVE [
            .replace("]","")//REMOVE ]
            .split(", ");//TURN TO ARRAY

        for(String innerItem: stringArray)
            System.out.println(innerItem);//NOW PRINT EVERYTHING OUT

    }else if(item.getClass() == short[].class){//IS SHORT[]

        String[] stringArray = Arrays.toString((short[])item)
            .replace("[","")//REMOVE [
            .replace("]","")//REMOVE ]
            .split(", ");//TURN TO ARRAY

        for(String innerItem: stringArray)
            System.out.println(innerItem);//NOW PRINT EVERYTHING OUT

    }else if(item.getClass() == long[].class){//IS LONG[]

        String[] stringArray = Arrays.toString((long[])item)
            .replace("[","")//REMOVE [
            .replace("]","")//REMOVE ]
            .split(", ");//TURN TO ARRAY

        for(String innerItem: stringArray)
            System.out.println(innerItem);//NOW PRINT EVERYTHING OUT

    }else{//IS OBJECT[] LIKE INTEGER[], STRING[], CHARACTER[]... SO E[] WORKS

        String[] stringArray = Arrays.toString((E[])item)
            .replace("[","")//REMOVE [
            .replace("]","")//REMOVE ]
            .split(", ");//TURN TO ARRAY

            for(String innerItem: stringArray)
                System.out.println(innerItem);//NOW PRINT EVERYTHING OUT
    }

}

通过Args:

int[] int1 = {4, 5, 6};
Integer[] Integer2 = {7, 8, 9};

double[] double3 = {10.01, 11.01, 12.01};
Double[] Double4 = {13.01, 14.01, 15.01};

char[] char5 = {'A', 'B', 'C'};
Character[] Character6 = {'D', 'E', 'F'};

float[] float7 = {1.999f, 2.999f};
Float[] Float8 = {3.999f, 4.999f};

LinkedList<String> listOfStrings = new LinkedList<>();
listOfStrings.add("List Item 1");
listOfStrings.add("List Item 2");

//CALLED AS
print(1, 2, 3, "Hello", int1, Integer2, double3, 
    Double4, char5, Character6, float7, Float8, listOfStrings);

输出

1
2
3
Hello
4
5
6
7
8
9
10.01
11.01
12.01
13.01
14.01
15.01
A
B
C
D
E
F
1.999
2.999
3.999
4.999
List Item 1
List Item 2

现在一切都打印在它自己的行上,无论它是一个原语,一个Wrapper类中的元素,一个数组,一个列表,还是其他什么。

4 个答案:

答案 0 :(得分:1)

如果你写public static <E> void print(E... toPrint){,它将要求所有输入都是同一个类(E)。并调用print(1, 2, 3, "Hello");之类的方法  将无法正常工作

您应该将方法更改为public static void print(Object... toPrint)

你可以自由地投射(Object[])item

public static void print(Object... items) {
    for (Object item: items) {
        if (item.getClass().isArray()) {
            Object[] objs =primitiveArrayFrom(item);
            if (objs == null) {
                objs = (Object[]) item;
            }
            for (Object obj: objs) {
                System.out.println(obj);
            }

        } else {
            System.out.println(item);
        }
    }
}

private static Object[] primitiveArrayFrom(Object obj) {
    if (obj instanceof int[]) {
        int[] integers = (int[]) obj;
       return IntStream.of(integers).boxed().toArray();
    }
    // Test for other primitives here
    //finally
    return null;
}

不幸的是,没有办法直接将原始数组的对象转换为Object[],因此您必须通过primitiveArrayFrom ()函数将其转换。

如果您确定您的输入属于同一类型(例如,您不要将Stringint混合,那么您肯定应该编写接受原始类型的重载版本)。否则,请尝试上面的实现。

答案 1 :(得分:1)

您的代码无效,因为您正在尝试将数组类型E强制转换为数组 - E[]

如果执行进入if语句,则表示E是一种数组类型。所以E[]是一个数组数组。 E[]E是不相关的类型。

所以你需要了解一些如何让编译器知道你确定E是一个数组并且它可以循环。但是,在Java中没有办法做到这一点。

所以是的,你需要重载print。该技术广泛用于标准库中。只需查看Arrays类,几乎每种方法都有各种数组的重载。 Java数组有许多限制,你必须忍受。

顺便问一下,你知道有一个名为Arrays.toString的方便方法吗?它可以简化阵列打印过程:

System.out.println(Arrays.toString(arr));

也许您毕竟不需要print

注意:

您的代码可以正常工作,但不适用于原始类型数组,因此如果传入Integer[],它将成功打印出来。

编辑:

您可以通过针对每种类型的基本数组检查类型来解决此问题:

public static void print(Object... toPrint) {
    for (Object item : toPrint) {
        if (item.getClass() == int[].class) {
            System.out.println(Arrays.toString((int[])item));
        } else if (item.getClass() == double[].class) { // check for all primitive types
            System.out.println(Arrays.toString((double[])item));
        } else if (item instanceof Object[]){
            System.out.println(Arrays.toString((Object[])item));
        } else {
            System.out.println(item);
        }
    }
}

答案 2 :(得分:1)

使用Array原始类型int的包装类,它是Integer将解决您的问题。

Integer[] arr = {4, 5, 6};
print(arr);

而不是:

print(1, 2, 3, "Hello");
int[] arr = {4, 5, 6};
print(arr);

现在,当您传递int[]数组并尝试将其转换为E []时会发生什么,它实际上会尝试转换为Integer[]。因此,基本上尝试对数组进行自动装箱,但只能使用autoboxing原始类型,但我们可以auto box primitive类型数组inke int[]

答案 3 :(得分:1)

您可以使用Array.get()索引数组而不知道其类型:

for (int i = 0, len = Array.getLength(item); i < len; i++)
    System.out.println(Array.get(item, i));