Day10-泛型

泛型

泛型的理解和好处

  1. 使用传统方法的问题分析

    • 不能对加入到集合ArrayList中的数据类型进行约束(不安全)

    • 遍历的时候,需要进行类型转换,如果集合中的数据量较大,对效率有影响

//传统方式
package 泛型;

import org.w3c.dom.DOMErrorHandler;

import java.util.ArrayList;
import java.util.Map;

@SuppressWarnings({"All"})
public class Demo01 {
   public static void main(String[] args) {
       ArrayList list = new ArrayList();
       list.add(new Dog("小白",1));
       list.add(new Dog("小黄",2));
       list.add(new Dog("发财",3));

       list.add(new Cat("来福",1));

       for (Object o :list) {
           Dog dog = (Dog)o;
           String name = dog.getName();
           int age = dog.getAge();
           System.out.println(name+"-"+age+"岁");
      }

  }
}

class Cat{
   private String name;
   private int age;

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

   public String getName() {
       return name;
  }

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

class Dog{
   private String name;
   private int age;

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

   public String getName() {
       return name;
  }

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

   public int getAge() {
       return age;
  }

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

}

  1. 使用泛型

    • 加入泛型之后,如果编译器发现添加的类型不满足要求,就会报错,提高了安全性

    • 在遍历的时候可以直接取出实例化的类型而不是Object类型

    • 减少了类型转换的次数,提高效率

    • 不再提示编译错

    • Dog----》Dog----〉Dog //放入时和取出时,不需要类型转换,提高效率

  2. 不使用泛型

    • Dog--加入--》Object--取出--〉Dog //放入ArrayList会先转成Object,在取出时,还需要转换成Dog

  • 泛型的作用是,可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值类型,或者是参数类型

class Person<E>{
 E s;  //E表示s的数据类型,该数据类型在定义Person对象的时候指定,即在编译期间,确定E是什么类型
 
 public Person(E s){
   this.s=s;
}
 
 public E f(){
   return s;
}
}

泛型的语法

泛型的声明

  1. interface接口<T>{}和class类<K,V>{}

比如:List,ArrayList

1)其中,T,K,V不代表值,而表示类型

2)任意字母都可以。常用T表示,是Type的缩写

泛型的实例化

要在类名后面指定类型参数的值(类型),如:

1)List<String> strList=new ArrayList<String>();

2)Iterator<Customer> iterator=customer.iterator();

package 泛型;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Demo02 {
   public static void main(String[] args) {
       //HashMap中使用泛型
       HashMap<String, Student> map = new HashMap<>();
       map.put("小明",new Student("小明",21));
       map.put("小红",new Student("小红",20));
       map.put("小黄",new Student("小黄",18));

       Set<String> strings = map.keySet();
       Iterator<String> iterator = strings.iterator();
       //迭代器遍历
       while (iterator.hasNext()) {
           String next =  iterator.next();
           System.out.println(next);
      }

       //HashSet中使用泛型
       System.out.println("==============");
       HashSet<Student> students = new HashSet<Student>();
       students.add(new Student("tom",12));
       students.add(new Student("jack",22));
       students.add(new Student("marry",16));
       //增强for循环
       for (Student o :students) {
           System.out.println(o);
      }

  }
}

class Student{
   private String name;
   private int age;

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

   public String getName() {
       return name;
  }

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

   public int getAge() {
       return age;
  }

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

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

泛型注意事项

  1. interface List<T>{},public class HashSet<E>{}....等等

说明:T,E只能是引用类型

List<Integer> list=new ArrayList<Integer>();//T
List<int> list2=new ArrayList<int>(); //F,int是基本数据类型
  1. 在给泛型指定具体类型后,可以传入该类型或者其子类型

package 泛型;

public class Demo03 {
  public static void main(String[] args) {
      Pig<A> aPig = new Pig<A>(new A()); //ok
      aPig.f();
      Pig<A> aPig1= new Pig<A>(new B()); //ok,B继承了A
      aPig1.f();
  }
}

class A{}
class B extends A{}

class Pig<E>{
  E s;

  public Pig(E s) {
      this.s = s;
  }

  public void f(){
      System.out.println(s.getClass());
  }
}

  1. 在实际开发中,我们往往简写,编译器会进行类型推断

