泛型的设计背景
集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在JDK1.5之前只能把元素类型设计为Object,JDK1.5之后使用泛型来解决。因为这个时候除了元素的类型不确定,其他的部分是确定的。
例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型
。Collection<E>, List<E>, ArrayList<E>
这个<E>
就是类型参数,即泛型。
泛型的类型必须是类
,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换
默认类型为java.lang.object类型
。例子
public class Order<T> { String orderName; int orderId; //类的内部结构就可以使用类的泛型 T orderT; public Order(String orderName, int orderId, T orderT) { this.orderName = orderName; this.orderId = orderId; this.orderT = orderT; } }
总结
public GenericClass(){}
。而下面是错误的:public GenericClass<E>(){}
尽管在编译时
ArrayList<String>
和ArrayList<Integer>
是两种类型,但是,在运>行时只有一个ArrayList被加载到JVM中
。
泛型对应的类型均按照Object处理,但不等价于Object
。ArrayList<Fruit> flist = new ArrayList<>();
不能使用基本数据类型
,可以使用包装类替换
。泛型方法:
在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。换句话说,泛型方法所属的类是不是泛型类都没有关系
。
泛型方法,可以声明为静态的
。原因: 泛型参数是在调用方法时确定的。并非在实例化类时确定。
例子
public <E> List<E> copyFromArrayTolist(E[] arr) { ArrayList<E> list = new ArrayList<>(); for (E e : arr) { list.add(e); } return list; }
class Father<T1, T2> {} //子类不保留父类的泛型 // 1)没有类型擦除 class Son<A, B> extends Father { //等价于class Son extends Father<0bject , object>{} } // 2)具体类型 class Son2<A, B> extends Father<Integer, String> {} //子类保留父类的泛型 // 1)全部保留 class Son3<T1, T2, A, B> extends Father<T1, T2> {} // 2)部分保留 class Son4<T2, A, B> extends Father<Integer, T2> {}
比如: List<?> ,Map<?,?>
List<?>是List<String>
、List<Object>
等各种泛型List的父类。
读取
List<?>的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object。
写入
list中的元素时,不行。因为我们不知道c的元素类型,我们不能向其中添加对象。➢唯一的例外是null,它是所有类型的成员。
例子:? 通配符相当于Object和String的通用父类,此时可以实现赋值
- 类A是类B的父类,
G<A>
和G<B>
是没有关系的,二者共同的父类是:G<?>
- 将任意元素加入到其中
不是类型安全
的:
Collection<?> C = new ArrayList();
c.add(new Object()); //编译时错误。因为我们不知道c的元素类型,我们不能向其中添加对象。
public void test3() { List<Object> list1 = null; List<String> list2 = null; List<?> list = null; list = list1; list = list2; print(list1); print(list2); } public void print(List<?> list) { Iterator<?> iterator = list.iterator(); while (iterator.hasNext()) { Object obj = iterator.next(); System.out.println(obj); } }
<?> 允许所有泛型的引用调用
上限extends
——使用时指定的类型必须是继承某个类,或者实现某个接口,即<=
下限super
——使用时指定的类型不能小于操作的类,即 >=
举例:
<? extends Number> (无穷小,Number]
<? super Number> [Number,无穷大)
<? extends Comparable>
DAO:data(base) access object