Java foundation 28-generics

Table of contents

1. Introduction to Generics

2. Generic Introduction

3. Generic syntax and application

1. Generic syntax

2. Generic case

3. Generic usage details

4. Generic classic exercises

4. Custom Generics

1. Custom generic class

Case 1

2. Custom generic interface

3. Custom generic methods

Custom generic method practice

5. Generic inheritance and wildcards

6. Generic Homework (Exercise)


1. Introduction to Generics

1. Use the traditional way

package com.feiyang.basic14;

import com.feiyang.static1.main;

import java.util.ArrayList;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:泛型
 */
public class Generic01 {
    public static void main(String[] args) {

        //使用传统方式解决
        ArrayList arrayList = new ArrayList();
        arrayList.add(new Dog("大黄",5));
        arrayList.add(new Dog("黑子",6));
        arrayList.add(new Dog("小花",2));

        //加入不小心添加了只猫
        arrayList.add(new Cat("咪咪",3));

        for (Object o : arrayList) {
            //向下转型(影响效率)
            Dog o1 = (Dog) o;
            System.out.println(o1.getName() + "-" + o1.getAge());
        }
    }
}

class Dog{
    private String name;
    private Integer age;

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

class Cat{
    private String name;
    private Integer age;

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

printout:

Rhubarb-5

Sunspot-6

Little flower-2

Exception in thread "main" java.lang.ClassCastException: com.feiyang.basic14.Cat cannot be cast to com.feiyang.basic14.Dog

at com.feiyang.basic14.Generic01.main(Generic01.java:22)

2. Use generics to solve the above problems

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:泛型
 */
public class Generic02 {
    public static void main(String[] args) {

        //使用传统方式解决
        ArrayList<Dog> arrayList = new ArrayList<Dog>();
        arrayList.add(new Dog("大黄",5));
        arrayList.add(new Dog("黑子",6));
        arrayList.add(new Dog("小花",2));

        //加入不小心添加了只猫
        //arrayList.add(new Cat("咪咪",3));

//        for (Object o : arrayList) {
//            //向下转型(影响效率)
//            Dog o1 = (Dog) o;
//            System.out.println(o1.getName() + "-" + o1.getAge());
//        }

        for (Dog o : arrayList) {
            System.out.println(o.getName() + "-" + o.getAge());
        }
    }
}

printout:

Rhubarb-5

Sunspot-6

Little flower-2

2. Generic Introduction

package com.feiyang.basic14;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:泛型介绍
 */
public class Generic03 {
    public static void main(String[] args) {

    }
}

class Person<E>{
    //属性类型泛型化
    E s;//E表示s的数据类型,该数据类型在定义Person对象的时候指定,即在编译时就确定E是什么类型。

    //参数类型泛型化
    public Person(E s) {
        this.s = s;
    }

