16

次の宣言はどのデータ構造を指定していますか?

 List<ArrayList>[] myArray;

各要素がList(aLinkedListまたは anなど) である配列を宣言し、それぞれにオブジェクトが含まれArrayListている必要があると思います。ListArrayList

私の推論:

 List<String> someList;             // A List of String objects
 List<ArrayList> someList;         // A List of ArrayList objects
 List<ArrayList>[] someListArray;  // An array of List of ArrayList objects

いくつかのテストを実行した後、各要素がLinkedListオブジェクトである配列を受け入れ、LinkedList オブジェクトに含まれるものを指定しないことがわかりました。

したがって、 にList<ArrayList>Listを含める必要があるかをList<ArrayList>[]指定しますが、 をどのようListに実装する必要があるかを指定します。

何か不足していますか?

これが私のテストです。

import java.util.ArrayList;
import java.util.List;
import java.util.LinkedList;


public class Generics1 {

    public static void main(String[] args) {

        List<ArrayList>[] someListArray;

        someListArray = getArrayWhereEachElementIsAnArrayListObject();
        // Why does this satisfy the declaration?
        //someListArray[0] => ArrayList object holding Strings

        someListArray= getArrayWhereEachElementIsAListOfArrayListObjects();
        //someListArray[0] => ArrayList object holding ArrayList objects

    }

    public static List[] getArrayWhereEachElementIsAnArrayListObject() {
        List[] arrayOfLists = new ArrayList[2];
        arrayOfLists[0] = getStringList();
        arrayOfLists[1] = getIntegerList();
        return arrayOfLists;
    }

  public static List[] getArrayWhereEachElementIsAListOfArrayListObjects() {   

        List list1 = new ArrayList();
        list1.add(getArrayList());

        List list2 = new ArrayList();
        list2.add(getArrayList());

        List[] arrayOfListsOfArrayLists = new ArrayList[2];
        arrayOfListsOfArrayLists[0] = list1;
        arrayOfListsOfArrayLists[1] = list2;
        return arrayOfListsOfArrayLists;
    }

    public static List getStringList() {
        List stringList= new ArrayList();
        stringList.add("one");
        stringList.add("two");
        return stringList;
    }


    public static List getIntegerList() {
        List intList= new ArrayList();
        intList.add(new Integer(1));
        intList.add(new Integer(2));
        return intList;
    }

    public static ArrayList getArrayList() {
        ArrayList arrayList = new ArrayList() ;
        return arrayList;
    }
}
4

6 に答える 6

17

答えは、配列は具体化された型のみを保持できるということです。また、一般化されたクラスは具体化されません。つまり、List<ArrayList> の実行時の「型」は単なる List です。ジェネリックは実行時に消去されます (詳細については、Google の「消去の壁」を参照してください)。

したがって、この:

List<ArrayList>[] myArray

本当に意味:

List[] myArray

宣言しようとしているものを宣言するタイプセーフな方法はありません。通常、この場合は配列ではなくリストを使用することをお勧めします。ジェネリックができた今、配列を非推奨の型として扱うべきだと提案する人もいます。そこまで行きたいとは言えませんが、配列に惹かれるときはいつでも、コレクションがより良い代替手段であるかどうかを検討する必要があります。

Naftalin と Wadler による著書Java Generics and Collectionsは、ジェネリックに関する疑問を解決する優れたリファレンスです。または、もちろん、Generics FAQは正規のオンライン リファレンスです。

于 2008-10-09T13:37:26.317 に答える
8

Josh Bloch 氏は次のように述べています。

「配列は共変であり、ジェネリックは不変であるため、配列よりもリストを好む」

あなたはおそらく行うことができます:

List<List<ArrayList>> someListArray;

これにより、パフォーマンスがいくらか低下する可能性がありますが (おそらくそれほど目立たないでしょう)、コンパイル時の型の安全性が向上します。

しかし、質問は「なぜ」これが必要なのかについてもっとあるべきだと思いますか?

于 2008-10-09T01:40:58.793 に答える
5
List<ArrayList>[] someListArray;

あなたに与えます:

array of ( List of ArrayList )

しかし、Java ジェネリックの制限 (バグ6229728 ) により、実際には以下のものしか作成できません。

array of List

そしてそれをキャストします:

List<ArrayList>[] someListArray = (List<ArrayList>[]) new List[5];
于 2008-10-09T01:44:42.013 に答える
0

List は ArrayList オブジェクトを保持できる List です List [] はそのような List の配列です

したがって、あなたが言ったことは、(ArrayListオブジェクトのリスト)の配列は正しいということです。

テストの内容を共有できますか。自分のテストは違う

