在我的方法readList中,我想构建一个用户定义类型的java.util.List(具体列表类型是一个参数).我不想将readList限制为ArrayList或LinkedList;用户可能提供自己的java.util.List实现.如果可能,该方法也可以缓存列表,因此该方法需要返回列表.我试了几件事.以下哪一个是您视图中的“最佳”API,还是另一个,甚至更好?
以下编译,但我收到编译器警告:“类型安全:ArrayList类型的表达式需要未经检查的转换以符合ArrayList”,所以它不是一个很好的解决方案:
void classParameter() {
ArrayList a = readList(ArrayList.class);
LinkedList b = readList(LinkedList.class);
}
> T readList(Class clazz) {
try {
return clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
以下编译,但我仍然得到编译器警告,加上它实际上没有按预期工作:
void classTypeParameters() {
ArrayList a = readList(ArrayList.class, String.class);
LinkedList b = readList(LinkedList.class, Integer.class);
}
, X> T readList(Class clazz, Class type) {
try {
return clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
以下作品,是我个人的最爱.它检查列表类型.有点危险的是有人可能会忘记分配结果.这可以通过将readList重命名为readListWithTemplate左右来解决,更明显的是使用返回值.它类似于List.toArray(T [] a):
void template() {
ArrayList a = readList(new ArrayList());
LinkedList b = readList(new LinkedList());
// wrong usage:
List c = new LinkedList();
readList(c);
}
@SuppressWarnings("unchecked")
> T readList(T template) {
try {
return (T) template.getClass().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
“超级令牌类型”也可以,但可能有点难以理解
对于不熟悉此模式的开发人员以及Eclipse
我收到警告“应该记录空块”,我想避免:
void superTypeToken() {
ArrayList a = readList(new ListType>() {});
LinkedList b = readList(new ListType>() {});
}
abstract static class ListType> {
// super type token class
}
@SuppressWarnings("unchecked")
> T readList(ListType t) {
try {
Type type = t.getClass().getGenericSuperclass();
if (!(type instanceof ParameterizedType)) {
throw new IllegalArgumentException("Missing type parameters");
}
ParameterizedType pt = (ParameterizedType) type;
type = pt.getActualTypeArguments()[0];
pt = (ParameterizedType) type;
Class> listClass = (Class>) pt.getRawType();
return (T) listClass.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
你更倾向哪个?或者有更好的解决方案吗?
解决方法:
我可能会委托另一个构建器类.一个只知道如何创建新列表的小类.它提供了更好的运行时安全性,因为它不依赖于给定类具有默认构造函数的假设.列表可能不那么有用,因为我们应该始终能够创建一个空列表,但对于其他类型的类更重要.
例如.
public interface EmptyListBuilder {
public List newList();
public static final EmptyListBuilder ARRAY_LIST_BUILDER =
new EmptyListBuilder() {
public List newList() {
return new ArrayList();
}
};
}
如静态字段所示,您还可以为几个标准类提供默认实现.
使用这样的类:
List readList(EmptyListBuilder builder) {
List list = builder.newList();
// read in elements
return list;
}
你无法确切地知道你有什么类型的列表,但是这是一个问题,那么听起来你正试图做一些有点奇怪的事情.
标签:java,generics
来源: https://codeday.me/bug/20190625/1286893.html