    //返回值类型泛型化
    public E func(){
        return s;
    }
}

3. Generic syntax and application

1. Generic syntax

2. Generic case

package com.feiyang.basic14;

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

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:泛型应用案例
 */
public class GenericExercise {
    public static void main(String[] args) {
        HashSet<Student> hashSet = new HashSet<>();
        hashSet.add(new Student("tom",35));
        hashSet.add(new Student("jack",16));
        hashSet.add(new Student("feiyang",28));

        for (Student student : hashSet) {
            System.out.println(student.getName() + "-" + student.getAge());
        }

        HashMap<String, Student> hm = new HashMap<>();
        hm.put("tom",new Student("tom",35));
        hm.put("jack",new Student("jack",16));
        hm.put("feiyang",new Student("feiyang",28));
        Set<Map.Entry<String, Student>> entries = hm.entrySet();
        for (Map.Entry<String, Student> entry : entries) {
            System.out.println(entry.getKey() + "-" + entry.getValue());
        }
    }
}

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

printout:

jack-16

tom-35

feiyang-28

tom-Student{name='tom', age=35}

jack-Student{name='jack', age=16}

feiyang-Student{name='feiyang', age=28}

3. Generic usage details

package com.feiyang.basic14;

import java.util.ArrayList;
import java.util.List;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:泛型使用细节
 */
public class GenericDetail {
    public static void main(String[] args) {

        //1.给泛型指定数据类型,要求是引用数据类型,不能是基本数据类型
        ArrayList<Integer> arrayList = new ArrayList<Integer>();//OK
        //ArrayList<int> arrayList2 = new ArrayList<int>();//error

        //2.给泛型指定具体类型后,可以传入该类型或其子类型
        Pig<A> aPig = new Pig<A>(new A());
        aPig.f();

        //Pig<B> bPig = new Pig<A>(new B());//error
        Pig<A> bPig2 = new Pig<A>(new B());//
        bPig2.f();

        //3.泛型的使用
        ArrayList<Integer> list = new ArrayList<Integer>();
        List<Integer> list2 = new ArrayList<Integer>();

        //也可以简写(推荐),编译器会进行类型推断
        ArrayList<Integer> list3 = new ArrayList<>();
        List<Integer> list4 = new ArrayList<>();
        List<Pig> pig = new ArrayList<>();
        
        //如果这样写,泛型默认是Object,
        ArrayList list5 = new ArrayList();//等价与=>ArrayList<Object> arrayList1 = new ArrayList<Object>();

    }
}

class A{}
//class B{}
class B extends A{}
class Pig<E>{
    E e;

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

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

4. Generic classic exercises

package com.feiyang.basic14;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:生日日期类
 */
public class MyDate implements Comparable<MyDate>{
    private int year;
    private int month;
    private int day;

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

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        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;
    }

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


    //把对日期的排序抽取出来放到MyDate类
    @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();
    }
}


package com.feiyang.basic14;

/**
 * @author:程序员飞扬
 * @公众hao:程序员飞扬
 * @description:雇员类
 */
public 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 "Employee{" +
                "name='" + name + '\'' +
                ", sal=" + sal +
                ", birthday=" + birthday +
                '}';
    }
}
package com.feiyang.basic14;

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

/**
 * @author:程序员飞扬
 * @公众hao:程序员飞扬
 * @description:泛型案例
 */
public class GenericExercise02 {
    public static void main(String[] args) {
        ArrayList<Employee> employees = new ArrayList<Employee>();
        employees.add(new Employee("alice",2000.00,new MyDate(1980,10,21)));
        employees.add(new Employee("bob",1800.00,new MyDate(2002,6,18)));
        employees.add(new Employee("alice",3500.00,new MyDate(1980,10,22)));

        employees.sort(new Comparator<Employee>() {
            @Override
            public int compare(Employee o1, Employee o2) {
                int i = o1.getName().compareTo(o2.getName());
                if(i != 0 ){
                    return i;
                }

                int i1 = o1.getBirthday().compareTo(o2.getBirthday());
                return i1;
            }
        });

        //lambda写法
        employees.sort((o1, o2) -> {
            int i = o1.getName().compareTo(o2.getName());
            if(i != 0 ){
                return i;
            }

            int i1 = o1.getBirthday().compareTo(o2.getBirthday());
            return i1;
        });

        employees.forEach(employee -> System.out.println(employee));
    }

}

printout:

Employee{name='alice', sal=2000.0, birthday=MyDate{year=1980, month=10, day=21}}

Employee{name='alice', sal=3500.0, birthday=MyDate{year=1980, month=10, day=22}}

Employee{name='bob', sal=1800.0, birthday=MyDate{year=2002, month=6, day=18}}

4. Custom Generics

1. Custom generic class

package com.feiyang.basic14;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:自定义泛型类
 */
public class CustomGeneric_ {
    public static void main(String[] args) {

    }
}

/**
 * 1.Tiger后面有泛型,所以我们把Tiger成为自定义泛型类
 * 2. T,R,M是泛型的标识类,一般是单个大写字母
 * 3. 泛型标识符可以有多个
 * 4. 普通成员可以使用泛型(属性,方法)
 * 5,使用泛型的数据不能初始化
 * @param <T>
 * @param <R>
 * @param <M>
 */