import java.util.*;

public class TestList {
    public static void main(String ... args) {
        class MySpecialLinkedList extends LinkedList<ArrayList<Integer>> {
            MySpecialLinkedList() {

            }

            public void foo() {

            }


            public Object clone()
            {
                return super.clone();
            }
        }

        List<ArrayList<Integer>> [] someListArray = new MySpecialLinkedList[10];
        for (int i = 0; i < 10; ++i) {
            someListArray[i] = new LinkedList<ArrayList<Integer>>();
            for (int j = 0; j < 20; ++j) {
                someListArray[i].add(new ArrayList<Integer>());
                for (int k = 0; k < 30; ++k) {
                    someListArray[i].get(j).add(j);
                }
            }
        }
    }
}
于 2008-10-09T02:47:19.407 に答える
0

あなたの言うことは正しいです:

いくつかのテストを実行した後、宣言は、各要素が ArrayList オブジェクトである配列を意味すると判断しました。

このコードの実行

List<ArrayList>[] myArray  = new ArrayList[2];

myArray[0] = new ArrayList<String>();
myArray[0].add("test 1");

myArray[1] = new ArrayList<String>();
myArray[1].add("test 2");

print myArray;

次の結果が生成されます。

{["test 1"], ["test 2"]}

代わりにこれを行わない理由はないように思えます:

List<ArrayList> myArray  = new ArrayList<ArrayList>();
于 2008-10-09T01:49:29.600 に答える
0

追加のテストをいくつか実行した後、答えが得られたと思います。

List<ArrayList>[] は実際に、各要素が ArrayList オブジェクトのリストである配列を指定します。

以下に示すようにコードをコンパイルすると、最初のテストで、各要素が何かのリストである配列を使用できる理由が明らかになりました。配列に値を設定するメソッドで List[] および List の戻り値の型を使用しても、割り当てを禁止するのに十分な情報がコンパイラに提供されませんでした。しかし、コンパイラはあいまいさについて警告を出しました。

コンパイラの観点からは、List[] を返すメソッドは、(宣言を満たす) List<ArrayList> を返す場合とそうでない場合があります。同様に、List を返すメソッドは、ArrayList を返す場合と返さない場合があります。

コンパイラの出力は次のとおりです。

javac Generics2.java -Xlint:未チェック

Generics2.java:12: 警告: [未チェック] 未チェックの変換
見つかった: java.util.List[]
必須: java.util.List<java.util.ArrayList>[]
        someListArray = getArrayWhereEachElementIsALinkedListObject();
                                                                   ^
Generics2.java:16: 警告: [未チェック] 未チェックの変換
見つかった: java.util.List[]
必須: java.util.List<java.util.ArrayList>[]
        someListArray= getArrayWhereEachElementIsAListOfLinkedListObjects();

これが私のテストです。

import java.util.ArrayList;
java.util.List をインポートします。
java.util.LinkedList をインポートします。


パブリック クラス Generics2 {

    public static void main(String[] args) {

        List<ArrayList>[] someListArray;

        someListArray = getArrayWhereEachElementIsALinkedListObject();
        // なぜこれが宣言を満たすのですか?
        //someListArray[0] => 文字列を保持する LinkedList オブジェクト

        someListArray= getArrayWhereEachElementIsAListOfLinkedListObjects();
        //someListArray[0] => LinkedList オブジェクトを保持する LinkedList オブジェクト

    }

    public static List[] getArrayWhereEachElementIsALinkedListObject() {
        List[] arrayOfLists = new LinkedList[2];
        arrayOfLists[0] = getStringLinkedListAsList();
        arrayOfLists[1] = getIntegerLinkedListAsList();
        arrayOfLists を返します。
    }

  public static List[] getArrayWhereEachElementIsAListOfLinkedListObjects() {

        リスト list1 = new LinkedList();
        list1.add(新しい LinkedList());

        リスト list2 = new LinkedList();
        list2.add(新しい LinkedList());

        List[] arrayOfListsOfLinkedLists = new LinkedList[2];
        arrayOfListsOfLinkedLists[0] = list1;
        arrayOfListsOfLinkedLists[1] = list2;
        arrayOfListsOfLinkedLists を返します。
    }

    public static List getStringLinkedListAsList() {
        リスト stringList= new LinkedList();
        stringList.add("1");
        stringList.add("2");
        stringList を返します。
    }


    public static List getIntegerLinkedListAsList() {
        List intList= new LinkedList();
        intList.add(新しい整数(1));
        intList.add(新しい整数(2));
        intList を返します。
    }

}
于 2008-10-09T03:16:23.297 に答える