How to see if an object is an array without using reflection?

如果一个对象是一个数组而不使用反射,我如何在 Java 中看到? 如何在不使用反射的情况下迭代所有项?

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

我希望能够实现以下方法,而不用反思:

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


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

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

126557 次浏览

你可以使用 instanceof

JLS 15.20.2 Type Comparison Operator instanceof

 RelationalExpression:
RelationalExpression instanceof ReferenceType

在运行时,如果 关系表达式的值不是 null,那么 instanceof操作符的结果是 true,并且引用可以在不引发 ClassCastException的情况下强制转换为 ReferenceType 参考类型。否则结果就是 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[]

而且,int[][]instanceof Object[],因此取决于您希望如何处理嵌套数组,它可能会变得复杂。

对于 toStringjava.util.Arrays有一个 toString(int[])和其他可以使用的重载。它还有一个用于嵌套数组的 deepToString(Object[])

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

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

参见

在基元类型的数组之间,或者在基元类型的数组和引用类型的数组之间,不存在子类型关系。参见 JLS 4.10.3

Therefore, the following is incorrect as a test to see if obj is an array of any kind:

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

Specifically, it doesn't work if obj is 1-D array of primitives. (It does work for primitive arrays with higher dimensions though, because all array types are subtypes of Object. But it is moot in this case.)

我使用 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[];
    }
    
  • You could also try messing around with the name of the object's class as follows, but the call to obj.getClass() is bordering on reflection.

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

1 - More precisely, the Class.isArray method is listed as supported by GWT in this page.

你可以使用 Class.isArray()

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

这对对象类型数组和基元类型数组都适用。

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

One can access each element of an array separately using the following code:

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

Notice that it is unnecessary to know what kind of underlying array it is, as this will work for any array.

You can create a utility class to check if the class represents any 收集, 地图 or 数组

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

简单的 obj instanceof Object[](在 JShell 上测试)。