【发布时间】:2010-09-18 04:56:41
【问题描述】:
使用之间是否存在偏好或行为差异:
if(obj.getClass().isArray()) {}
和
if(obj instanceof Object[]) {}
?
【问题讨论】:
标签: java arrays reflection
使用之间是否存在偏好或行为差异:
if(obj.getClass().isArray()) {}
和
if(obj instanceof Object[]) {}
?
【问题讨论】:
标签: java arrays reflection
在后一种情况下,如果 obj 为 null,您将不会得到 NullPointerException 而是 false。
【讨论】:
我可以发现两者之间的行为没有区别(除了明显的 null 情况)。至于更喜欢哪个版本,我会选择第二个。这是在 Java 中执行此操作的标准方式。
如果它让您的代码的读者感到困惑(因为 String[] instanceof Object[] 是真的),如果代码审阅者不断询问它,您可能希望使用第一个更明确。
【讨论】:
如果您曾经在反射解决方案和非反射解决方案之间做出选择,请永远不要选择反射解决方案(涉及 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。
【讨论】:
int[] 分配给obj 时断言obj instanceof int[] 产生false,那您就错了。
Object obj = new int[7],obj instanceof Object[] 会产生 false。
java.lang.Object,所以这是有道理的。但是instanceof 仍然可以用于测试原始数组。
isArray()应该被使用。在非常不一般只有对象数组的特殊情况下,instanceof 提供了一种高性能替代方案。
如果obj 是int[] 类型,那么它将有一个数组Class,但不是Object[] 的实例。那么你想用obj 做什么。如果您要投射它,请使用instanceof。如果要使用反射,请使用.getClass().isArray()。
【讨论】:
getClass().isArray() 在 Sun Java 5 或 6 JRE 上比在 IBM 上慢得多。
在 Sun JVM 上使用 clazz.getName().charAt(0) == '[' 会更快。
【讨论】:
Java 数组反射适用于没有可用于执行“instanceof”的类实例的情况。例如,如果您正在编写某种注入框架,将值注入到类的新实例中,例如 JPA,那么您需要使用 isArray() 功能。
我在 12 月初曾在博客上写过这篇文章。 http://blog.adamsbros.org/2010/12/08/java-array-reflection/
【讨论】:
我最近遇到了将 Groovy 应用程序从 JDK 5 升级到 JDK 6 的问题。在 JDK6 中使用 isArray() 失败:
MissingMethodException:
No signature of sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl.isArray() ...
更改为 instanceof Object[] 解决了这个问题。
【讨论】:
isArray是Class的方法,不是Type,所以GenericArrayTypeImpl当然没有那个方法。而getClass 永远不能返回非Class Type,所以你(或Groovy??)一定是做错了什么,比如假设每个Type 都是Class。