Какую структуру данных определяет следующее объявление?
List<ArrayList>[] myArray;
Я думаю, он должен объявить массив, где каждый элемент является List (например, 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.
Таким образом, 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;
}
}
Похоже, что все аргументы универсального типа были удалены из вашего образца кода. Это могло произойти, потому что вы заключили его в теги PRE, а сайт интерпретировал аргументы типа как искаженные или запрещенные теги HTML (согласно Q31657). Вы должны иметь возможность редактировать его.




Джош Блох говорит:
"Prefer lists to array because arrays are covariant and generics are invariant'
Возможно, вы могли бы сделать:
List<List<ArrayList>> someListArray;
Это может привести к некоторому снижению производительности (даже не заметному, я уверен), но вы получите лучшую безопасность типов во время компиляции.
но я думаю, что вопрос должен быть больше вокруг "зачем" вам это нужно?
Мне это не «нужно». Я наткнулся на объявление во время обслуживания кода и пытался понять, что оно означает.
List<ArrayList>[] someListArray;
дает вам:
array of ( List of ArrayList )
Но из-за ограничений в дженериках Java (ошибка 6229728) вы можете только создать:
array of List
и брось это:
List<ArrayList>[] someListArray = (List<ArrayList>[]) new List[5];
Вы правильно сказали:
After running some tests, I determined the declaration means an array where each element is an ArrayList object.
Выполнение этого кода
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>();
Список - это список, способный содержать объекты ArrayList List [] - это массив таких списков
Итак, вы сказали, что массив (List of ArrayList object) ПРАВИЛЬНЫЙ.
Вы можете поделиться своими тестами. Мои собственные тесты разные
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);
}
}
}
}
}
После дополнительных тестов я думаю, что у меня есть ответ.
List <ArrayList> [] действительно определяет массив, каждый элемент которого является списком объектов ArrayList.
Компиляция кода, показанного ниже, показала, почему мой первый тест позволил мне использовать массив, где каждый элемент представляет собой список чего угодно. Использование возвращаемых типов List [] и List в методах, заполняющих массивы, не предоставило компилятору достаточно информации, чтобы запретить присваивания. Но компилятор выдавал предупреждения о двусмысленности.
С точки зрения компилятора, метод, возвращающий List [], может возвращать List <ArrayList> (который удовлетворяет объявлению), а может и нет. Точно так же метод, возвращающий List, может возвращать или не возвращать ArrayList.
Вот результат компилятора:
javac Generics2.java -Xlint: не отмечено
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;
}
}
у вас должна быть возможность отредактировать исходное сообщение, включив приведенный выше код, что было бы лучше, чем публиковать его в качестве ответа
Ответ в том, что массивы могут содержать только овеществленные типы. И обобщенные классы не материализуются. То есть "типом" среды выполнения List <ArrayList> является просто List. Обобщения стираются во время выполнения (подробнее см. В Google "стена стирания").
Итак, это:
List<ArrayList>[] myArray
действительно означает:
List[] myArray
Нет надежного способа объявить то, что вы пытаетесь объявить. Как правило, в этом случае я бы рекомендовал вам использовать список вместо массива. Некоторые люди зашли так далеко, что предложили рассматривать массивы как устаревшие типы теперь, когда у нас есть дженерики. Я не могу сказать, что готов зайти так далеко, но вы должны подумать, является ли коллекция лучшей альтернативой всякий раз, когда вы обращаетесь к массиву.
Книга Нафталина и Вадлера Обобщения и коллекции Java является отличным справочником по вопросам, которые могут возникнуть о дженериках. Или, конечно, Часто задаваемые вопросы по дженерикам - это ваш канонический онлайн-справочник.
Вероятно, каждому элементу было присвоено значение myArray [0] = new ArrayList <ArrayList> ();