Java数组反射:isArray与instanceof

时间:2008-10-20 20:56:37

标签: java arrays reflection

使用之间是否存在偏好或行为差异:

if(obj.getClass().isArray()) {}

if(obj instanceof Object[]) {}

8 个答案:

答案 0 :(得分:198)

在大多数情况下,您应该使用instanceof运算符来测试对象是否为数组。

通常,在向下转换为编译时已知的特定类型之前测试对象的类型。例如,您可能编写了一些可以使用Integer[]int[]的代码。你想用instanceof保护你的演员:

if (obj instanceof Integer[]) {
    Integer[] array = (Integer[]) obj;
    /* Use the boxed array */
} else if (obj instanceof int[]) {
    int[] array = (int[]) obj;
    /* Use the primitive array */
} else ...

在JVM级别,instanceof运算符转换为特定的"instanceof"字节代码,该代码在大多数JVM实现中进行了优化。

在极少数情况下,您可能使用反射来遍历未知类型的对象图。在这种情况下,isArray()方法可能会有所帮助,因为您在编译时不知道组件类型;例如,您可能正在实现某种序列化机制,并且无论类型如何,都能够将数组的每个组件传递给相同的序列化方法。

有两种特殊情况:空引用和对基本数组的引用。

空引用会导致instanceof结果为false,而isArray会引发NullPointerException

应用于基本数组,instanceof产生false,除非右侧操作数上的组件类型与组件类型完全匹配。相反,isArray()将为任何组件类型返回true

答案 1 :(得分:32)

在后一种情况下,如果obj为null,则不会得到NullPointerException而是false。

答案 2 :(得分:8)

如果obj的类型为int[],那么它将有一个数组Class,但不是Object[]的实例。那么你想用obj做什么?如果您要进行投射,请使用instanceof。如果您要使用反射,请使用.getClass().isArray()

答案 3 :(得分:5)

我最近遇到了将Groovy应用程序从JDK 5升级到JDK 6的问题。在JDK6中使用isArray()失败:

MissingMethodException:
No signature of sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl.isArray() ...

更改为instanceof Object[]已解决此问题。

答案 4 :(得分:4)

对于Sun Java 5或6 JRE,

getClass().isArray()明显慢于IBM。

在Sun JVM上使用clazz.getName().charAt(0) == '['的速度更快。

答案 5 :(得分:3)

Java数组反射适用于您没有可用于执行“instanceof”的类实例的情况。例如,如果您正在编写某种注入框架,它将值注入到类的新实例中,例如JPA,那么您需要使用isArray()函数。

我在12月早些时候在博客上写过这篇文章。 http://blog.adamsbros.org/2010/12/08/java-array-reflection/

答案 6 :(得分:2)

如果您可以选择反射解决方案和非反射解决方案,请不要选择反射解决方案(涉及Class对象)。这不是“错误”或任何事情,但任何涉及反思的事情通常都不那么明显,也不那么清晰。

答案 7 :(得分:0)

我可以在两者之间找到的行为没有区别(明显的空案例除外)。至于喜欢哪个版本,我会选择第二个版本。这是在Java中执行此操作的标准方法。

如果它使您的代码的读者感到困惑(因为String[] instanceof Object[]为真),如果代码审核者不断询问,您可能希望使用第一个更明确。