15
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次元配列が配列への参照の配列として実装されているということです。barしたがって、上記のコードでa[0][0] が生成されない理由がわかりません。代わりに、コンパイルしません:

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

7 に答える 7

13

私の理解では、配列はJavaのオブジェクトであるため、Object型のサブクラスです。私のさらなる理解は、2次元配列が配列への参照の配列として実装されているということです。

これはすべて正しく、割り当てを実行できる理由を説明しています

a[0] = b;

コンパイラからの苦情なし。

したがって、私のa[0][0]が上記のコードでバーを生成しない理由がわかりません。

さて、この式の型を見てみましょう:

  • aは-のObject[]配列ですObject
  • a[0]Object
  • a[0][0]-ここで、で配列の添え字を使用しようとしていますObject。コンパイラは、が実際に配列であることを認識していないObjectため、文句を言います。
于 2012-10-07T00:03:57.917 に答える
10

オブジェクトインスタンスの実行時型は、静的に推測された型とは異なります。コンパイラーは、特定のタイプのエラーを早期にキャッチするために、各変数がプログラム内にある可能性のあるタイプを推定しようとします。この場合、a[0]は常に配列になりますが、コンパイラはこれを認識しません。オブジェクト配列からオブジェクトを取得しているので、コンパイラが知っているのはそれa[0]がオブジェクトであるということだけです。したがって、エラーが発生します。

何かが常に特定のタイプであることがわかっているが、コンパイラーがそれを理解できない場合は、明示的なキャストを挿入することでこれを回避できます。

System.out.println(((Object[])a[0])[0]);
于 2012-10-07T00:00:09.503 に答える
7

そうです、配列は常にObjectsJavaにありますが、常に配列であるとは限りません。したがって、(1次元)Objectsであるため、コンパイルエラーが発生します。アクセスできませんaObject[]

a[0][0];

は 2 次元配列ではないためaです (少なくともそのように宣言されていません)。ただし、この場合、それは確かにa[0]の配列ですObjects。したがって、これを行うことができます:

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

これにより、戻り値の型(つまり) が a にキャストされ、配列の「2 番目のレイヤー」にアクセスできるようになります。a[0]ObjectObject[]

于 2012-10-07T00:08:14.833 に答える
4

Javaの配列はオブジェクトであるため、1番目と2番目の割り当ては、配列をObject配列の1番目の要素として格納します。

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]);
于 2012-10-07T00:01:06.780 に答える
4

行う:

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

これにより、実行時にオブジェクトがオブジェクト配列に「キャスト」されます。

于 2012-10-07T00:02:06.083 に答える
2

最近多くのC++コーディングを行っているので、JavaはC++よりも型チェックがはるかに厳密であることがわかりました。Javaはプリミティブ型以外のすべてをオブジェクトと見なしますが、Javaは配列型と非配列型を区別する上でさらに一歩進んでいます。「a[0]=b;」のような割り当て中 、Javaは、最初に配列型であるかどうかを確認し、その後、通常のポリモーフィック型のチェック手順を実行します。コードを機能させたい場合は、次のことを行う必要があります...

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;」よりも優先されるかどうかがわかります。

于 2012-10-07T09:00:07.877 に答える
1

あなたがしていることはすべてこれと同等です

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

どちらもコンパイルされません。

于 2012-10-07T00:22:04.407 に答える