Java高级编程——泛型

Java高级编程——泛型

目录

Java高级编程——泛型

一、为什么要有泛型

 1.为什么要有泛型(Generic)

 2.泛型的概念

二、在集合中使用泛型

 上代码

三、自定义泛型结构

 1.自定义泛型结构

 2.泛型类、泛型接口

 2.1.泛型类 

 2.2.泛型方法

 上代码

四、泛型在继承上的体现

五、 通配符的使用

 注意点

 有限制的通配符

 上代码

六、泛型应用举例

1.泛型嵌套

2.实验 

2.1 自定义泛型类的使用

2.2 集合中使用泛型


一、为什么要有泛型

1.为什么要有泛型(Generic)

 2.泛型的概念

二、在集合中使用泛型

 上代码

package com.tyl.java;

import org.junit.Test;

import java.util.*;

/**
 * @author tyl 邮箱:tyl202061@gmail.com
 * @Package:com.tyl.java
 * @Project:workidea
 * @Filename: GenericTest
 * @create 2023-06-07 11:52
 *
 * 泛型的使用
 * 1.jdk5.0新增的特性
 *
 * 2.在集合中使用泛型:
 *    总结:
     * 2.1.集合接口或集合类在jdk5.0时都修改为带泛型的结构。
     * 2.2.在实例化集合类时,可以指明具体的泛型类型
     * 2.3.指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的泛型类型
     *        比如:add(E e) --> 实例化以后:add(Integer e)
     * 2.4. 注意点:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,用包装类代替。
     * 2.5. 如果实例化时,没有指明泛型的类型。默认类型为ava.Lang.Object类型。
 *
 * 3.如何自定义泛型结构:泛型类、泛型接口:泛型方法  见:GenericTest1.java
 */
public class GenericTest {
    //在集合中使用泛型之前的情况:
    @Test
    public void test1(){

        ArrayList list = new ArrayList();
        //需求:存放学生的成绩
        list.add(77);
        list.add(88);
        list.add(99);
        list.add(66);

        //问题一:类型不安全
//        list.add("tyl");

        for(Object score : list){
            //问题二:强转时,可能出现CLassCastException
            int stuScore = (Integer) score;

            System.out.println(stuScore);
        }
    }

    //在集合中使用泛型的情况:以ArrayList为例
    @Test
    public void test2(){
        ArrayList<Integer> list = new ArrayList<Integer>();

        list.add(77);
        list.add(99);
        list.add(55);
        list.add(55);
        list.add(66);
        //编译时,就会进行类型检查,保证数据的安全
//        list.add("tom");

        // 方式一:
//        for(Integer score : list){
//            //避免了强转操作
//            int stuScore = score;
//            System.out.println(stuScore);
//        }

        // 方式二:
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()){
            int stuScore = iterator.next();
            System.out.println(stuScore);
        }
    }

    //在集合中使用泛型的情况:以HashMap为例
    @Test
    public void test3(){
//        Map<String, Integer> map = new HashMap<String, Integer>();
        //jdk7新特性:类型推断
        Map<String, Integer> map = new HashMap<>();


        map.put("tom", 87);
        map.put("wc", 87);
        map.put("tyl", 99);

        // 泛型的嵌套
        Set<Map.Entry<String, Integer>> entry = map.entrySet();
        Iterator<Map.Entry<String, Integer>> iterator = entry.iterator();

        while (iterator.hasNext()){
            Map.Entry<String, Integer> e = iterator.next();
            String key = e.getKey();
            Integer value = e.getValue();
            System.out.println(key + "....." + value);
        }
    }
}

三、自定义泛型结构

1.自定义泛型结构

 2.泛型类、泛型接口

2.1.泛型类 

 2.2.泛型方法

 上代码

package com.tyl.java;

import org.junit.Test;

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

/**
 * @author tyl 邮箱:tyl202061@gmail.com
 * @Package:com.tyl.java
 * @Project:workidea
 * @Filename: GenericTest1
 * @create 2023-06-07 18:10
 *
 * 如何自定义泛型结构:泛型类、泛型接口:泛型方法
 *
 * 1.关于自定义泛型类、泛型接口:
 */
public class GenericTest1 {
    @Test
    public void test1(){

        // 如果定义了泛型类,实例化没有指明类的泛型,则认为此,泛型类型为Object类型
        // 要求:如果大家定义了类是带泛型的,建议在实例化时要指明类的泛型。
        Order order = new Order();
        order.setOrderT(123);
        order.setOrderT("abc");

        //建议:实例化时指明类的泛型
        Order<String> order1 = new Order<>("orderAA", 1001, "order:AA");
        order1.setOrderT("AA:jjjjjj");

    }

