编辑:我带来一个好消息。 有一种方法可以获取您想要的大多数东西。
public static > R createListFullOfEmptyString(IntFunction creator, int size)
{
R list = creator.apply(size);
for (int i = 0; i < size; i++)
{
list.add("");
}
return list;
}
// compiles
List l1 = createListFullOfEmptyString(ArrayList::new, 5);
List l2 = createListFullOfEmptyString(ArrayList::new, 5);
List l3 = createListFullOfEmptyString(ArrayList::new, 5);
// doesn't compile
List l4 = createListFullOfEmptyString(ArrayList::new, 5);
缺点是客户确实需要提供R的一个实例以进行突变,或提供某种构造R的方法。没有其他方法可以安全地构造它。
我将在下面保留原始答案,以供参考。
综上所述:
没有充分的理由,只是没有完成。
直到这样的时候,对于执行以下所有操作的方法,不可能编写具有正确方差的精确类型:
A)接受或创建参数化的数据结构
B)将计算的(未传入)值写入该数据结构
C)返回该数据结构
写入/接受值恰好是应用协方差的情况,这意味着数据结构上的类型参数必须由要写入数据结构的值的类型下限。 目前,在Java中表达此信息的唯一方法是在数据结构上使用下界通配符,例如 列表。
如果我们正在设计诸如OP之类的API,则可以自然(但不合法)将其表示为:
// T is the type of the value(s) being computed and written to the data structure
// Method creates the data structure
Container create()
// Method writes to the data structure
Container write(Container container)
那么我们可以使用的选项是:
A)使用下界通配符,并强制调用方强制转换输出:
// This one is actually useless - there is no type the caller can cast to that is both read- and write-safe.
Container super T> create()
// Caller must cast result to the same type they passed in.
Container super T> write(Container super T> container)
B)过度限制数据结构上的类型参数以匹配要写入的值的类型,并强制调用方强制转换输入和输出:
// Caller must accept as-is; cannot write values of type S (S super T) into the result.
Container create()
// Caller must cast Container (S super T) to Container before calling, then cast the result back to Container.
Container write(Container container)
C)使用一个新的类型参数,并在内部进行我们自己的不安全转换:
// Caller must ensure S is a supertype of T - we cast T to S internally!
Container create()
// Caller must ensure S is a supertype of T - we cast T to S internally!
Container write(Container container)
选择你的毒药。