day7
1.泛型
与c++泛型的第一个区别是,java泛型的参数T不能为基本数据类型,如果是int编译器自动推导成Integer。
泛型第一个应用就是可以创造生成器,工厂模式的一个应用:
|
|
对于模板方法的定义与c++不同,要在返回值的后面加上模板参数:
|
|
2.Iterator与Iterable
java.lang.Iterable是一个接口interface,一般用来实现这个接口可用于iterator()方法。这个接口也是我们自己设计类时常实现的接口,我们不直接实现Iterator,而是实现Iterable。
为什么这样做呢?
因为Iterator接口的核心方法next()或者hasNext() 是依赖于迭代器的当前迭代位置的。 如果Collection直接实现Iterator接口,势必导致集合对象中包含当前迭代位置的数据(指针)。 当集合在不同方法间被传递时,由于当前迭代位置不可预置,那么next()方法的结果会变成不可预知。 除非再为Iterator接口添加一个reset()方法,用来重置当前迭代位置。 但即时这样,Collection也只能同时存在一个当前迭代位置。 而Iterable则不然,每次调用都会返回一个从头开始计数的迭代器。 多个迭代器是互不干扰的。
|
|
3.运用于匿名内部类
|
|
可以看到,Customer类中的generator方法有了static修饰,不能用继承接口Generator实现方法。可以通过泛型来做到这点。
4.擦除
什么是擦除?
我们可以声明ArrayList.class,但是不能调用ArrayList
|
|
两个我们看来不同的类型ArrayList
|
|
上述代码会报错,原因是Java运用了擦除,就是说在泛型代码运行时是将类型T擦掉的,一直向上替换到边界,没指定上边界就会换到Object.比如说上例中obj就无法调用.f()。简而言之:
在泛型代码内部,无法获得任何泛型参数类型的信息
我们需要通过边界来让他接受这个类型是有这个调用方法的。
在泛型参数T后加上extends HasF,表示这个参数是HasF的类型或者子类,这样就肯定有.f()方法。
另,在泛型中不要创建数组,例如T[]最好用ArrayList
5.边界
语法定义:
T extends classA&interfaceB&interfaceC&…//一定要按照这种顺序写
6.运用通配符
我们在表示两个List
如果B是A的子类,那么List<? extends B>是List<? extends A>的子类