泛型通配符中,子类边界与父类边界方法受限原因

本文深入探讨Java泛型的基本概念及其实现方式,同时解析通配符的使用场景,包括子类边界和父类边界对方法的影响,帮助读者掌握泛型编程的核心技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

泛型:
为了使类以适应只因参数不同,而对参数到操作基本相同而提供的一种占位符。
如:

public class test<T>{
    private T t = null;
    public void setT(T t){
        this.t = t;
    }
    public T getT(){
        return this.t;
    }
}

在集合中为了提高代码的重用性,很多都使用泛型来指定存储的数据类型:

List<Integer> list = new ArrayList<Integer>();

但有时我们希望通过一个函数来操作这些集合类型:
如遍历,修改指定参数,添加参数:

public void print(List<Integer> list){
    //遍历集合方法
}

//那么当我们想要遍历List<Number> list 时 ,此方法就不再使用
public void print(List<Number> list){
}
//由于泛型擦除,这两个方法会被认为相同,而无法编译

于是引入了通配符来解决以泛型类作为参数的方法:

//List<? extends T>
//List<? super T>
public void print(List<? extends T> list){
//此方法即可接收,泛型为T子类的集合类型
//相当于: 
// List<? extends Number> list = new ArrayList<Integer>();
}

public void print(List<? super T> list){
//此方法即可接收,泛型为T父类的集合类型
//相当于: 
// List<? super Integer> list = new ArrayList<Number>();
}

主要为了记录子类边界,父类边界对方法的影响:
T为<? extends T>中的T
如果使用子类边界,那么则不能使用该集合中以泛型T为参数的方法:

public static void main(String[] args){
    List<Integer> list = new ArrayList<Integer>();
    test(list);
}
public void test(List<? extends Number> list){
    //list.add(new Integer); 此类方法不能使用
    /*
    原因是:
    凡是泛型为Number子类的参数均可传递进来,
    这样就无法确定传递过来的参数的准确数据类型,
    又如何对其进行操作呢

    但是上帝关上了一扇门,一定会打开另一扇窗,
    因为传递过来的参数的父类是明确的(Number类型),
    通过父类引用指向子类对象,
    就可以使用返回值为Number类型的方法
    */
    Number number = list.get(0);
    //此类返回值为泛型的参数就可以使用

}

如果使用父类边界,那么不能使用该集合中返回值为泛型T的方法


public void test2(List<? super Integer> list){
    //list.get();
    /*此类返回值为泛型的方法不能使用,
    因为凡是Integer的父类泛型的集合均可传递,
    那么久无法明确其父类,
    而无法通过父类类型来返回参数

    由于传递过来的是Integer的父类,父类类型可以存储操作自己的子类型
    如:
        List<Object> list = new ArrayList<Object>();
        list.add(new Integer(1));//可行的
        List<Number> list = new ArrayList<Number>();
        list.add(new Integer(2));//也是可行的
    */
    list.add(new Integer());
}

总结:

造成通配符子类边界<? extends T>,与父类边界<? super T>方法使用受限的原因,是因为他们都无法得知传递来的参数的具体类型;子类边界只能确定传递来的参数的子类型,父类边界只能确定传递来的参数的父类型;由于引用只能由父类指向子类,利用此特性,子类边界来完成返回值为原泛型的方法,父类边界来完成参数为原泛型的方法!

注:原泛型即为作为实参传递进方法的对象的泛型,如:

public static void main(String[] args){
    //Integer即为原泛型
    List<Integer> list = new ArrayList<Integer>();
    this.test(list)
}
public void test(List<? extends Number>){
    //操作
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值