【问题标题】:Java array reflection: isArray vs. instanceofJava 数组反射:isArray 与 instanceof
【发布时间】:2010-09-18 04:56:41
【问题描述】:

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

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

if(obj instanceof Object[]) {}

?

【问题讨论】:

    标签: java arrays reflection


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      我可以发现两者之间的行为没有区别(除了明显的 null 情况)。至于更喜欢哪个版本,我会选择第二个。这是在 Java 中执行此操作的标准方式。

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

      【讨论】:

        【解决方案3】:

        如果您曾经在反射解决方案和非反射解决方案之间做出选择,请永远不要选择反射解决方案(涉及 Class 对象)。不是说“错”什么的,而是涉及到反射的东西一般都不太明显,不太清楚。

        【讨论】:

        • 呃,好吧,“instanceof”也是一种反思(或者,至少,自省),但我明白你的意思。
        • 另外,一般比较慢。
        【解决方案4】:

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

        【讨论】:

        • 是的,但是会有多大的不同呢?对我来说,这听起来像是一种微优化。
        • @Dims 如果您在将int[] 分配给obj 时断言obj instanceof int[] 产生false,那您就错了。
        • 对不起,我的意思是如果Object obj = new int[7]obj instanceof Object[] 会产生 false
        • 对,在 Java 中,原始数据类型不是对象,也不扩展 java.lang.Object,所以这是有道理的。但是instanceof 仍然可以用于测试原始数组。
        • -1:一般来说,由于原始数组数组调用isArray()应该被使用。在非常不一般只有对象数组的特殊情况下,instanceof 提供了一种高性能替代方案。
        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

          getClass().isArray() 在 Sun Java 5 或 6 JRE 上比在 IBM 上慢得多。

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

          【讨论】:

          • 您有任何可以链接到的统计数据、案例研究或其他证据吗?
          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:

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

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

            更改为 instanceof Object[] 解决了这个问题。

            【讨论】:

            • 这毫无意义。 isArrayClass的方法,不是Type,所以GenericArrayTypeImpl当然没有那个方法。而getClass 永远不能返回非Class Type,所以你(或Groovy??)一定是做错了什么,比如假设每个Type 都是Class
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-05-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多