    @Test
    public void test2(){
        subOrder sub1 = new subOrder();
        // 由于子类在继承带泛型的父类时,指明了泛型类型。则实例化子类对象时,不再需要指明泛型
        sub1.setOrderT(1122);

        subOrder1<String> sub2 = new subOrder1<>();
        sub2.setOrderT("odsdsdsdad.....");

    }

    @Test
    public void test3(){
        ArrayList<String> list1 = null;
        ArrayList<Integer> list2 = new ArrayList<Integer>();
        // 泛型不同的引用不能相互赋值
//        list1 = list2;

    }

    //测试泛型方法
    @Test
    public void test4(){
        Order<String> order = new Order<>();
        Integer[] arr = new Integer[]{1,2,3,4};
        // 泛型方法在调用时,指明泛型参数的类型。
        List<Integer> list = order.copyFromArrayToList(arr);
        System.out.println(list);

    }

}

四、泛型在继承上的体现

五、 通配符的使用

 注意点

 有限制的通配符

 上代码

package com.tyl.java2;

import org.junit.Test;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author tyl 邮箱:tyl202061@gmail.com
 * @Package:com.tyl.java2
 * @Project:workidea
 * @Filename: GenericTest3
 * @create 2023-06-09 13:30
 *
 * 1.泛型在继承方面的体现
 *
 * 2.通配符的使用
 */
public class GenericTest3 {

    /*
    泛型在继承方面的体现

    类A是B的父类,G<A>和G<B>二者不具备子父类关系,二者是并列关系。

    补充:类A是类B的父类,A<G>是B<G>的父类


     */
    @Test
    public void test1(){

        Object obj = null;
        String str = null;
        obj = str;

        Object[] arr1 = null;
        String[] arr2 = null;
        arr1 = arr2;

        List<Object> list1 = null;
        List<String> list2 = new ArrayList<String>();
        //此时的饥ist1和ist2的类型不具有子父类关系
        //编译不通过
//        list1 = list2;

        /*
        反证法:
        假设List1=List2;
        List1.add(123);  导致混入String的数据。出错。
         */

        show1(list1);
        show(list2);

    }

    public void show(List<String> list){

    }

    public void show1(List<Object> list){

    }

    @Test
    public void test2(){

        AbstractList<String> list1 = null;
        List<String> list2 = null;
        ArrayList<String> list3 = null;
        list2 = list3;
        list1 = list3;

        List<Object> list4 = new ArrayList<>();
    }

    /*
    2.通配符的使用
      通配符:?
      类A是都的父类,G<A>和G<B>是没有关系的,二者共同的父类是:G<?>
     */
    @Test
    public void test3(){
        List<Object> list1 = null;
        List<String> list2 = null;

        List<?> list = null;

//        print(list1);
//        print(list2);

        ArrayList<String> list3 = new ArrayList<>();
        list3.add("aa");
        list3.add("bb");
        list3.add("cc");
        list = list3;

        //添加(写入):对于List<?>就不能向其内部添加数据。
        //除了添加nuLL之外。
//        list.add("DD");
//        list.add("?");
        list.add(null);

        // 获取(读取):允许读取数据,读取的数据类型为Object。
        Object o = list.get(0);
        System.out.println(o);

//        print(list);

    }

    public void print(List<?> list){
        Iterator<?> iterator = list.iterator();
        while (iterator.hasNext()){
            Object obj = iterator.next();
            System.out.println(obj);
        }
    }

    /*
    3.有限制的通配符
    ? extends A: G<?extends A>可以作为G<A>和G<B>的父类,其中B是A的子类

    ? super A: G<? super A>可以作为G<A>和G<B>的父类,其中B是A的父类
     */
    @Test
    public void test4(){
        List<? extends Person> list1 = null;
        List<? super Person> list2 = null;

        List<Student> list3 = new ArrayList<>();
        List<Person> list4 = new ArrayList<>();
        List<Object> list5 = new ArrayList<>();

        list1 = list3;
        list1 = list4;
//        list1 = list5;

//        list2 = list3;
        list2 = list4;
        list2 = list5;

        //读取数据,
        list1 = list3;
        list1 = list4;
        Person p1 = list1.get(0);

        list2 = list4;
        Object obj = list2.get(0);

        //写入数据
//        list1.add(new Student());

        list2.add(new Person());
        list2.add(new Student());


    }

}

