java泛型,通配符

以前对泛型的接触和理解基本只有List,Map 可以说相当初级了哈哈。最近比较详细地研究了泛型的实质,范围等,在这里做一个分享,希望和大家交流。

本文将按以下结构叙述:1.泛型是用来解决什么问题的?2.泛型常见的应用场景。3.通配符,extends,super等关键字

首先,什么是泛型呢。根据java官方文档的解释,Generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods 简单来说就是将class,interface,method参数化,在其他类使用的时候再决定其具体的类型。
泛型要解决的,主要就是在编译的时候做类型检查,并提供自动类型转换等便利。具体可以参考网上其他文档,这里就不再赘述了。

所以,明确了泛型的解决问题,使用场景就清楚了:
1.编译阶段提供类型检查。如果没有泛型,那么Collection等接口提供的装箱操作就只能放Object,如果类型有误,要在运行时才会报错,这样无疑增加了时间成本。
2.自动转换类型。在java没有提供泛型的时候,每次从集合中取出对象,需要做一次强制类型转换,如果开发者知道集合中存放的类型还好,如果不知道,还要去上下文中仔细寻找才能得知。
3.代码复用。因为class,method参数化了,可以被多种类型复用。

最后是通配符和各种关键字的解释,这些在平时的业务代码中用得比较少,所以没怎么接触过,正好借这个机会一并了解了。

首先是通配符“?”,在java中是任何的意思。下面通过代码演示
有三个类,继承关系如下:

class Person{
    public static List<Person> getPersonList(){
        return null;
    }
};
class Man extends Person{};
class Father extends Man{
    public static List<Father> getFatherList(){
        return null;
    }
};

大家都知道,一个声明了父类的集合可以存放子类,例如

List<Person> list = new ArrayList<>();
list.add(new Man());

是完全没有问题的,但是如果声明了父类的集合,却是不能指向一个子类的集合的:

//下面的代码编译报错,类型不匹配
//List<Person> list = Father.getFatherList();

如果这里Person是一个接口,我就是想声明接口集合怎么办呢,这时候通配符就很有用了:

List<? extends Person> list = Father.getFatherList();

上述代码会告诉编译器,这个list里存放的,可能是任何Person的子类,所以指向的集合,只要泛型的类型是Person的子类都可以。编译通过了,也能正常使用。但需要注意的是,使用通配符后,表明该集合中可能是任何Person的子类,所以编译器不知道list中存放的具体类型是什么,所以一切参数与类型有关的方法都不能使用,例如list.add(),list.addAll()。而如果参数类型是Object或者没有参数的,都可以正常使用:list.get(),list.remove()等

与extends相对应的,super关键字,表示该泛型是super后面声明的类型的父类。

List<? super Father> list = Person.getPersonList();

该用法表示list中可以是任何Fahter的父类,因此可以指向一个Person的集合,因为Person是Father的父类。

最后是泛型常见的T,其实T并没有特别的含义,只不过在约定中,泛型使用T代表类型,你也可以用A,B,C……通常的约定是:
E - Element (Collections Framework)
K - Key
N - Number
T - Type
V - Value
S,U,V etc. - 2nd, 3rd, 4th types

public class Holder<T>{
    T entry;
}

这样我们在看声明的时候就知道了,Holder中的T,是一个类型的声明,我们常见的
Map<K,V> K代表Key,V代表Value

英文水平ok的同学可以参考官方文档
https://docs.oracle.com/javase/tutorial/java/generics/why.html
里面很详细的介绍了泛型的使用,有疑问的地方欢迎和我讨论

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值