Java中如何打印数组

7

我正在编写一个方法,用于打印传递给它的每个对象。对于对象,可以通过调用Object.toString()方法来实现这一点,但是对于数组则不行。可以使用Object.getClass().isArray()方法确定是否为数组,但是我不知道如何进行强制类型转换。

int[] a;
Integer[] b;

Object aObject = a;
Object bObject = b;

// this wouldn't work
System.out.println(Arrays.toString(aObject));
System.out.println(Arrays.toString(bObject));
5个回答

12

如果你不知道类型,可以将对象转换为 Object[] 并像这样打印它(在确保它确实是数组并可以转换为 Object[] 之后)。如果它不是 Object[] 的实例,则使用反射先创建一个 Object[],然后再打印:

private void printAnyArray(Object aObject) {
    if (aObject.getClass().isArray()) {
        if (aObject instanceof Object[]) // can we cast to Object[]
            System.out.println(Arrays.toString((Object[]) aObject));
        else {  // we can't cast to Object[] - case of primitive arrays
            int length = Array.getLength(aObject);
            Object[] objArr = new Object[length];
            for (int i=0; i<length; i++)
                objArr[i] =  Array.get(aObject, i);
            System.out.println(Arrays.toString(objArr));
        }
    }
}

测试:

printAnyArray(new int[]{1, 4, 9, 16, 25});
printAnyArray(new String[]{"foo", "bar", "baz"});

输出:

[1, 4, 9, 16, 25]
[foo, bar, baz]

我该如何找出它是否为原始数组?同时,我需要知道该数组的原始类型。 - multiholle
请检查更新后的代码,现在它将打印任何数组对象,而无需您在丑陋的if/elseif/else链中转换为每个原始类型。 - anubhava
1
@PaulBellora 我已经阅读了很多文章,警告我们不要使用所谓的“昂贵”反射,但也看到几乎每个现代框架都充分利用它。例如,请阅读这篇文章:http://buzdin.blogspot.com/2011/01/is-java-reflection-really-slow.html 我的建议是:确保你有一个合适的用例来使用反射,并且我认为这个问题正好适合使用反射。 - anubhava
这对我来说很好,因为它仅用于调试,性能并不那么重要。谢谢你的想法。 - multiholle
1
太棒了,正是我需要的。 - Alex
显示剩余2条评论

1

如果你想知道如何在任何数组上以编程方式调用此方法,那么对于原始数组来说这是不可能的。查看Arrays 类的文档,你会看到每个原始数组类型都有一个toString() 重载。

这是因为例如int[] 扩展自Object 而不是Object[]

编辑:以下是包括原始数组的可行但啰嗦的解决方案:

public static void printObject(Object obj) {

    String output;

    if (obj == null) {
        output = "null";
    }
    else if (obj.getClass().isArray()) {

        if (obj instanceof Object[]) {
            output = Arrays.toString((Object[])obj); //Object[] overload
        }
        else if (obj instanceof int[]) {
            output = Arrays.toString((int[])obj);    //int[] overload
        }
        //and so on for every primitive type
    }
    else {
        output = obj.toString();
    }

    System.out.println(output);
}

我希望其他人能提供更优雅的解决方案,但基于原始数组的限制,这可能是你能做的最好的。


1
为什么不使用方法重载来解决你的问题呢?只需编写两个(或更多)具有相同名称但不同签名的方法,然后让编译器在程序执行时决定将调用哪个方法:
void print(Object object) {
   System.out.println("Object: " + object);
}

void print(Object[] array) {
    System.out.println("Object[]: " Arrays.toString(array)); 
}

void print(int[] array) {
    System.out.println("int[]: " Arrays.toString(array)); 
}

在代码的其他地方使用示例:

String first = "test";
print(first);   // prints "Object: test";

String[] second = {"A", "B"};    
print(second);   // prints "Object[]: [A, B]" 

int[] third = {1, 2};
print(third);    // prints "int[]: [1, 2]"

0

如果您不想依赖于对象的类本身来重载对象的toString方法(以获得比打印类名和哈希码更有用的内容),则需要使用反射来深入了解对象的结构。

我的建议是使用一个使用反射来深入了解结构的库,例如GSON:http://code.google.com/p/google-gson/

public static String print(Object object) {
    return new Gson().toJson(object);
}

public static void test() {
    System.out.println(print(new int[][] {new  int[] {1, 2, 3} }));
    // outputs: [[1,2,3]]
    System.out.println(print(new String[] { "aa", "bb", "cc" }));
    // outputs: ["aa","bb","cc"]
}

这个程序可以轻松地打印数组,包括多维数组和基本数组。

但真正的好处在于它以统一的方式打印任何类的对象,无论该类是否以有用的方式重写了toString方法。


-2
如果你只是想将它作为字符串打印出来,为什么要进行强制类型转换呢?只需将其视为对象数组,遍历该数组,然后在每个对象上调用toString()方法即可。

但如果它包含基本类型,我就无法将其转换为“Object”数组。 - multiholle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接