我有以下方法:
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;
}
现在我希望能够使用 ArrayList/Vector/Stack 而不是 LinkedList(如果需要,可以进行不同的组合。我阅读了一些有关此问题的泛型文章,并且我发现使用工厂模式来创建这些是最合适的(因为我不需要反射,并且因为使用通用,K扩展List>
不起作用。)。所以我想出的解决方案如下:
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.
}}
此解决方案给出警告:
ListFactorable 是一种原始类型。对泛型类型 ListFactorable 的引用应该参数化
这是针对 createObject 方法签名的。和:
类型安全:List类型的表达式需要未经检查的转换才能符合List of List of String>>
这是针对工厂调用 create() 方法的行。
但是如果我使用这个:
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;
}
我得到编译器错误:
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>)
有什么方法可以让编译器不抛出警告或错误,并在 createObject 方法不知道所使用的 List 实现的情况下实例化这些列表(在编译时) ?!
干杯,
暴君
编辑:
请原谅我没有发布其余的课程(我很愚蠢:))。我们开始吧:
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 issues):
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);
}
编译器错误:
- 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>>>
请尝试编译并运行我发布的示例和您的解决方案。它是一个测试类,您可以轻松地在 IDE 上运行。谢谢!
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!
发布评论
评论(3)
以下内容“在我的机器上运行”,没有警告或错误。超出我的认知的是所有大惊小怪的原因 - 请参阅秒代码块。
这个解决方案更干净一些,省略了一些泛型噪音。
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.
这并不能完全解决您的问题,但有助于更快地找到解决方案。
当你有任何看起来像这样的东西时 X>考虑重构为一个类。我将提供一个例子。你看起来像是在使用转换。现在我不知道你的目标是什么,因为你还没有说明它们,但一种常见的方法是:
更好的方法是这样的:
现在如果没有看到更多的实现,很难看看你到底做错了什么。但无论你在做什么,考虑删除任何嵌套的泛型,而不是尝试将它们隔离到类中。这将使您能够以面向对象的方式巩固行为,并更好地组织您的逻辑,以便您可以专注于它应该做什么,而不是泛型的语义。
This won't exactly solve your problem, but it will lend itself to finding the solution faster.
When you have anything that looks like this X> consider refactoring into a class. I'll provide an example. You look like you're using transations. Now I don't know exactly what your goals are, because you haven't stated them, but one common way to do it would be:
What would be better would be something like this:
Now without seeing more of your implementation it's hard to see exactly what you're doing wrong. But WHATEVER you're doing, look at removing any nested generics and instead trying to isolate them into classes. This will allow you to consolidate behavior in an object oriented manner, and better organize your logic so you can focus on what it's supposed to do instead of the semantics of generics.
您需要正确的 ListFactorable 类:
然后 createObject 方法可能如下所示:
You need to properly ListFactorable class:
Then createObject method could look something like this: