泛型(总结完整)

1、泛型的理解和好处

1.1 使用传统方法的问题分析

  • 无法对加入到几个ArrayList中的数据类型进行约束(不安全) 抛出ClassCastException异常
  • 遍历的时候需要进行类型转化(向下转型),如果集合中的数据量较大,对效率有影响

1.2使用泛型

  • 编译时,添加检查元素的类型,提高了安全性
  • 减少了类型转化的次数

1.3小结(重点)

不使用泛型 Dog -加入-> Object -取出-> Dog 放入ArrayList中会先转成Object,取出再转成Dog

使用泛型 Dog --> Dog --> Dog

1.4 泛型理解 E

  • 泛型是< E >

  • Dog,String这些是传入泛型的参数

1.5 泛型使用

1. E 表示 s的数据类型,该数据类型在定义Person对象的时候指定,即在编译期间,就确定了E是什么类型
Person<E>{
    E s;//E 表示 s的数据类型,该数据类型在定义Person对象的时候指定,即在编译期间,就确定了E是什么类型
    
    public Person(E s){
        this.s = s;
    }
    public E f(){
        return s;
    }
}
2. 泛型的语法和使用
  • List< Integer> list = new ArrayList< Integer>() OK
  • List< int> list = new ArrayList< int>() 错误

泛型(T,E)只能是引用类型

泛型中可以传入子类

3. 在开发时往往进行简写(重点,推荐)

编译器会进行类型推断,所以后面的可以省略

List< Integer> list = new List<>();

1.6 泛型的遍历(迭代器 和 增强for循环)

1.7 泛型使用并且sort排序的例子

import java.util.ArrayList;
import java.util.Comparator;

public class Practice0559 {

    public static void main(String[] args) {
        ArrayList<Empolyee> list = new ArrayList<>();
        list.add(new Empolyee("c",12,new MyDate(2000,11,12)));
        list.add(new Empolyee("a",120,new MyDate(20000,110,120)));
        list.add(new Empolyee("a",1200,new MyDate(200000,1100,1200)));

        for (Empolyee empolyee : list) {
            System.out.println(empolyee);
        }

        list.sort(new Comparator<Empolyee>() {
            @Override
            public int compare(Empolyee emp1, Empolyee emp2) {
                //先按姓名排序,再按生日排序
                //先对传入的参数进行验证
                if(!(emp1 instanceof Empolyee && emp2 instanceof Empolyee)){
                    System.out.println("类型不匹配!");
                    return 0;
                }
                int i = emp1.getName().compareTo(emp2.getName());
                if(i!=0) return i;

//                int yearMinus = emp1.getBirthday().getYear()-emp2.getBirthday().getYear();
//                if(yearMinus!=0) return yearMinus;
//
//                int monthMinus = emp1.getBirthday().getMonth()-emp2.getBirthday().getMonth();
//                if(monthMinus!=0) return monthMinus;
//
//                return emp1.getBirthday().getDay()-emp2.getBirthday().getDay();

                //封装到类中
                return emp1.getBirthday().compareTo(emp2.getBirthday());

            }
        });

        //排序后
        System.out.println("排序后==================================");
        for (Empolyee empolyee : list) {
            System.out.println(empolyee);
        }

    }

}


class Empolyee{
    private String name;
    private double sal;
    private MyDate birthday;

    public Empolyee(String name, double sal, MyDate birthday) {
        this.name = name;
        this.sal = sal;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSal() {
        return sal;
    }

    public void setSal(double sal) {
        this.sal = sal;
    }

    public MyDate getBirthday() {
        return birthday;
    }

    public void setBirthday(MyDate birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "Empolyee{" +
                "name='" + name + '\'' +
                ", sal=" + sal +
                ", birthday=" + birthday +
                '}';
    }
}

class MyDate implements Comparable<MyDate>{
    private int month;
    private int day;
    private int year;

