Java 数组反射: isArray 与 instanceof

使用:

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

还有

if(obj instanceof Object[]) {}

144992 次浏览

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

除了明显的空情况之外,我发现这两者在行为上没有什么不同。至于选择哪个版本,我会选择第二个版本。这是在 Java 中实现这一点的标准方法。

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

如果你要在反射式解决方案和非反射式解决方案之间做出选择,千万不要选择反射式解决方案(涉及 Class 对象)。这并不是说它是“错误的”或任何东西,但任何涉及反射的东西通常都不那么明显和清晰。

在大多数情况下,应该使用 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

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

在 SunJava5或6JRE 上,getClass().isArray()明显慢于 IBM。

以至于在 Sun JVM 上使用 clazz.getName().charAt(0) == '['更快。

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

我在十二月的早些时候在博客上写过这个。 Http://blog.adamsbros.org/2010/12/08/java-array-reflection/

我最近遇到了一个问题,将 Groovy 应用程序从 JDK5升级到 JDK6。在 JDK6中使用 isArray()失败:

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

改成 instanceof Object[]修正了这个问题。