六、泛型应用举例

1.泛型嵌套

2.实验 

2.1 自定义泛型类的使用

package com.tyl.exer1;

import java.util.*;

/**
 * @author tyl 邮箱:tyl202061@gmail.com
 * @Package:com.tyl.exer1
 * @Project:workidea
 * @Filename: DAO
 * @create 2023-06-12 17:43
 *
 * 定义个泛型类 DAO<T>,在其中定义一个 Map 成员变量,Map 的键为 String 类型,值为 T 类型。
 * 分别创建以下方法:
     * public void save(String id,T entity): 保存 T 类型的对象到 Map 成员变量中
     * public T get(String id):从 map 中获取 id 对应的对象
     * public void update(String id,T entity):替换 map 中 key 为 id 的内容,改为 entity 对象
     * public List<T> list():返回 map 中存放的所有 T 对象
     * public void delete(String id):删除指定 id 对象
 */
public class DAO<T> {
    private Map<String, T> map = new HashMap<>();

    //保存 T 类型的对象到 Map 成员变量中
    public void save(String id, T entity){
        map.put(id,entity);
    }

    // 从 map 中获取 id 对应的对象
    public T get(String id){
       return map.get(id);
    }

    //替换 map 中 key 为 id 的内容, 改为 entity 对象
    public void update(String id,T entity){
        if(map.containsKey(id)){
            map.put(id,entity);
        }
    }

    // 返回 map 中存放的所有 T 对象
    public List<T> list(){
        // 错误的
//        Collection<T> values = map.values();
//        return (List<T>) values;
        //正确的
        ArrayList<T> list = new ArrayList<>();
        Collection<T> values = map.values();
        for (T t : values){
            list.add(t);
        }
        return list;
    }

    // 删除指定 id 对象
    public void delete(String id){
        map.remove(id);
    }

}
package com.tyl.exer1;

import java.util.Objects;

/**
 * @author tyl 邮箱:tyl202061@gmail.com
 * @Package:com.tyl.exer1
 * @Project:workidea
 * @Filename: User
 * @create 2023-06-12 17:57
 *
 * 定义一个 User 类:
 * 该类包含:private 成员变量(int 类型) id,age;(String 类型)name。
 */
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 + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        User user = (User) o;

        if (id != user.id) return false;
        if (age != user.age) return false;
        return Objects.equals(name, user.name);
    }

    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result + age;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        return result;
    }
}
package com.tyl.exer1;

import java.util.List;

/**
 * @author tyl 邮箱:tyl202061@gmail.com
 * @Package:com.tyl.exer1
 * @Project:workidea
 * @Filename: DAOTest
 * @create 2023-06-12 17:59
 *
 * 定义一个测试类:
 * 创建 DAO类的对象, 分别调用其 save、get、update、list、delete 方法来操作 User 对象,
 * 使用 Junit 单元测试类进行测试。
 */
public class DAOTest {
    public static void main(String[] args) {
        DAO<User> dao = new DAO<>();

        dao.save("1001", new User(1001, 22, "tyl"));
        dao.save("1002", new User(1002, 18, "wc"));
        dao.save("1003", new User(1003, 21, "aaa"));

        dao.update("1003",new User(1003, 30, "ccc"));

        dao.delete("1003");

        List<User> list = dao.list();
//        System.out.println(list);
        list.forEach(System.out::println);



    }
}

2.2 集合中使用泛型

package com.tyl.exer;

/**
 * @author tyl 邮箱:tyl202061@gmail.com
 * @Package:com.tyl.exer
 * @Project:workidea
 * @Filename: Employee
 * @create 2023-05-31 22:48
 *
 * 该类包含:private 成员变量 name,age,birthday,其中 birthday 为MyDate 类的对象;
 * 并为每一个属性定义 getter, setter 方法;
 * 并重写 toString 方法输出 name, age, birthday
 */
public class Employee implements Comparable<Employee>{
    private String name;
    private int age;
    private MyDate birthday;

    public Employee() {
    }

