How to reclaim the generic type you declared an arraylist to be in Java?
I was just playing around and a thought came to my mind and I decided I want to try it: Make an ArrayList that holds more ArrayLists.
For example, I created an ArrayList called intList that holds ints, then filled it with values. After that I did a stringList one and filled it too. Then I made an ArrayList that holds other ArrayLists called aList and added intList and stringList to it.
Now the problem I faced was if I was retrieving objects from aList, it would not recognize if the generic type was int or string.
Here is the code I tried:
import java.util.*;
public class Practice {
public static void main(String[] args) {
List<ArrayList> list = new ArrayList<ArrayList>();
ArrayList<int> intList = new ArrayList<int>();
intList.开发者_StackOverflow社区add(1);
intList.add(2);
intList.add(3);
ArrayList<String> stringList = new ArrayList<String>();
stringList.add("One");
stringList.add("Two");
stringList.add("Three");
list.add(intList);
list.add(stringList);
for(ArrayList lst : list) {
for(ArrayList lt : lst) {
System.out.println(lt);
}
}
}
}
Java has "generic type erasure", meaning that the type parameters to generics are "erased". Once you create an ArrayList<T>
there's no way to find out what T
was.
Only class types can be used as generic type parameters, so you can't have an ArrayList<int>
. Use an ArrayList<Integer>
instead.
In addition, the types used in your loops are wrong. Since list
is a list of lists of values, lst
is a list of values, which means that your lt
variable will be either an integer or a string, not another ArrayList
.
The deeper problem here is that you're still using raw types, so the compiler can't find that error for you. You should declare list
as something like List<List<? extends Object>>
. That way you can add both an ArrayList<Integer>
and an ArrayList<String>
to it, and extract the values as type Object
within your loop.
Since no type information is stored in generic type, you could get element from sub-list and check it's type:
for(ArrayList subList : list) {
if (subList.size() > 0) {
Class elementClass = subList.get(0).getClass();
// do something else with it
}
}
But:
- It will not work, if subList is empty
- Generally, the concept of storing several lists of different types in another list looks rather strange.
Type erasure means that at runtime, the type is erased. That's why you can cast from one generic to another:
import java.util.ArrayList;
public class Test {
public static void main(String [] args){
ArrayList<String> list = new ArrayList<String>();
ArrayList list2 = (ArrayList)list;
list2.add(new Integer(5));
System.out.println(list2.get(0).getClass());
}
}
Will output:
class java.lang.Integer
import java.util.*;
public class Practice {
public static void main(String[] args) {
List<ArrayList<?>> list = new ArrayList<ArrayList<?>>();
ArrayList<Integer> intList = new ArrayList<Integer>();
intList.add(1);
intList.add(2);
intList.add(3);
ArrayList<String> stringList = new ArrayList<String>();
stringList.add("One");
stringList.add("Two");
stringList.add("Three");
list.add(intList);
list.add(stringList);
for(ArrayList<?> lst : list) {
for(Object lt : lst) {
System.out.println(lt);
}
}
}
}
精彩评论