    public MyDate(int month, int day, int year) {
        this.month = month;
        this.day = day;
        this.year = year;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public int getDay() {
        return day;
    }

    public void setDay(int day) {
        this.day = day;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    @Override
    public String toString() {
        return "MyDate{" +
                "month=" + month +
                ", day=" + day +
                ", year=" + year +
                '}';
    }

    @Override
    public int compareTo(MyDate o) {//年月比较

        int yearMinus = this.year-o.getYear();
        if(yearMinus!=0) return yearMinus;

        int monthMinus = this.month-o.getMonth();
        if(monthMinus!=0) return monthMinus;

        return this.day-o.getDay();

    }
}

1.8 泛型接口的使用

  • 无法初始化数组 因为数组在new时不能确定泛型的类型,就无法开辟内存空间,只能定义
  • 静态方法无法使用泛型,同样原理,因为静态方法与对象无关,只与类有关,在类加载时对象还未创建

1.9 自定义泛型方法的使用(难点,重要)

  • 泛型方法,可以定义在普通类中,也可以定义在泛型类中
  • 修饰符 < T,R> 返回类型 方法名(T t,R r)(参数列表){}
  • 自动识别泛型,并且装箱
  • 如果修饰符后面没有加如泛型,方法就不是泛型方法,而是使用了泛型方法(前面定义的)(重要)
//泛型方法
public <T,R> void fly(T t,R r){
    sout t.getclass();
    sout r.getclass();
}
//使用
a.fly("string", 10);  
//输出  String  Integer

b.fly(10,10.1);
//输出 Integer Float


下面的例子中,T是类的泛型,而K是方法自己创建的泛型

public <K> void hello(T t,K k){};

1.10 泛型的继承和通配符

  • 泛型不具备继承性
  • <?> 支持任意泛型类型
List<Object> list = new ArryList<String> list; //错误
  • <? extends A> 支持A类以及A类的子类,规定了泛型的上限
  • <? super A> 支持A类以及A类的父类,规定了泛型的下限

1.11 JUnit使用 一般使用JUnit5.4

练习
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Test;

import java.util.*;

public class Junit0565 {

    public static void main(String[] args) {

    }

    @Test
    public void testList(){
        DAO<User> userDAO = new DAO<>();
        userDAO.save("001",new User(1,10,"jack"));
        userDAO.save("002",new User(2,20,"King"));

        List<User> list = userDAO.list();
        for (User user : list) {
            System.out.println(user);
        }
    }

}

//定义User类
class User{
    private int id;
    private int age;
    private String name;

    public User(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

//定义泛型类
class DAO<T>{
    private Map<String, T> map = new HashMap<String,T>();

    public DAO() {
    }

    public void save(String id, T entity){
        map.put(id,entity);
    }

    public T get(String id){
        return map.get(id);
    }

    public void update(String id,T entity){
        map.put(id,entity);
    }

    //返回map中的所有T对象
    public List<T> list(){
        List<T> list = new ArrayList<>();

        Set<String> keySet = map.keySet();
        for (String key :keySet) {
            list.add(map.get(key));
        }

        return list;
    }

    public void delete(String id){
        map.remove(id);
    }

    public DAO(Map<String, T> map) {
        this.map = map;
    }

    public Map<String, T> getMap() {
        return map;
    }

    public void setMap(Map<String, T> map) {
        this.map = map;
    }

    @Override
    public String toString() {
        return "DAO{" +
                "map=" + map +
                '}';
    }
}

2、总结

1. 为什么需要泛型

  • 不需要向下转换
  • 减少安全隐患

2. 泛型介绍

  • 语法
  • 实例化
  • 使用例子

3. 泛型使用

  • 自定义泛型类
  • 自定义泛型接口
  • 自定义泛型方法 重点
  • 泛型的继承和通配符

4. JUnit练习

5. 个人体会

更像是一种编码思路,能够灵活使用即可!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值