    public Employee(String name, int age, MyDate birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

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

    public MyDate getBirthday() {
        return birthday;
    }

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

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

    @Override
    public int compareTo(Employee o) {
        return this.name.compareTo(o.name);
    }

    // 没有指明泛型时的写法
    //1). 使 Employee 实现 Comparable 接口,并按 name 排序
//    @Override
//    public int compareTo(Object o) {
//        if(o instanceof Employee){
//            Employee e = (Employee) o;
//            return this.name.compareTo(e.name);
//        }
        return 0;
//        throw new RuntimeException("输入的数据类型不一致");
//    }
}
package com.tyl.exer;

/**
 * @author tyl 邮箱:tyl202061@gmail.com
 * @Package:com.tyl.exer
 * @Project:workidea
 * @Filename: MyDate
 * @create 2023-05-31 22:48
 *
 * MyDate 类包含:
 * private 成员变量 year,month,day;并为每一个属性定义 getter, setter
 * 方法;
 */
public class MyDate implements Comparable<MyDate>{
    private int year;
    private int monthr;
    private int day;

    public MyDate() {
    }

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

    public int getYear() {
        return year;
    }

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

    public int getMonthr() {
        return monthr;
    }

    public void setMonthr(int monthr) {
        this.monthr = monthr;
    }

    public int getDay() {
        return day;
    }

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

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

//    @Override
//    public int compareTo(Object o) {
//        if(o instanceof MyDate){
//            MyDate m = (MyDate) o;
//
//            //年
//            int minusYear = this.getYear() - m.getYear();
//            if(minusYear != 0){
//                return minusYear;
//            }
//
//            //月
//            int minusMonth = this.getMonthr() - m.getMonthr();
//            if(minusMonth != 0){
//                return minusMonth;
//            }
//
//            //日
//            return this.getDay() - m.getDay();
//        }
        return 0;
//        throw new RuntimeException("输入的数据类型不一致");
//    }

    @Override
    public int compareTo(MyDate m) {
        //年
        int minusYear = this.getYear() - m.getYear();
        if(minusYear != 0){
            return minusYear;
        }

        //月
        int minusMonth = this.getMonthr() - m.getMonthr();
        if(minusMonth != 0){
            return minusMonth;
        }

        //日
        return this.getDay() - m.getDay();
    }
}
package com.tyl.exer;

import org.junit.Test;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

/**
 * @author tyl 邮箱:tyl202061@gmail.com
 * @Package:com.tyl.exer
 * @Project:workidea
 * @Filename: EmployeeTest
 * @create 2023-05-31 22:49
 * <p>
 * 创建该类的 5个对象,并把这些对象放入 TreeSet 集合中(下一章:TreeSet 需使用泛型来定义)
 * 分别按以下两种方式对集合中的元素进行排序,并遍历输出:
 * 1). 使 Employee 实现 Comparable 接口,并按 name 排序
 * 2). 创建 TreeSet 时传入 Comparator 对象,按生日日期的先后排序。
 */
public class EmployeeTest {

    // 按生日日期的先后排序。
    @Test
    public void test2() {
        TreeSet<Employee> set = new TreeSet<>(new Comparator<Employee>() {
            @Override
            public int compare(Employee o1, Employee o2) {
                MyDate b1 = o1.getBirthday();
                MyDate b2 = o2.getBirthday();
                //方式二:
                return b1.compareTo(b2);
            }
        });

        Employee e1 = new Employee("liudehua", 55, new MyDate(1995, 5, 4));
        Employee e2 = new Employee("zahngxueyuo", 43, new MyDate(1965, 5, 4));
        Employee e3 = new Employee("guofucheng", 44, new MyDate(1965, 5, 9));
        Employee e4 = new Employee("liming", 51, new MyDate(1978, 8, 12));
        Employee e5 = new Employee("liangcahowei", 21, new MyDate(1955, 12, 4));

        set.add(e1);
        set.add(e2);
        set.add(e3);
        set.add(e4);
        set.add(e5);

        Iterator<Employee> iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

    }

    //问题一:使用自然排序
    @Test
    public void test1() {
        TreeSet<Employee> set = new TreeSet<>();

        Employee e1 = new Employee("liudehua", 55, new MyDate(1995, 5, 4));
        Employee e2 = new Employee("zahngxueyuo", 43, new MyDate(1965, 5, 4));
        Employee e3 = new Employee("guofucheng", 44, new MyDate(1965, 5, 9));
        Employee e4 = new Employee("liming", 51, new MyDate(1978, 8, 12));
        Employee e5 = new Employee("liangcahowei", 21, new MyDate(1955, 12, 4));

        set.add(e1);
        set.add(e2);
        set.add(e3);
        set.add(e4);
        set.add(e5);

        Iterator<Employee> iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }


}

听得听迷糊,需要在以后的学习中反复练习才能体会到精髓!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值