Подтвердить что ты не робот

Синтаксис Java Generics для массивов

В какой структуре данных указано следующее объявление?

 List<ArrayList>[] myArray;

Я думаю, он должен объявить массив, где каждый элемент является List (например, a LinkedList или ArrayList) и требует, чтобы каждый List содержал объекты ArrayList.

Мое рассуждение:

 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 содержат.

So 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;
    }
}
4b9b3361

Ответ 1

Ответ заключается в том, что массивы могут содержать только типы reified. И генерализованные классы не воссоединяются. То есть "тип" среды выполнения List <ArrayList> это просто список. Дженерики стираются во время выполнения (google "стена стирания" ).

Итак, это:

List<ArrayList>[] myArray

действительно означает:

List[] myArray

Нет безопасного типа для объявления того, что вы пытаетесь объявить. В общем случае я бы рекомендовал использовать List вместо массива в этом случае. Некоторые люди зашли так далеко, что предположили, что массивы должны рассматриваться как устаревшие типы, когда у нас есть дженерики. Я не могу сказать, что я готов пойти так далеко, но вы должны подумать о том, является ли коллекция лучшей альтернативой всякий раз, когда вы привязаны к массиву.

Книга Java Generics and Collections от Naftalin и Wadler - отличная ссылка на вопросы, которые могут возникнуть в отношении дженериков. Или, конечно, Общие вопросы - это ваша каноническая онлайн-ссылка.

Ответ 2

Г-н Джош Блох говорит:

"Предпочтительные списки для массива, потому что массивы являются ковариантными, а дженерики - инвариант

Вы могли бы сделать:

List<List<ArrayList>> someListArray;

Это может привести к некоторому результативному результату (даже не отметить, что я ставлю), но при компиляции вы получите лучшую безопасность типов.

но я думаю, что вопрос должен быть больше вокруг "зачем" вам это нужно?

Ответ 3

List<ArrayList>[] someListArray;

дает вам:

array of ( List of ArrayList )

Но из-за ограничений в дженериках Java (ошибка 6229728) вы можете создать только:

array of List

и произведите его:

List<ArrayList>[] someListArray = (List<ArrayList>[]) new List[5];

Ответ 4

Вы правильно говорите:

После запуска некоторых тестов, я определил объявление - это массив, в котором каждый элемент является объектом 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>();

Ответ 5

Список - это список, способный содержать объекты ArrayList Список [] - это массив таких списков

Итак, вы сказали, что Array of (Список объектов 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);
                }
            }
        }
    }
}

Ответ 6

После выполнения некоторых дополнительных тестов, я думаю, что у меня есть мой ответ.

List <ArrayList> [] действительно указывает массив, в котором каждый элемент является объектом List of ArrayList.

Компиляция кода, как показано ниже, показала, почему мой первый тест позволил мне использовать массив, в котором каждый элемент является списком чего-либо. Использование возвращаемых типов List [] и List в методах, которые заполняют массивы, не предоставило компилятору достаточную информацию для запрета назначений. Но компилятор действительно выдавал предупреждения о двусмысленности.

С точки зрения компилятора метод, возвращающий List [], может возвращать List <ArrayList> (который удовлетворяет декларации), а может и нет. Точно так же метод, возвращающий список, может возвращать ArrayList или не возвращать его.

Здесь был выход компилятора:

javac Generics2.java -Xlint: unchecked

Generics2.java:12: warning: [unchecked] unchecked conversion
found   : java.util.List[]
required: java.util.List<java.util.ArrayList>[]
        someListArray = getArrayWhereEachElementIsALinkedListObject();
                                                                   ^
Generics2.java:16: warning: [unchecked] unchecked conversion
found   : java.util.List[]
required: java.util.List<java.util.ArrayList>[]
        someListArray= getArrayWhereEachElementIsAListOfLinkedListObjects();

Вот мои тесты.

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


public class Generics2 {

    public static void main(String[] args) {

        List<ArrayList>[] someListArray;

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

        someListArray= getArrayWhereEachElementIsAListOfLinkedListObjects();
        //someListArray[0] => LinkedList object holding LinkedList objects

    }

    public static List[] getArrayWhereEachElementIsALinkedListObject() {
        List[] arrayOfLists = new LinkedList[2];
        arrayOfLists[0] = getStringLinkedListAsList();
        arrayOfLists[1] = getIntegerLinkedListAsList();
        return arrayOfLists;
    }

  public static List[] getArrayWhereEachElementIsAListOfLinkedListObjects() {

        List list1 = new LinkedList();
        list1.add(new LinkedList());

        List list2 = new LinkedList();
        list2.add(new LinkedList());

        List[] arrayOfListsOfLinkedLists = new LinkedList[2];
        arrayOfListsOfLinkedLists[0] = list1;
        arrayOfListsOfLinkedLists[1] = list2;
        return arrayOfListsOfLinkedLists;
    }

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


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

}