class Tiger<T, R, M>{
    String name;
    T t; //属性使用泛型
    R r;
    M m;
    //T[] tarr = new T[8]; //不可以,因为数组在 new时不能确定T的类型,所有不能开辟内存空间


    //1. 静态和类相关,在类加载时对象还未创建
    //2. 所以静态方法和静态属性使用了泛型,JVM就无法完成初始化
    //static R r2;
    //public static void m1(M m){
    //
    //}

    public Tiger(String name, T t, R r, M m) { //构造器使用泛型
        this.name = name;
        this.t = t;
        this.r = r;
        this.m = m;
    }
}

Case 1

package com.feiyang.basic14;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:自定义泛型类
 */
public class CustomGeneric_ {
    public static void main(String[] args) {
        Tiger<Double, String, Integer> g = new Tiger<>("john");
        g.setT(10.9);//OK
        //g.setT("yy");//错误,类型不对
        System.out.println(g);
        Tiger g2 = new Tiger("john~~");//OK,默认T=Object,R=Object,M=Object
        g2.setT("yy");//OK,因为此时T=Object,而"yy"=String,是Object的子类
        System.out.println(g2);

    }
}

/**
 * 1.Tiger后面有泛型,所以我们把Tiger成为自定义泛型类
 * 2. T,R,M是泛型的标识类,一般是单个大写字母
 * 3. 泛型标识符可以有多个
 * 4. 普通成员可以使用泛型(属性,方法)
 * 5,使用泛型的数据不能初始化
 * @param <T>
 * @param <R>
 * @param <M>
 */
class Tiger<T, R, M>{
    String name;
    T t; //属性使用泛型
    R r;
    M m;
    //T[] tarr = new T[8]; //不可以,因为数组在 new时不能确定T的类型,所有不能开辟内存空间


    //1. 静态和类相关,在类加载时对象还未创建
    //2. 所以静态方法和静态属性使用了泛型,JVM就无法完成初始化
    //static R r2;
    //public static void m1(M m){
    //
    //}

    public Tiger(String name, T t, R r, M m) { //构造器使用泛型
        this.name = name;
        this.t = t;
        this.r = r;
        this.m = m;
    }

    public Tiger(String john) {
    }

    public String getName() {
        return name;
    }

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

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

    public R getR() {
        return r;
    }

    public void setR(R r) {
        this.r = r;
    }

    public M getM() {
        return m;
    }

    public void setM(M m) {
        this.m = m;
    }

    @Override
    public String toString() {
        return "Tiger{" +
                "name='" + name + '\'' +
                ", t=" + t +
                ", r=" + r +
                ", m=" + m +
                '}';
    }
}

output:

Tiger{name='null', t=10.9, r=null, m=null}

Tiger{name='null', t=yy, r=null, m=null}

2. Custom generic interface

package com.feiyang.basic14;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class CustomInterfaceGeneric_ {
}

interface IUsb<U, R>{
    //普通方法中可以使用接口泛型
    R get(U u);

    void hi(R r);

    void run(R r1,R r2,U u1,U u2);

    //在jdk8中,可以在接口中使用默认方法,也是可以使用泛型
    default R method(U u){
        return null;
    }

    /**
     * 泛型接口使用说明:
     * 1. 接口中,静态成员不能使用泛型
     */
    int n = 10;
    //U name;//静态成员不能使用泛型

}

//在继承接口时,指定泛型接口的类型
interface IA extends IUsb<String,Double>{

}

//当我们继承IA接口时,因为IA接口继承IUsb接口时指定了U为String,R为Double,
//所以重写IUsb接口的方法时,用String替换了U,用Double替换了R。
class AA implements IA{

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

    @Override
    public void hi(Double aDouble) {

    }

    @Override
    public void run(Double r1, Double r2, String u1, String u2) {

    }
}

//在实现接口时直接指定泛型接口的类型
//给U指定Integer,给R指定Float
//所以当我们实现IUsb接口时,会用Integer替换U,用Float替换R
class BB implements IUsb<Integer,Float>{

