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

可变长度参数列表将泛型和泛型数组作为参数传递-Java,java,generics,arguments,variable-length,Java,Generics,Arguments,Variable Length,我正在尝试编写一个助手打印方法,这样我就可以用更少的代码和更简单的方式将项目打印到控制台 但是,我在打印传递到方法中的数组时遇到了问题,因为我无法循环一个常规泛型变量(E),但是我没有看到一种不可能重载方法的方法来修复它 当我检查变量是否是泛型类型的数组时,为什么循环在我的实例中不起作用?我觉得这至少应该允许对数组进行转换(这是注释代码现在显示的内容),但这也失败了,这让我认为在Java中从E转换到E[]是不可能的 这是我的代码: @SafeVarargs@SuppressWarnings("u

我正在尝试编写一个助手打印方法,这样我就可以用更少的代码和更简单的方式将项目打印到控制台

但是,我在打印传递到方法中的数组时遇到了问题,因为我无法循环一个常规泛型变量(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);
        }
    }
}
@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
    }

}

现在,无论是原语、包装类中的元素、数组、列表还是其他任何内容,所有内容都在自己的行上打印。

如果编写
publicstaticvoidprint(E…toPrint){
它将要求所有输入都是相同的类(
E
),并调用类似
print(1,2,3,“Hello”);
行不通

您应该将方法更改为
publicstaticvoidprint(Object…toPrint)

您可以自由地投射
(Object[])项

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()
函数将其转换


如果您确定输入的类型相同(例如,您没有将
String
int
混合,那么您肯定应该编写接受原语类型的重载版本)。否则,请尝试上述实现。

如果您编写
公共静态无效打印(E…toPrint){
它将要求所有输入都是相同的类(
E
)。并调用类似
print(1,2,3,“Hello”);
行不通

您应该将方法更改为
publicstaticvoidprint(Object…toPrint)

您可以自由地投射
(Object[])项

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()
函数将其转换


如果您确定输入的类型相同(例如,您没有将
String
int
混合,那么您肯定应该编写接受基元类型的重载版本)。否则,请尝试上述实现。

您的代码不起作用,因为您试图将数组类型
E
强制转换为数组-
E[]

如果执行进入If语句,这意味着
E
是数组类型。因此
E[]
是数组的数组。
E[]
E
是不相关的类型

因此,您需要了解如何让编译器知道您确信
E
是一个数组,并且它可以循环

所以,是的,你需要重载
打印
。这种技术在标准库中被广泛使用。只要看看这个类,几乎所有的方法都有各种数组的重载。Java数组有很多限制,你不得不忍受

顺便问一下,你知道有一种叫做数组的简便方法吗?toString
?它可以简化数组打印过程:

System.out.println(Arrays.toString(arr));
也许你根本不需要打印

注:

您的代码可以工作,但不适用于基元类型数组,因此如果您传入一个
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);
        }
    }
}

您的代码无法工作,因为您试图将数组类型
E
强制转换为数组数组-
E[]

如果执行进入If语句,这意味着
E
是数组类型。因此
E[]
是数组的数组。
E[]
E
是不相关的类型

因此,您需要了解如何让编译器知道您确信
E
是一个数组,并且它可以循环

所以,是的,你需要重载
打印
。这种技术在标准库中被广泛使用。只要看看这个类,几乎所有的方法都有各种数组的重载。Java数组有很多限制,你不得不忍受

顺便问一下,你知道有一种叫做数组的简便方法吗?toString
?它可以简化数组打印过程:

System.out.println(Arrays.toString(arr));
也许你根本不需要打印

注:

您的代码可以工作,但不适用于基元类型数组,因此如果您传入一个
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);
        }
    }
}

使用原语类型
int
Array
包装类可以解决您的问题

Integer[] arr = {4, 5, 6};
print(arr);
而不是:

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

现在,当您传递
int[]
数组并尝试将其转换为E[]时会发生什么?实际上,它尝试将数组转换为
Integer[]
。因此,基本上尝试对数组进行自动装箱,但只有原语类型的
自动装箱是可能的,但我们不能
自动装箱
原语
键入数组inke
int[]

使用
数组
基元类型的包装类
int
,它是整数,可以解决您的问题

Integer[] arr = {4, 5, 6};
print(arr);
而不是:

print(1, 2, 3, "Hello");
int[] arr = {4, 5, 6};
print(arr);
现在,当您传递
int[]
数组并尝试将其转换为E[]时会发生什么?实际上,它尝试将数组转换为
Integer[]
。因此,基本上尝试对数组进行自动装箱,但只有原语类型的
自动装箱是可能的,但我们不能
自动装箱
原语
键入数组inke
int[]

您可以使用