I have the following method:
public static List<List<String>> createObject() {
List<List<String>> listOfListOfStrings = new LinkedList<List<String>>();
List<String> listOfStrings = new LinkedList<String>();
//do some populating on the lists here
listOfListOfStrings.add(listOfStrings);
return listOfListOfStrings;
}
Now I want to be able to use an ArrayList/Vector/Stack instead of the LinkedList (and do different combinations if needed. I read some posts on generics regarding this issue and I found out that using a factory pattern for creating those is most suited (since I don’t want reflection, and since using the generic <T extends List<K>, K extends List<String>> would not work.). So the solution I came up with is the following:
public class Tester {
public static void main(String[] args){
checkGenericsOfLists();
}
public static void checkGenericsOfLists(){
List<List<String>> listOfListOfStrings = createObject(new LinkedListFactory<List<String>>(), new LinkedListFactory<String>());
print(listOfListOfStrings);
translate(listOfListOfStrings);
print(listOfListOfStrings);
}
public static List<List<String>> createObject(ListFactorable mainListFactory, ListFactorable subListsFactory) {
List<List<String>> listOfListOfStrings = mainListFactory.create();//new LinkedList<List<String>>();
List<String> listOfStrings = subListsFactory.create();//new LinkedList<String>();
listOfStrings.add("A");
listOfListOfStrings.add(listOfStrings);
return listOfListOfStrings;
}
public static void transform(List<List<String>> listOfListOfStrings){
//do some abuse on the lists here.
}}
This solution gives warnings:
ListFactorable is a raw type. References to generic type ListFactorable should be parameterized
This is for the createObject method signature. And:
Type safety: The expression of type List needs unchecked conversion to conform to List of List of String>>
This is for the lines where the factory invokes the create() method.
But if I use this one:
public static List<List<String>> createObject(ListFactorable<List<List<String>>, List<String>> mainListFactory, ListFactorable<List<String>, String> subListsFactory) {
List<List<String>> listOfListOfStrings = mainListFactory.create();//new LinkedList<List<String>>();
List<String> list = subListsFactory.create();//new LinkedList<String>();
list.add("A");
listOfListOfStrings.add(list);
return listOfListOfStrings;
}
I get compiler error:
The method createObject(ListFactorable<List<List<String>>,List<String>>, ListFactorable<List<String>,String>) in the type Tester is not applicable for the arguments (LinkedListFactory<List<String>>, LinkedListFactory<String>)
Is there any way I can make the compiler not throw warning or error and have those lists instantiated without the createObject method being aware of the List implementation used (during compile time)?!
Cheers,
Despot
EDIT:
Excuse me for not posting the rest of the classes (very silly of me:)). Here we go:
public interface ListFactorable<T extends List<K>, K> {
T create();}
public class LinkedListFactory<K> implements ListFactorable<LinkedList<K>, K> {
public LinkedList<K> create(){
return new LinkedList<K>();
}}
EDIT2 (Eugene take on issue):
public interface EugeneListFactorable<T extends List<?>> {T create();}
public class EugeneLinkedListFactory implements EugeneListFactorable<LinkedList<?>> {
public LinkedList<?> create(){
return new LinkedList<List<?>>();
}
}
public static void checkGenericsOfLists2(){
List<List<String>> listOfListOfStrings = createObject(new EugeneLinkedListFactory(), new EugeneLinkedListFactory());
translate(listOfListOfStrings);
}
Compiler error:
- Type mismatch: cannot convert from LinkedList<?> to List<List<String>>
- Bound mismatch: The generic method createObject(EugeneListFactorable<N>, EugeneListFactorable<M>) of type
Tester is not applicable for the arguments (EugeneLinkedListFactory, EugeneLinkedListFactory). The inferred type LinkedList<?>
is not a valid substitute for the bounded parameter <N extends List<List<String>>>
Please do try to compile and run the example I posted and your solution. Its a test class which you can easily run on ur IDE. Thanks!
The followin stuff “works on my machine” without warnings or errors. What is beyond my perception is the reason for all the fuss – see the seconds codeblock.
This solution is a little bit cleaner leaving out some generics noise.