Java Generics Syntax for arrays
What data structure does the following declaration specify?
List<ArrayList>[] myArray;
I think it should declare an array where each element is a List
(e.g., a LinkedList
or an ArrayList
) and require that each List
contain ArrayList
objects.
My reasoning:
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
After running some tests, I determined that it accepts an array where each element is an LinkedList
object and does not specify what the LinkedList objects contain.
So List<ArrayList>
specifies what the List
must contain, but List<ArrayList>[]
specifies how the List
must be implemented.
Am I missing something?
Here are my tests.
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;
}
}
Asked by: Sienna368 | Posted: 21-01-2022
Answer 1
The answer is that arrays can only hold reified types. And generified classes are not reified. That is, the runtime "type" of the List<ArrayList> is just List. Generics are erased at runtime (google "wall of erasure" for more).
So this:
List<ArrayList>[] myArray
really means:
List[] myArray
There is no type-safe way to declare what you're trying to declare. Generally, I'd recommend you use a List instead of an array in this case. Some people have gone so far as to suggest that arrays should be treated as deprecated types now that we have generics. I can't say I'm willing to go that far but you should consider whether a collection is a better alternative whenever you're drawn to an array.
The book Java Generics and Collections by Naftalin and Wadler is an excellent reference for questions you might have about generics. Or, of course, the Generics FAQ is your canonical online reference.
Answered by: Kevin493 | Posted: 22-02-2022Answer 2
Mr Josh Bloch says:
"Prefer lists to array because arrays are covariant and generics are invariant'
You could perhaps do:
List<List<ArrayList>> someListArray;
This may give some performance hit (not even noticable i bet) but you will get better type safety at compile time.
but I think the question should be more around "why" you need this?
Answered by: Lydia600 | Posted: 22-02-2022Answer 3
List<ArrayList>[] someListArray;
gives you an:
array of ( List of ArrayList )
But due to limitations in Java generics (bug 6229728) you can only actually create:
array of List
and cast it:
List<ArrayList>[] someListArray = (List<ArrayList>[]) new List[5];
Answered by: Dominik783 | Posted: 22-02-2022
Answer 4
List is a List capable of holding ArrayList objects List [] is an array of such Lists
So, what you said is that An Array of (List of ArrayList object) is CORRECT.
Can you share what your tests were. My own tests are different
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);
}
}
}
}
}
Answered by: Lydia747 | Posted: 22-02-2022
Answer 5
You are correct in saying:
After running some tests, I determined the declaration means an array where each element is an ArrayList object.
Executing this code
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;
Produces this result:
{["test 1"], ["test 2"]}
It seems to me there is no reason not to do this instead:
List<ArrayList> myArray = new ArrayList<ArrayList>();
Answered by: Eric287 | Posted: 22-02-2022
Answer 6
After running some additional tests, I think I have my answer.
List<ArrayList>[] does indeed specify an array where each element is a List of ArrayList objects.
Compiling the code as shown below revealed why my first test allowed me to use an array where each element is a List of anything. Using return types of List[] and List in the methods that populate the arrays did not provide the compiler enough information to prohibit the assignments. But the compiler did issue warnings about the ambiguity.
From the compiler's point of view, a method returning a List[] might be returning a List<ArrayList> (which satisfies the declaration) or it might not. Similarly, a method returning a List might or might not return an ArrayList.
Here was the compiler output:
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();
Here are my tests.
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; } }Answered by: Miranda585 | Posted: 22-02-2022
Similar questions
Java generics syntax
I am trying to understand what the following means?
public class Bar<T extends Bar<T>> extends Foo<T> {
//Some code
}
What is the advantage of doing something like this (e.g. use-case?).
Java Generics syntax setter
I have this two classes and i need to initialize in the child class filds from parent class.
public class A {
protected LazyFacade<E> list;
protected LazyDataModel<E> model;
protected MyObject myObject;
protected LazyDataModel<E> buildModel() {
lazyModel = new LazyDataModel<E>() {
public List<E> load(int first, int pageSize, String ...
java - Generics in legacy code
We've got a fairly large amount of code that just made the jump to Java 5. We've been using generics in those components targeted at being released in the Java 5 version, but the remaining code is, of course, full of raw types. I've set the compiler to generate an error for raw types and started manually clearing them, but at the present rate it'll take a very long time to go through with it (there are about 2...
generics - How do I write a Java function that returns a typed instance of 'this' and works when extended?
This is a bit of a lazyweb question but you get the rep so :-)
I have a Java class that returns instances of itself to allow chaining
(e.g. ClassObject.doStuff().doStuff())
For instance:
public class Chainer
{
public Chainer doStuff()
{
/* Do stuff ... */
return this;
}
}
I would like to extend this class. Is there a way, perhaps using generics, t...
generics - Java Class Type
I have a block of code that works and I wanted to ask what exactly is happening here?
Class<?> normalFormClass = null;
---added---
The wildcard "<?>" is the part that is confusing for me. Why would this be used rather than not using it (generics)?
How to use generics in a world of mixed Java versions?
I like generics a lot and use them whereever I can. Every now and then I need to use one of my classes in another project which has to run on an old JVM (before 5.0), needs to run on JavaME (where generics are not allowed neither) or in Microsoft J# (which has VERY poor Support for generics).
At the moment, I remove all generics manually, which means inserting many casts as well.
Since generics are said to ...
C# vs Java generics
This question already has answers here:
In Java, when should I use "Object o" instead of generics?
For example, I could write either of these:
class example <T>
{
...
public void insert (T data)
{
...
}
}
or
class example
{
...
public void insert (Object o)
{
...
}
}
Is there a signficant difference between the 2 in terms of performance? With generics I could restrict the type of the parameter and ...
generics - Why can't the Java compiler figure this out?
Why is the compiler unable to infer the correct type for the result from Collections.emptySet() in the following example?
import java.util.*;
import java.io.*;
public class Test {
public interface Option<A> {
public <B> B option(B b, F<A,B> f);
}
public interface F<A,B> {
public B f(A a);
}
public Collection<String> getColl() {
Opt...
java - How do you access Class object for generics?
How can I access Class object for Generics?
Currently, I am doing it this way:
List<String> list= new ArrayList<String>();
list.getClass();
Is this OK? Or, what should be the way?
How do I fix this Java generics wildcard error?
In this question, TofuBeer was having problems creating a genericized IterableEnumeration.
The answer came from jcrossley3 pointing to this link http://www.javaspecialists.eu/archive/Issue107.html which pretty much solved the p...
Java: Generics won't work for my method, what else can I do?
In the code below, I would like the second method to be generic, too, but since I create the Calendar object inside the method, because of type erasure, I don't see how. One possibility would be to pass in the Calendar object, but that would defeat the main purpose for having this method at all (not h...
Still can't find your answer? Check out these amazing Java communities for help...
Java Reddit Community | Java Help Reddit Community | Dev.to Java Community | Java Discord | Java Programmers (Facebook) | Java developers (Facebook)