2016-08-27 4 views
1

子クラスオブジェクトを親クラスコンテナに割り当てる方法について読んでいました。下記の3つのシナリオがあります。コレクション、配列、および普通のオブジェクトの場合。 &について3つのシナリオの間で、Javaでどのように3つの処理が異なるのか、混乱しました。以下のシナリオの簡単な説明はありますか?彼らは非常に基本的なJavaのコンセプトのようですが、なぜ私を混乱させるのか分かりません。整数をオブジェクトに割り当てることはできますが、整数配列をオブジェクト配列に割り当てることはできませんか?

  1. これはコンパイル時エラーです。

    List<Object> objectList = new ArrayList<Integer>();//compile time error 
    
  2. しかし、これは

    Object object = new Integer(9); 
    object = 1.2;// no run time error 
    
  3. を許可されている。しかし、これはないですか? (ただし、技術的にコンパイラができますが、我々は、実行時エラーが発生します)

    Object objectArr[] = new Integer[1]; 
    objectArr[0] = 1.2;// run time error (Exception in thread "main" java.lang.ArrayStoreException: java.lang.Double) 
    
+0

最初の例のコンパイル時に発生するエラーは何ですか? –

+0

これが正しい! *共分散*と創世記の反反動についての研究を行う。 – GhostCat

答えて

2

Aは、大まかに言えばBのサブタイプある場合は、タイプBの変数にタイプAの何かを割り当てることができ、これは、AがBが行うすべての操作をサポートしなければならないことを意味します。

あなたの例を見て:

まず:

List<Object> objectList = new ArrayList<Integer>();//compile time error 

右、ArrayList<Integer>List<Object>ではありませんので。 Objectを追加することはできません。考えてみましょう:

List<Object> l = new ArrayList<Object>(); 
List<Integer> l2 = new ArrayList<Integer>(); 
l.add(new Object()); // ok 
l2.add(new Object()); // not ok; `List<Integer>` doesn't support this. 

ですからList<Integer>(またはArrayList<Integer>)を参照してくださいList<Object>のサブタイプではありません - それはすべて同じ操作をサポートしていないため。

次へ:この場合

Object object = new Integer(9); 
object = 1.2;// no run time error 

、値1.2ラッパータイプDouble(フルネームjava.lang.Double)に自動箱詰めです。これはObjectのサブクラスなので、割り当ては正常に動作します。変数objectに格納されるのは、プリミティブdoubleの値1.2ではなく、プリミティブ値をラップするDoubleオブジェクトへの参照です。最後に

Object objectArr[] = new Integer[1]; 
objectArr[0] = 1.2;// run time error (Exception in thread "main" java.lang.ArrayStoreException: java.lang.Double) 

これは変わり者ケースです。 JavaはIntegerの配列をObjectの配列のサブタイプと見なしますが、通常の型理論ではそうではありませんが、Object(これもIntegerではありません)をこのような配列に格納することはできません。一方、Integerの配列は、配列Objectの他のすべての操作をサポートしています。要素を取得し、サブタイプがObjectであることを確認できます。配列の長さをチェックすることができます。したがって(配列Integer)をObject[]の変数に割り当てることができます。

このタイプのサブタイプ作業を行うには、Integerアレイは暗黙のうちにObject[]と同様の「ストアObject要素」操作を実装する必要があります。しかし、Integer[]にはIntegerオブジェクトしか含まれていないため、ストア操作は失敗する必要があります。Integer以外のものを保存しようとすると、実行時に例外が発生します。あなたの例では、Integerではなく、Doubleに自動ボックス化された1.2を保存しています。

+0

非常に良い、upvoted。 –

+0

なぜ "オブジェクト= 1.2"がボクシングですが、 "objectArr [0] = 1.2"ではありませんか? –

+0

@KumarManishそれもボクシングです。しかし、 'Double'型に囲まれ、配列は' Integer'配列です。 'Double'は' Integer'ではないので、配列に格納することはできません。 – davmac

0
  1. ArrayList<Integer>List<Object>の実装ではありません。 ArrayList<Object>です。

  2. Integerを作成し、Object変数に割り当てます。 doubleObjectに割り当てることはできません。doubleはプリミティブ型であり、Objectから継承しないためです。あなたはDoubleを割り当てることができます。

  3. Integer単一要素の配列を作成し、変数Objectの配列に割り当てます。次にIntegerではないInteger要素に値を割り当てようとします。

EDIT:

davmanが説明したように、2の私の答えが間違っている、オブジェクト= 1.2;実際に有効なコードはboxingです。

さらなる説明:

  1. どれIntegerObjectですが、Objectは必ずしもIntegerではありません。 List<Object>にはObjectを追加できますが、ArrayList<Integer>にはIntegerの値しか追加できません。たとえば、ArrayList<Integer>List<Object>に割り当てた場合は、List<Object>で完全に有効なをList<Object>に追加しようとする可能性があります。しかし、操作が無効なArrayList<Integer>が保存されているため、操作は失敗します。この失敗はArrayList<Integer>List<Object>に割り当てる不一致によるものです。コンパイラーは、この矛盾からコンパイル時エラーであなたを守ります。

  2. Objectの配列を持っていても、Integerという文字が入っていることは変わりません。そして、Integerに値を割り当てようとします.Integerには無効です。あなたが書く必要がありますあなたの最初の行で

+1

(1)に対するあなたの答えは良いですが、何らかの説明が追加されました(なぜ 'ArrayList 'は 'List 'ではありません - それはどのような操作でサポートされていませんか?ボクシングを考慮に入れないので、(2)の答えは間違っています。 (3)については、もう少し詳細が良いでしょう。 – davmac

+0

@davmac、建設的な批判に感謝します。私はそれに応じて私の答えを編集します。 –

0

List<? extends Object> objectList = new ArrayList<Integer>(); 

それが動作します。 ? extends Objectは、Listに、オブジェクトを拡張する要素が含まれていることを意味します。整数。

?演算子をここに示すように使用すると、addメソッドがなくなります。つまり、あなたのArrayList内のすべての要素を追加し、後でそれを割り当てることが最初のものが必要です。

ArrayList<Integer> al = new ArrayList<>(); 
al.add(3); 
... 
List<? extends Object> objectList = al; 
関連する問題