java泛型——边界与通配符

边界

在泛型的参数类型上设置的限制条件。例如:使用extends关键字<T extends AClass>

2、边界可以有多个

边界可以是类也可以是接口,接口可以有多个而类只可以有一个。类放在前,接口在后

例如:

class A{}
Interface I1{}
Interface I2{}
public class B<T extends A & I1 &I2>{}

通配符

通配符表示表示任何一个类型,用“?”代表通配符。

1、子类限定通配符<? extends AClass>,它表示一个类,这个类是AClass的子类。

(1)子类限定通配符可以使你建立某种类型的向上转型关系。例如:

假如Apple是Fruit的子类。

//编译错误,这里并没有向上转型的关系。List<Apple>不是List<Fruit>的子类
List<Fruit> list = new ArrayList<Apple>();

使用子类限定通配符可以建立向上转型的关系。但是无法使用参数是泛型参数的方法。

List<? extends Fruit> list = new ArrayList<Apple>();//编译通过
list.add(new Fruit());//编译错误
list.add(new Apple());//编译错误
list.add(new Object());//编译错误
list.add(null);//可以
Fruit f = list.get(0);//可以
list.contains(new Apple());//可以

但是如果像上面这样声明一个List,它无法添加任何对象(除了null),但是可以使用get()和contains(),方法。可以这么理解:

对于不能添加对象:

add的参数是T,也就是这个参数将变成“? extends Fruit”,这代表这它可以是任何事物,编译器无法确认任何事物的类型安全。

对于可以使用的get()等方法:

通过源码可以发现,这些方法的参数是Object,所以无论什么类型的对象都可以。

2、超类型通配符<? super AClass>

可以向List<? super AClass>中添加AClass和它的子类。

返回值为泛型的方法不能使用。

3、无界通配符

(1)无界通配符代表某个具体的类型,而原生类型代表任何类型。

原生类型什么都能放。

List l1 = new ArrayList<>();
l1.add("aa");
l1.add(1);
Object o = l1.get(0);

使用无界通配符后,什么都不能放(除了null)。可以使用get()取,因为还不知道确切的类型,所以只能用Object。

List<?> l = new ArrayList<>();
l.add(1);//编译错误
Object o = l.get(0);

(2)捕获转换

假如方法f1()的参数为List<?>,泛型方法f2()的参数为List<T>,那么就可以在f1()中调用f2()

public class Test{
    /*
     *调用f1()时传给它的参数的具体类型将被捕获,也就是说当调用之后才知道他的具体类型
     *所以可以将它传给f2
     */
    public static void f1(List<?> list){
        f2(list);
    }
    public static <T> void f2(List<T> list){
        T t = list.get();
    }
    public static void main(String[] args){
        List<String> list = new ArrayList<>();
        f1(list);
    }
}

这节学得很迷,书上的语句实在难理解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值