泛型概述
- 表示泛型,只能填写引用数据类型。实例化接口的实现类时,指明E的类型
- list接口声明中使用了泛型,但使用时可不指定泛型,默认为object,则各类型对象都可以添加
- 接口的方法也使用了泛型
- 好处在于不需要类型强转(直接返回指定类型,而不是Object类对象)
集合中的泛型使用
未使用泛型
- 班级成绩按照学号顺序存储到list中,有序采用集合list实现
- Interger类型(自动装箱拆箱)混入了个String类型
使用泛型(List)
- 指定存储对象的类型,则get(i)直接返回Interger类型对象,省了强转
- 注释处采用for增强循环遍历
- 注意泛型写法
使用泛型(Map)
- 书写泛型时,左一定要写,右边可省略
- Set对象未使用泛型前:元素为object,使用后,元素为entry(一个键,一个值)
- 使用泛型后,不需要强转了(已经是entry类型了),直接调用getKey和getValue方法
自定义泛型类
泛型类
测试类1
- 实例化泛型类,指定T的类型
- 创建order对象,则创建list(可存储T类型元素的list)
- 通过add方法将T类型对象(一个成员变量)放入list中
- 未定义泛型,默认为object类型
测试类2
- 子类继承父类,父类指定泛型,则子类采用父类泛型,见上图1
- 子类也可不指明,见上图2
泛型在数据库中的使用
定义DAO泛型类
DAO子类1(泛型类)
DAO子类2(泛型类)
测试类(具体操作)
- Java访问数据库数据,以对象形式返回
- DAO定义操作数据库表里的数据方法
- 声明泛型后,操作具有通用性
泛型方法
- 适用于要指明不同于T类型的变量的情况
- 调用方法时指明E类型
- 书写格式,注意最前方的
Collection接口一方法
- 利用泛型将整型集合变为整型数组,而不是Object类型数组(Collection接口里另有一未指定泛型的方法)
泛型与继承
- 类对象,数组可赋值(String类型数组可赋值给Object类型数组),推理得出:list也可赋值,但事实是不可以
- 类对象和数组可赋值说明子类可以赋值给父类(一种类比说法),list不可以,说明list不是list1父类,所以不能赋值
- 类比垃圾和放垃圾的垃圾桶,果皮是垃圾的子类,但放果皮的垃圾桶不是放垃圾的垃圾桶的子类
- list和list1是两个使用泛型的集合类对象,为并列关系,类比垃圾桶间都是并列的
通配符
- ?是所有具体类型的父类,具有通用性
- list
泛型思想(generic)
把一个集合中的内容限制为一个特定的数据类型,这就是generics的核心思想
- 泛型限定数据类型
- 泛型使用不局限于集合
泛型注意点
- 静态方法中不能使用类的泛型。
- 如果泛型类是一个接口或抽象类,则不可创建泛型
类的对象(和泛型类没什么关系哦,属于接口或抽象类的知识点) - 不能在catch中使用泛型
- 从泛型类派生子类,泛型类型需具体化(参照上文Order和SubOrder)
第二点:T是抽象的,形式化的,T在实例化时确定,而静态结构在类加载时就加载了,T未确定,所以不可以在静态方法中使用类的泛型
第三点:即使T继承了某个异常类,也不能使用泛型
通配符的集合类对象
list1和list都指向堆空间创建的同一实体
集合类对象声明含?,iterator方法的返回值类型也含?
next方法的返回值有类型,不是通配符?,而是Object类型
- 说明不管list存放何种类型,返回值都是Object类型(要采用Object类型变量接收)
- 形参类型为?,不是Object类型,所以任何类对象都不可写入
- 不仅仅是集合类如此,其他含?的泛型类都这样(不可写入)
- 特殊的是含?的泛型类,可添加入null,因为不管任何类都包含null,null是所有类默认初始化值
泛型练习
练习1(人对应不同信息类型)
- 人对应不同信息类型,将信息类型设计为接口(Info)
- 不同信息类型即是接口的实现类(Contact类和Introduction类)
- 人在自定义的类上(Person类)使用泛型,泛型就是信息类型,是接口类型的
- 具体创建人的对象时,指明泛型类型,即信息类型
interface Info{ // 只有此接口的子类才是表示人的信息
}
class Contact implements Info{ // 表示联系方式
private String address ; // 联系地址
private String telephone ; // 联系方式
private String zipcode ; // 邮政编码
public Contact(String address,String telephone,String zipcode){
this.address = address;
this.telephone = telephone;
this.zipcode = zipcode;
}
public void setAddress(String address){
this.address = address ;
}
public void setTelephone(String telephone){
this.telephone = telephone ;
}
public void setZipcode(String zipcode){
this.zipcode = zipcode;
}
public String getAddress(){
return this.address ;
}
public String getTelephone(){
return this.telephone ;
}
public String getZipcode(){
return this.zipcode;
}
@Override
public String toString() {
return "Contact [address=" + address + ", telephone=" + telephone
+ ", zipcode=" + zipcode + "]";
}
}
class Introduction implements Info{
private String name ; // 姓名
private String sex ; // 性别
private int age ; // 年龄
public Introduction(String name,String sex,int age){
this.name = name;
this.sex = sex;
this.age = age;
}
public void setName(String name){
this.name = name ;
}
public void setSex(String sex){
this.sex = sex ;
}
public void setAge(int age){
this.age = age ;
}
public String getName(){
return this.name ;
}
public String getSex(){
return this.sex ;
}
public int getAge(){
return this.age ;
}
@Override
public String toString() {
return "Introduction [name=" + name + ", sex=" + sex + ", age=" + age
+ "]";
}
}
class Person<T extends Info>{
private T info ;
public Person(T info){ // 通过构造方法设置信息属性内容
this.info = info;
}
public void setInfo(T info){
this.info = info ;
}
public T getInfo(){
return info ;
}
@Override
public String toString() {
return "Person [info=" + info + "]";
}
// public String toString(){ // 覆写Object类中的toString()方法
// return this.info.toString() ;
// }
}
public class GenericPerson{
public static void main(String args[]){
Person<Contact> per = null ; // 声明Person对象
per = new Person<Contact>(new Contact("北京市","01088888888","102206")) ;
System.out.println(per);
Person<Introduction> per2 = null ; // 声明Person对象
per2 = new Person<Introduction>(new Introduction("李雷","男",24));
System.out.println(per2) ;
}
}
创建对象时指明T类型,即信息类型
电话号码String存储,避免连接变成相加减
泛型思想:编写通用内容,实例化时指明具体类型
练习2(TreeSet)
回顾TreeSet章节,加入泛型
- TreeSet要求元素同一类型,与泛型限制数据类型不谋而合
- next方法返回不再是Object类型,而是Employee类型
练习3(DAO)
操作对象类
- 省略了get和set方法,构造器,ToString以及equals和hashcode方法(Map中存储)
泛型类
- 显式初始化Map类对象
测试类
- 在测试类中对dao.map进行显式初始化(就不用在泛型类中显式初始化了,二选一)