在我的方法readList中,我想构建一个用户定义类型的java.util.List(具体的列表类型是一个参数)。但是,我不想将readList限制为ArrayListLinkedList;用户可以提供自己的java.util.List实现。如果可能,该方法还可能缓存列表,因此该方法需要返回列表。我尝试了几件事。您认为以下哪一项是“最佳” API,或者还有另一种甚至更好的API?

可以进行以下编译,但是我得到编译器警告:“类型安全:ArrayList类型的表达式需要未经检查的转换才能符合ArrayList”,因此它并不是一个很好的解决方案:

void classParameter() {
    ArrayList<String> a = readList(ArrayList.class);
    LinkedList<String> b = readList(LinkedList.class);
}

<X, T extends List<X>> T readList(Class<T> clazz) {
    try {
        return clazz.newInstance();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

以下编译,但是我仍然收到编译器警告,加上它实际上并没有按预期工作:
void classTypeParameters() {
    ArrayList<String> a = readList(ArrayList.class, String.class);
    LinkedList<String> b = readList(LinkedList.class, Integer.class);
}

<T extends List<X>, X> T readList(Class<T> clazz, Class<X> type) {
    try {
        return clazz.newInstance();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

以下作品是我个人的最爱。它检查列表类型。有点危险的是有人可能会错误地忘记分配结果。可以通过将readList重命名为readListWithTemplate左右来解决,这显然会使用返回值。它类似于List.toArray(T[] a):
void template() {
    ArrayList<String> a = readList(new ArrayList<String>());
    LinkedList<String> b = readList(new LinkedList<String>());
    // wrong usage:
    List<String> c = new LinkedList<String>();
    readList(c);
}

@SuppressWarnings("unchecked")
<X, T extends List<X>> T readList(T template) {
    try {
        return (T) template.getClass().newInstance();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

“超级 token 类型”也可以,但是可能有点难以理解
对于不熟悉此模式的开发人员,以及在Eclipse中
我收到警告“应该记录空块”,我想避免这种情况:
void superTypeToken() {
    ArrayList<String> a = readList(new ListType<ArrayList<String>>() {});
    LinkedList<String> b = readList(new ListType<LinkedList<String>>() {});
}

abstract static class ListType<X extends List<?>> {
    // super type token class
}

@SuppressWarnings("unchecked")
<X, T extends List<X>> T readList(ListType<T> 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 <E> List<E> newList();

    public static final EmptyListBuilder ARRAY_LIST_BUILDER =
            new EmptyListBuilder() {

        public <E> List<E> newList() {
            return new ArrayList<E>();
        }
    };
}

如静态字段所示,您还可以为一些标准类提供默认实现。

使用这样的类:
<T> List<T> readList(EmptyListBuilder builder) {
    List<T> list = builder.newList();
    // read in elements
    return list;
}

您可能无法准确知道自己拥有的列表类型,但这是一个问题,然后听起来您正在尝试做一些奇怪的事情。

10-06 05:28