【问题标题】:Object type in Java and referencing arraysJava中的对象类型和引用数组
【发布时间】:2012-09-27 17:05:56
【问题描述】:
public class RefMix {
  public static void main(String[] args) {
    Object[] a = {null, "foo"};
    Object[] b = {"bar", b};
    a[0] = b;

    System.out.println(a[0][0]);
  }
}

我的理解是数组是 Java 中的对象,因此是 Object 类型的子类。我的进一步理解是 2-dim 数组是作为数组引用的数组实现的。因此我不明白为什么我的 a[0][0] 在上面的代码中没有产生bar。相反,它不会编译:

RefMix.java:7: array required, but java.lang.Object found

【问题讨论】:

    标签: java arrays object


    【解决方案1】:

    由于我最近做了很多 C++ 编码,我发现 Java 在类型检查方面比 C++ 严格得多。 Java 将除原始类型之外的所有内容都视为 Object,但 Java 在区分 Array 和非 Array 类型方面更进了一步。在分配期间,例如“a [0] = b;” , Java 首先检查它是否是一个 Array 类型,然后通过常规的多态类型检查过程。如果你想让你的代码工作,你应该这样做......

    Object[][] a = {{null}, {"foo"}};
    Object[] b = {"bar", new java.util.Date()};
    a[0] = b;
    

    您可以通过查看作为参数传递给 Class.forName() 的 Java 类签名来了解 java 如何特别注意数组类型。比如数据类型..

    com.foo.Bar[][] barsIn2D;
    

    可以加载下面的签名...

    // [ => Array
    // [[ => Array of Array type
    // L<object>; => Object, not Array
    Class.forName("[[Lcom/foo/Bar;");
    

    如您所见,签名以“[”或“L”开头。 这告诉我们它是否是一个数组优先于“Lcom/foo/Bar;”。

    【讨论】:

      【解决方案2】:

      你所做的一切都等价于这个

      Object a = {"bar", "foo"};
      System.out.println(a[0]);
      

      也不编译。

      【讨论】:

        【解决方案3】:

        你是对的,数组在 Java 中总是 Objects,但 Objects 并不总是数组,因此会出现编译错误,因为 aObject[](一维)。您无法访问

        a[0][0];
        

        因为a 不是二维数组(至少它没有这样声明)。但是在这种情况下,您可以肯定,a[0]Objects 的数组。因此,您可以这样做:

        Object[] c = (Object[]) a[0];
        System.out.println(c[0]);
        // or directly:
        System.out.println(((Object[])a[0])[0]);
        

        a[0](即Object)的返回类型转换为Object[],然后您可以访问数组的“第二层”。

        【讨论】:

          【解决方案4】:

          我的理解是数组是 Java 中的对象,因此是 Object 类型的子类。我的进一步理解是 2-dim 数组是作为数组引用的数组实现的。

          这都是正确的,并解释了为什么你可以做作业

          a[0] = b;
          

          没有来自编译器的任何抱怨。

          因此我不明白为什么我的 a[0][0] 在上面的代码中没有产生 bar。

          好,我们来看看这个表达式中的类型:

          • a 是一个 Object[] -- 这是一个 Objects 的数组
          • a[0]Object
          • a[0][0] -- 现在您正尝试在 Object 上使用数组下标。编译器不知道Object 实际上是一个数组,所以它会报错。

          【讨论】:

            【解决方案5】:

            做:

            System.out.println(((Object[])a[0])[0]);
            

            这将在运行时将对象“转换”为对象数组。

            【讨论】:

              【解决方案6】:

              由于 Java 中的数组是一个对象,因此第一个和第二个赋值会将您的数组存储为您的 Object 数组的第一个元素..

              Object[] a = {null, "foo"};
              Object[] b = {"bar", b};
              

              现在,您已将 a 对象数组的第一个元素更改为包含值 b 而不是数组。但因为它是一个对象数组。从中产生的一切都将成为对象..

              因为 a[0] 是一个对象.. 所以,你显然不能访​​问这样的东西:-

              System.out.println(a[0][0]);
              

              您可以尝试将对象 a[0] 类型转换为对象数组..:-

              System.out.println(((Object[])a[0])[0]);
              

              【讨论】:

                【解决方案7】:

                对象实例的运行时类型不同于静态推断的类型。编译器将尝试估计每个变量在程序中可能是什么类型,以便及早捕获某些类型的错误。在这种情况下,a[0] 将始终是一个数组,但编译器不知道这一点。由于您要从对象数组中获取对象,因此编译器所知道的只是 a[0] 是一个对象。因此会引发错误。

                如果您知道某些东西始终是某种类型但编译器无法识别,您可以通过插入显式强制转换来解决此问题。

                System.out.println(((Object[])a[0])[0]);
                

                【讨论】:

                • 这种丑陋的演员阵容让我放弃了使用这样的数组;我将只使用“普通”类的对象引用。不过谢谢!
                • @Fixee,Java 中的数组相当丑陋,但您通常可以通过减少存储异构数据的次数来避免强制转换。您通常不需要将字符串和 object[] 存储在同一个数组中。
                • @Antimony 我实际上找不到一个你会需要这样的东西的用例...... ;)
                • @brimborium,这有点过分了,这是一种情况:如果你有一个 ORM 并缓存数据或只需要一个中间层,它可能有 object[] w/所有字段目标类,然后正确分配给实例。总的来说,它在中间件中很常见。这是通过反射调用任何东西的另一种情况,将 Object[] 作为参数,后者可以包含任何必要的内容。
                猜你喜欢
                • 1970-01-01
                • 2011-06-05
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-12-12
                • 1970-01-01
                • 2018-07-10
                相关资源
                最近更新 更多