3.1 Java之泛型

泛型概述

这里写图片描述


这里写图片描述

  • 表示泛型,只能填写引用数据类型。实例化接口的实现类时,指明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的核心思想

  • 泛型限定数据类型
  • 泛型使用不局限于集合

泛型注意点

  1. 静态方法中不能使用类的泛型。
  2. 如果泛型类是一个接口或抽象类,则不可创建泛型
    类的对象(和泛型类没什么关系哦,属于接口或抽象类的知识点)
  3. 不能在catch中使用泛型
  4. 从泛型类派生子类,泛型类型需具体化(参照上文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进行显式初始化(就不用在泛型类中显式初始化了,二选一)

猜你喜欢

转载自blog.csdn.net/lwz45698752/article/details/81383377
3.1