    @Override
    public Float get(Integer integer) {
        return null;
    }

    @Override
    public void hi(Float aFloat) {

    }

    @Override
    public void run(Float r1, Float r2, Integer u1, Integer u2) {

    }
}

3. Custom generic methods

Custom generic method practice

package com.feiyang.basic14;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class CustomMethodGenericExercise {
    public static void main(String[] args) {
        Apple<String, Integer, Double> apple = new Apple<>();
        apple.fly(10);
        apple.fly(new Dog2());

    }
}

class Dog2{}

class Apple<T,R,M>{
    public <E> void fly(E e){
        System.out.println(e.getClass().getSimpleName());
    }

    //错误,下面的方法并不是泛型方法,只是想使用类声明的泛型,然而类并没有声明泛型U
    //public void eat(U u){}

    //使用了泛型类声明的泛型M
    public void rnn(M m){}
}

output:

Integer

Dog2

5. Generic inheritance and wildcards

package com.feiyang.basic14;

import java.util.ArrayList;
import java.util.List;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class GenericExtends {
    public static void main(String[] args) {
        Object xx = new String("xx");//这样可以

        List list = new ArrayList();//可以,多态的体现
        //List<Object> list0 = new ArrayList<String>();//不可以,泛型不具有继承性

        //举例说明几个方法的使用
        List<Object> list1  = new ArrayList();
        List<String> list2  = new ArrayList();
        List<AAA> list3  = new ArrayList();
        List<BBB> list4  = new ArrayList();
        List<CCC> list5  = new ArrayList();

        //List<?>
        printCollection1(list1);
        printCollection1(list2);
        printCollection1(list3);
        printCollection1(list4);
        printCollection1(list5);

        //List<? extends AAA>
//        printCollection2(list1);//×
//        printCollection2(list2);//×
//        printCollection2(list3);//√
//        printCollection2(list4);//√
//        printCollection2(list5);//√

        //List<? super CCC>
//        printCollection3(list1);//√
//        printCollection3(list2);//×
//        printCollection3(list3);//√
//        printCollection3(list4);//×
//        printCollection3(list5);//×



    }

    //几个方法说明:
    //List<?>表示任意的泛型类型都可以接受
    public static void printCollection1(List<?> c){
        for (Object o : c) {
            System.out.println(o);
        }

    }
    //List<? extends AAA>表示上限,可以接受AAA或AAA的子类
    public static void printCollection2(List<? extends AAA> c){
        for (Object o : c) {
            System.out.println(o);
        }

    }
    //List<? super CCC>表示下限,可以接受AAA类或AAA类的父类
    public static void printCollection3(List<? super AAA> c){
        for (Object o : c) {
            System.out.println(o);
        }

    }
}

class AAA{

}

class BBB extends AAA{

}

class CCC extends BBB{

}

6. Generic Homework (Exercise)

package com.feiyang.basic14;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class User {
    private int id;
    private int age;
    private String name;

    public User() {
    }

    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 "User{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
package com.feiyang.basic14;

import org.junit.jupiter.api.Test;
import java.util.*;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:泛型作业练习
 */
public class HomeWork01 {
    public static void main(String[] args) {

    }

    @Test
    public void testList(){
        DAO<User> dao = new DAO<>();
        dao.save("01",new User(1,10,"tom"));
        dao.save("02",new User(2,15,"rose"));
        dao.save("03",new User(3,18,"jack"));

        //返回所有对象
        List<User> list = dao.list();
        System.out.println(list);

        //更新
        dao.update("03",new User(4,20,"bella"));
        List<User> list2 = dao.list();
        System.out.println(list2);

        //删除
        dao.delete("01");
        List<User> list3 = dao.list();
        System.out.println(list3);

        //根据id获得
        System.out.println("02===" + dao.get("02"));

    }
}

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

    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(get(key));
        }
        return list;
    }

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

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

}

Guess you like

Origin blog.csdn.net/lu_xin5056/article/details/126193147