java泛型的学习

390 阅读5分钟

Java 泛型学习——————

泛型的好处

1.编译时,检查添加元素的类型,提高了安全性

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

实例如下:不使用泛型Dog->加入->Object->取出->Dog//放入到ArrayList会转到Object,取出还需要转到Dog

import java.util.ArrayList;

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

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

     public int getAge() {
         return age;
     }

     public void setAge(int age) {
         this.age = age;
     }
}
class Generic{
    public static void main(String[] args) {
         ArrayList list= new ArrayList();
         list.add(new Dog("旺财",12));
         list.add(new Dog("发财",1));
        list.add(new Dog("小黄",13));

        //增加一只猫,这里编译时不会报错,但运行会报错
         list.add(new Cat("招财猫",23));
       //增强for循环
        for(Object o:list){
            //向下转型Object--》Dog
            Dog dog=(Dog)o;
            System.out.println(dog.getName()+"-"+dog.getAge());
        }


    }
}

使用了泛型

Dog->Dog->Dog,放进去和取出时都不需要类型转换

实例如下,我们修改 Genreic类代码

、、、、、、、这上面还是Cat和Dog类不变
public class Genreic {
    public static void main(String[] args) {
        ArrayList<Dog> list=new ArrayList<Dog>();
        list.add(new Dog("招财狗",23));
        list.add(new Dog("财狗",25));
            
        //  泛型约束,编译器检测,不满足要求会报错
        // list.add(new Cat("猫",23));

        //便利时可以直接取出Dog类型,而不是Object类型,不用向下转型
        for (Dog o:list){
            System.out.println(o.getName()+"-"+o.getAge());
        }
    }
}

泛型介绍

泛型又称参数化类型,(泛型可以理解为一种可以表示数据类型的一种数据类型),是jdk5.0出现的新特性,解决数据类型安全的问题

注意1 泛型指向的数据类型要求是引用数据类型而不是基本数据类型

       ArrayList<Integer> list1=new ArrayList<Integer>();
     //    ArrayList<int> list2=new ArrayList<int>();

注意二:在给泛型指定具体类型后,可以给类型出入它或者他的子类类型

public class Test {
 
    pig<A>pig=new pig<A>(new A());
     //在给泛型指定具体类型后,可以给类型传入它或者他的子类类型
    pig<A>pig2=new pig<A>(new B());
}

class A{};
class B extends A{};

class pig<E>{
    E e;

    public pig(E e) {
        this.e = e;
    }
}

注意三:如果没有给泛型指定数据类型,编译器默认是Object

//如果这样写,默认泛型是Object,两者等价
   ArrayList list=new ArrayList();
   ArrayList<Object>list2=new ArrayList<>();

实战题目

截屏2021-05-16 上午6.05.20.png

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
 class Eployee {
   private String name;
   private  int sal;
   private Mydata birthdy;

    public Eployee() {
    }

    public Eployee(String name, int sal, Mydata birthdy) {
        this.name = name;
        this.sal = sal;
        this.birthdy = birthdy;
    }

    public String getName() {
        return name;
    }

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

    public int getSal() {
        return sal;
    }

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

    public Mydata getBirthdy() {
        return birthdy;
    }

    public void setBirthdy(Mydata birthdy) {
        this.birthdy = birthdy;
    }

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




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

    public Mydata() {
    }

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

    public int getMonth() {
        return month;
    }

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

    public int getYear() {
        return year;
    }

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

    public int getDay() {
        return day;
    }

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

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

    @Override
    public int compareTo(Mydata o) {
        int yearminth=year- o.getYear();
        if (yearminth!=0){
            return yearminth;
        }
        //比较minth
        int monthminth=month-o.getMonth();
        if (monthminth!=0) {
            return monthminth;
        }
        return day-o.getDay();

    }
}

 class  Test{
    public static void main(String[] args) {
        ArrayList<Eployee>list=new ArrayList<>();
        list.add(new Eployee("tom",30000,new Mydata(2000,11,27)));;
        list.add(new Eployee("jact",12000,new Mydata(2001,12,12)));;
        list.add(new Eployee("tom",60000,new Mydata(2000,10,27)));;
        System.out.println("eplyees"+list);
        System.out.println("-----------------排序后------------------");

        list.sort(new Comparator<Eployee>() {
            @Override
            public int compare(Eployee o1, Eployee o2) {
                //先对传入的实参进行验证
                if (!(o1 instanceof Eployee && o2 instanceof Eployee)) {
                    System.out.println("类型不匹配");
                    return 0;
                }
                //如果类型相同,就比较姓名
                int i = o1.getName().compareTo(o2.getName());
                if (i != 0) {
                    return i;
                }
                //比较生日
                return  o1.getBirthdy().compareTo(o2.getBirthdy());
            }
        });
        System.out.println(list);
    }
}

