Java下界通配符(? super Type)的使用
作者:小湘西
在Java中,? super Type
是一个下界通配符,表示参数化类型的下限是Type
。这意味着容器可以持有Type
类型的任何对象或者Type
的父类型对象。
使用场景
这种类型的通配符通常用于泛型方法中,允许方法接受Type
的实例或其父类型的集合。这是基于PECS原则(Producer Extends, Consumer Super),即如果你需要一个提供(生产)指定类型元素的集合,使用? extends
;如果你需要一个消费(接受)指定类型元素的集合,使用? super
。
例子
假设有一个基类Animal
和两个子类Dog
和Cat
class Animal {} class Dog extends Animal {} class Cat extends Animal {}
现在,我们有一个方法,它的目的是往一个集合里添加Dog
对象:
public void addDogsToList(List<? super Dog> dogs) { dogs.add(new Dog()); // 这是允许的,因为List可以是Dog或其父类型 }
这个方法接受的参数是一个列表,这个列表的类型是Dog
或Dog
的任何父类型。因此,以下的调用都是有效的:
List<Animal> animalList = new ArrayList<>(); List<Dog> dogList = new ArrayList<>(); List<Object> objectList = new ArrayList<>(); addDogsToList(animalList); // 正确:Animal是Dog的父类型 addDogsToList(dogList); // 正确:列表的类型正好是Dog addDogsToList(objectList); // 正确:Object是所有类的父类型
在这个例子中,无论是Animal
列表、Dog
列表还是Object
列表,都可以传递给addDogsToList
方法,因为它们都满足? super Dog
的条件。这样做的好处是,你可以将方法的使用范围扩展到更通用的类型,同时仍然能够向集合中添加特定类型的元素(在本例中是Dog
)。
遍历
使用? super Type
时,遍历集合可能会受到一些限制,因为你不知道集合中元素的确切类型。你只能确保它们是Type
或其父类的实例。在遍历时,通常需要将元素视为Type
的父类类型,这样会丢失与Type
相关的特定信息。
例如
public void processAnimals(List<? super Animal> animals) { for(Object obj : animals) { // 因为不确定List的具体类型,只能将元素当作Object处理 // 如果需要使用Animal特有的方法或属性,需要进行类型转换 if (obj instanceof Animal) { Animal animal = (Animal) obj; // 现在可以调用Animal类的方法 } } }
总结
? super Type
通配符的使用提高了代码的灵活性,它允许你编写能够接受更广泛类型集合的泛型方法,同时保证了向这些集合中添加元素的类型安全。这是PECS原则中的“Consumer Super”部分,适用于你的集合是消费或接受元素的情况。在遍历这样的集合时,通常需要将元素视为最通用的类型(如Object
),除非进行显式的类型转换。
到此这篇关于Java下界通配符(? super Type)的实现的文章就介绍到这了,更多相关Java下界通配符内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!