【问题标题】:How to see if an object is an array without using reflection?如何在不使用反射的情况下查看对象是否为数组?
【发布时间】:2011-02-13 02:37:06
【问题描述】:

如果一个对象是一个不使用反射的数组,我如何在 Java 中查看? 以及如何在不使用反射的情况下遍历所有项目?

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

我希望在不使用引用的情况下实现以下方法:

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

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

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

【问题讨论】:

    标签: java arrays gwt instanceof


    【解决方案1】:

    您可以使用Class.isArray()

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

    这适用于对象和原始类型数组。

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

    【讨论】:

    • 值得补充的是,您可以使用obj.getClass().getComponentType()找出数组类型。
    【解决方案2】:

    您可以使用instanceof

    JLS 15.20.2 Type Comparison Operator instanceof

     RelationalExpression:
        RelationalExpression instanceof ReferenceType
    

    在运行时,如果 RelationalExpression 的值不是 null 并且引用可以转换为 ReferenceTypeinstanceof 运算符的结果是 true /em> 没有提出ClassCastException。否则结果为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 is very repetitive),但在 Java 中使用数组就是这样。

    另见

    【讨论】:

    • 谢谢,没想到这么简单。认为 instanceof 不能直接与 T[] 一起使用 :(
    • 顺便说一句:我还注意到另一种很好的方法来发现某个东西是否是数组 Class.isArray()(在 Arrays.deepToString() 中使用)。
    • @edbras:是的,这就是 Steve Kuo 在下面所说的。我的解决方案使用纯语言结构而不是 API 调用。
    • 它工作正常,我只是不使用 instanceof 而是使用 getClass 作为比较。类似于: if (array.getClass == int[].class) { Arrays.toString((int[]) array); } 谢谢大家..
    • @edbras:java.util.Arrays 就是这样做的,是的。我看到你一直在阅读我链接的代码。
    【解决方案3】:

    可以使用以下代码分别访问数组的每个元素:

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

    请注意,不必知道它是哪种底层数组,因为这适用于任何数组。

    【讨论】:

    • isArray() 在此之前 4 年发布的答案中已经充分涵盖。
    • 这个答案很棒,因为它向我们展示了如何在不知道其内容类型的情况下获取数组的大小并检索元素。我敢肯定大多数人以前从未编写过这样的代码。
    • @MaartenBodewes - 我会使用 this link 来决定 GWT 的“不使用反射”意味着什么。
    【解决方案4】:

    原始类型的数组之间或原始类型的数组和引用类型的数组之间没有子类型关系。见JLS 4.10.3

    因此,以下是不正确的测试,以查看 obj 是否是一个数组任何类型的

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

    具体来说,如果obj 是一维基元数组,则它不起作用。 (它确实适用于具有更高维度的原始数组,因为所有数组类型都是Object 的子类型。但在这种情况下它没有实际意义。)

    我使用 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[];
      }
      
    • 您也可以尝试如下弄乱对象类的名称,但对obj.getClass() 的调用接近于反射。

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

    1 - 更准确地说,Class.isArray 方法在 this page 中被 GWT 列为支持。

    【讨论】:

      【解决方案5】:

      您可以创建一个实用程序类来检查该类是否代表任何 CollectionMapArray

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

      【讨论】:

        【解决方案6】:

        只需obj instanceof Object[](在 JShell 上测试)。

        【讨论】:

          猜你喜欢
          • 2016-09-21
          • 2016-10-30
          • 1970-01-01
          • 1970-01-01
          • 2010-12-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多