首先,我想知道您(一个人)将代码整理成这种形式需要付出多少努力:
import java.util.List;
import java.util.Map;
interface IModel<T> {}
interface I {}
class A implements I {}
class B implements I {}
class C implements I {}
public class UpperBounds
{
public static void main(String[] args)
{
IModel<Map<A, Map<B, List<C>>>> model = null;
foo(model);
}
static void foo(IModel<Map<? extends I, Map<? extends I, List<? extends I>>>> dataModel)
{
}
}
而不是让数百人(他们想帮助你)自己做这件事,以便他们可以在他们的 IDE 中编译和查看一些东西。我的意思是,这并不那么难。
话虽如此:从技术上讲,您在这里还缺少一些 extends 子句。这编译得很好:
import java.util.List;
import java.util.Map;
interface IModel<T> {}
interface I {}
class A implements I {}
class B implements I {}
class C implements I {}
public class UpperBounds
{
public static void main(String[] args)
{
IModel<Map<A, Map<B, List<C>>>> model = null;
foo(model);
}
static void foo(IModel<? extends Map<? extends I, ? extends Map<? extends I, ? extends List<? extends I>>>> dataModel)
{
}
}
但你应该
不是
这样实现。那是晦涩难懂的。无论dataModel 参数是什么,您都应该考虑为此创建适当的数据结构,而不是传递如此混乱的深度嵌套的通用映射。
其他答案中已经提到了原始版本无法编译的原因。并且可以通过使用非常更简单的方法调用的示例来使其更加清晰。考虑这个例子:
interface IModel<T> {}
interface I {}
class A implements I {}
class B implements I {}
class C implements I {}
public class UpperBounds
{
public static void main(String[] args)
{
List<List<A>> lists = null;
exampleA(lists); // Error
exampleB(lists); // Works!
}
static void exampleA(List<List<? extends I>> lists)
{
}
static void exampleB(List<? extends List<? extends I>> lists)
{
}
}
exampleA 方法不能接受给定的列表,而exampleB 方法可以接受它。
Angelika Langer 的泛型常见问题解答的Which super-subtype relationships exist among instantiations of generic types? 中很好地解释了详细信息。
直观地说,关键是List<A> 类型是List<? extends I> 的子类型。但是让该方法只接受List<List<? extends I>> 不允许您传入一个列表,其元素是List<? extends I> 的子类型。为了接受子类型,您必须使用? extends。
(这甚至可以进一步简化:当一个方法接受 List<Number> 时,您不能传入 List<Integer>。但这不会说明 List<A> 是 List<? extends I> 的子类型在此处清楚)