      ArrayList<Pig> pigs = new ArrayList<Pig>(); //ok
     List<Pig> pigs1 = new ArrayList<Pig>();  //ok
       
     ArrayList<Pig> pigs2 = new ArrayList<>(); //ok
     List<Pig> pigs3 = new ArrayList<>(); //ok

如果我们这样写 List list3=new ArrayList();默认给它的泛型是【<E>E就是Object】

例题1

package 泛型;

import javax.naming.Name;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Comparator;

public class Demo04 {
   public static void main(String[] args) {
       ArrayList<Employee> employees = new ArrayList<>();
       employees.add(new Employee("caa",1_0000,new MyDate(12,3,1999)));
       employees.add(new Employee("caa",2_0000,new MyDate(12,30,1999)));
       employees.add(new Employee("b",3_0000,new MyDate(2,13,1997)));
       System.out.println("=====排序前的结果=====");
       System.out.println(employees);
       employees.sort(new Comparator<Employee>() {
           @Override
           public int compare(Employee o1, Employee o2) {
               //1.先对参数传入的实参进行验证
               if (!(o1 instanceof Employee && o2 instanceof Employee)){
                   System.out.println("类型不匹配");
                   return 0;
              }
               //2.比较name
               int i = o1.getName().compareTo(o2.getName());
               //如果名字不相同直接返回i
               if (i!=0){
                   return i;
              }
               //如果名字相同就比较birthday
               return o1.getBirthday().compareTo(o2.getBirthday());
          }
      });
       System.out.println("=============排序后的结果==========");
       System.out.println(employees);
  }
}

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

   public Employee(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 "\nEmployee{" +
               "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   year + "-" + month +
               "-" + day ;
  }

   @Override
   public int compareTo(MyDate o) {
       int yearMinus = year - o.getYear();
       if (yearMinus!=0){
           return yearMinus;
      }
       int monthMinus = month - o.getMonth();
       if (monthMinus!=0){
           return monthMinus;
      }
       return day-o.getDay();
  }
}

自定义泛型

基本语法
 class 类名<T,R...>{//...表示可以有多个
   成员
}
  • 普通成员可以使用泛型(属性,方法)

  • 使用泛型的数组不能初始化

  • 静态方法中不能使用类的泛型,但是静态方法可以有自己的泛型参数(因为静态是和类相关的,在类加载时,对象还没有创建)

  • 泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)

  • 如果在创建对象时,没有指定类型,默认为Object

注意事项:接口里的成员都是静态性质的

泛型的继承和通配符

  • 泛型不具备继承性

List<Object> list = new ArrayList<String>();
  • <?>:支持任意泛型类型

  • <? extends A>:支持A类以及A类的子类,规定了泛型的上限

  • <? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限

例题

User类
package 泛型;

public 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;
  }

   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;
  }

   @Override
   public String toString() {
       return "\nUser{" +
               "id=" + id +
               ", age=" + age +
               ", name='" + name + '\'' +
               '}';
  }
}
DAO类
package 泛型;

import java.security.Key;
import java.util.*;

public class DAO<T> {
   private Map<String,T> map =new HashMap<>();

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

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

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

   public List<T> list() {
       List<T> list = new ArrayList<>();
       Set<String> strings = map.keySet();
       for (String key :strings) {
          list.add(get(key));
      }
       return list;
  }

   public void delete(String id){
       map.remove(id);
  }
}
测试类
package 泛型;

import org.junit.jupiter.api.Test;

import java.security.PublicKey;
import java.util.List;

public class Demo05 {
   public static void main(String[] args) {

  }

   @Test
   public void test(){
       DAO<User> dao = new DAO<User>();
       dao.save("001",new User(1,12,"张三"));
       dao.save("002",new User(2,13,"李四"));
       dao.save("003",new User(3,14,"王五"));
       List<User> list = dao.list();
       System.out.println("list="+list);
       System.out.println("========修改后========");
       dao.update("003",new User(3,23,"小刘"));
       list = dao.list();
       System.out.println("list="+list);
       dao.delete("001");
       list=dao.list();
       System.out.println("list="+list);
       System.out.println("id=003"+dao.get("003"));
  }
}

 

posted @ 2023-06-30 22:46  仓鼠的气垫床  阅读(13)  评论(0编辑  收藏  举报