如何在不使用反射的情况下查看对象是否为数组?


99

如何在Java中查看Object是否是不使用反射的数组?而且如何在不使用反射的情况下遍历所有项目?

我使用Google GWT,所以我不允许使用反射:(

我很想在不使用反射的情况下实现以下方法:

private boolean isArray(final Object obj) {
  //??..
}

private String toString(final Object arrayObject) {
  //??..
}

顺便说一句:我也不想使用JavaScript,这样我就可以在非GWT环境中使用它。

Answers:


248

您可以使用 Class.isArray()

public static boolean isArray(Object obj)
{
    return obj!=null && obj.getClass().isArray();
}

这适用于对象和原始类型数组。

对于toString,请看一下Arrays.toString。您必须检查数组类型并调用适当的toString方法。


1
值得补充的是,您可以使用找出数组类型obj.getClass().getComponentType()
史蒂夫·钱伯斯

68

您可以使用instanceof

JLS 15.20.2类型比较运算符 instanceof

 RelationalExpression:
    RelationalExpression instanceof ReferenceType

在运行时,instanceof运算符的结果是:true如果RelationalExpression的值不是null,并且引用可以强制转换为ReferenceType而不引发ClassCastException。否则结果为false

这意味着您可以执行以下操作:

Object o = new int[] { 1,2 };
System.out.println(o instanceof int[]); // prints "true"        

你不得不检查对象是instanceof boolean[]byte[]short[]char[]int[]long[]float[]double[],或者Object[],如果你想检测所有数组类型。

另外,an int[][]是an instanceof Object[],因此取决于您要如何处理嵌套数组,它可能会变得复杂。

对于toStringjava.util.ArraystoString(int[]),你可以用其他重载。它还具有deepToString(Object[])用于嵌套数组的功能。

public String toString(Object arr) {
   if (arr instanceof int[]) {
      return Arrays.toString((int[]) arr);
   } else //...
}

这将是非常重复的(但甚至java.util.Arrays是非常重复的)),但这就是Java中带有数组的方式。

也可以看看


谢谢,没有意识到这是如此简单。不能用T [] :(
edbras

2
顺便说一句:我还注意到另一种很好的方法来发现某物是否是一个数组Class.isArray()(用于Arrays.deepToString())。
edbras

@edbras:是的,这就是郭富城下面所说的。我的解决方案使用纯语言构造而不是API调用。
polygenelubricants 2010年

它工作正常,我只是不使用instanceof而是使用getClass作为比较。类似于:if(array.getClass == int []。class){Arrays.toString((int [])array); }感谢大家..
edbras

@edbras:是的java.util.Arrays,是的。我发现您一直在阅读我链接到的代码。
polygenelubricants 2010年

35

可以使用以下代码分别访问数组的每个元素:

Object o=...;
if ( o.getClass().isArray() ) {
    for(int i=0; i<Array.getLength(o); i++){
        System.out.println(Array.get(o, i));
    }
}

注意,不必知道它是哪种底层数组,因为它适用于任何数组。


2
isArray()在此之前4年发布的答案中已经充分涵盖了该答案。
杰森C

15
这个答案很好,因为它向我们展示了如何在不知道其内容类型的情况下获取数组的大小和检索元素。我敢肯定,大多数人以前从未写过这样的代码。
Christopher Yang

@MaartenBodewes-我将使用此链接来确定“不使用反射”对GWT的含义。
Stephen C

10

基本类型的数组之间,基本类型的数组与引用类型的数组之间没有子类型关系。参见JLS 4.10.3

因此,以下是不正确的测试,以查看是否obj任何类型的数组:

// INCORRECT!
public boolean isArray(final Object obj) {
    return obj instanceof Object[];
}

具体来说,如果obj是图元的一维数组,则不起作用。(尽管它确实适用于具有更高维的基本数组,因为所有数组类型都是。的子类型,Object但是在这种情况下,它没有意义。)

我使用Google GWT,所以我不允许使用反射:(

最佳解决方案(针对问题的isArray数组部分)取决于什么才算是“使用反射”。

  • 在GWT中,调用obj.getClass().isArray()不算作使用反射1,因此这是最佳解决方案。

  • 否则,弄清楚对象是否具有数组类型的最佳方法是使用instanceof表达式序列。

    public boolean isArray(final Object obj) {
        return obj instanceof Object[] || obj instanceof boolean[] ||
           obj instanceof byte[] || obj instanceof short[] ||
           obj instanceof char[] || obj instanceof int[] ||
           obj instanceof long[] || obj instanceof float[] ||
           obj instanceof double[];
    }
  • 您还可以尝试按如下方式弄乱对象的类名,但对的调用obj.getClass()正处于反射中。

    public boolean isArray(final Object obj) {
        return obj.getClass().toString().charAt(0) == '[';
    }

1 -更准确地说,Class.isArray被列为方法,通过GWT在支持此页面


0

您可以创建一个实用程序类来检查该类是否表示任何CollectionMapArray

  public static boolean isCollection(Class<?> rawPropertyType) {
        return Collection.class.isAssignableFrom(rawPropertyType) || 
               Map.class.isAssignableFrom(rawPropertyType) || 
               rawPropertyType.isArray();
 }

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.