自定义泛型

基本语法

class 类名<T,R..>{//可以有多个
    成员.......
}

普通成员可以使用泛型

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

class Targer<T,R,M>{
    String name;
    T t;
    R r;
    M m;
   //因为数组在new 不能确定R数据类型,无法知道开辟多大空间
   // R[]rs =new R[8];
  
    //但是可以定义
    R[]rs2;
}

静态方法中不能使用类的泛型

class Targer<T,R,M>{
    String name;
    T t;
    R r;
    M m;
 //因为静态和类相关,在类加载的时候对象还没有创建
  //如果静态方法和属性使用了泛型,JVM无法完成初始化
    static T t;
    public Static void m1 (T t){

    }
}

自定义泛型接口

基本语法

在接口中静态成员也不能使用泛型

泛型接口的类型,在继承接口或者实现接口实现

 interface 接口名<T,R..>{ }
package com.taoge.con;

interface Test2<U,R> {
    int n=10;
    //在接口中属性也是静态属性
   // U name; 错误

    //普通方法也可以使用接口泛型
    R get(U u );
    void hi(U u,R r);

    //在jdk8中,可以在接口中使用默认方法,也可以使用泛型
    default R meth(U u){
        return null;
    }
}
//在继承接口时实现接口的类型
interface Test3 extends Test2<String,Double>{}


//但我们实现Test3接口时,因为在Test2中指定了U为String,R为Double
//在实现方法时,自动替代
class person implements Test3{

    @Override
    public Double get(String s) {
        return null;
    }

    @Override
    public void hi(String s, Double aDouble) {

    }
}

自定义泛型方法

基本语法

修饰符<T,R..>返回类型 方法名(形参列表){
  
}

泛型方法可以定义在普通类中也可以定义在泛型类中

注意 反正泛型方法带个<T,R..>这个东西

public void eat(T t){}//这个不是泛型方法,只是使用了泛型

public <T,R> void eat(T t,R r){}//这个是

泛型的继承和通配符

泛型不具备继承性

package com.taoge.con;

import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion;

import java.util.ArrayList;

public class Test {
    //可以多态
    Object o=new String("xx");
    //错误
    // ArrayList<Object>list=new ArrayList<String>();
}


通配符

起到一种约束的作用

<?>:支持任意泛型类型
<? extends A>支出A类以及A的子类,规定了泛型的上限
<? super A>:支持A类及父类,不限于直接父类,规定了泛型下限

实战

截屏2021-05-16 上午6.03.36.png

package com.taoge.con;

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

public class DAO<T> {
   private Map<String,T> map=new HashMap<>();
  //从map中获取id对象
    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> lsit(){
        //创建ArrList
        ArrayList<T> list = new ArrayList<>();
        //便利Map
        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 void sava(String id,T entity){
      map.put(id,entity);
    }
}

class Uesr{
    private int id;
    private int age;
    private String name;

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

//测试
class Test{
    public static void main(String[] args) {


    }
}
@Test
public void testlist(){
    DAO<Uesr>dao=new DAO<>();
    dao.sava("111",new Uesr(1,19,"jack"));
    dao.sava("222",new Uesr(2,12,"wewe"));

    List<Uesr>list= dao.lsit();
    System.out.println("list"+list);
    //剩下不测了
}