Java泛型

文章目录

提示:以下是本篇文章正文内容,下面案例可供参考

一、泛型概念

所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。

这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时) 确定 (即传入实际的类型参数,也称为类型实参)

二、泛型的使用

1. 泛型的使用

  • 在集合中使用泛型
  • 总结:
  • 1.集合接口或集合类在jdk5.0时都能修改为带泛型的结构
  • 2.在实例化集合类时,可以指明具体的泛型类型
  • 3.指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(属性、方法、构造器)使用到类的泛型的位置,都指定为实例化的泛型类型
  • 比如:add(E e) --->实例化以后:add(Interger e)
  • 4.注意点:泛型的类型必须是类,不能是基本数据类型,需要基本数据类型的地方,用包装类
  • 5.如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型
cpp 复制代码
package com.tyust.edu;

import org.junit.Test;

import java.util.*;

/**
 * 泛型的使用
 * 在集合中使用泛型
 *
 * 总结:
 * 1.集合接口或集合类在jdk5.0时都能修改为带泛型的结构
 * 2.在实例化集合类时,可以指明具体的泛型类型
 * 3.指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(属性、方法、构造器)使用到类的泛型的位置,都指定为实例化的泛型类型
 * 比如:add(E e)  --->实例化以后:add(Interger e)
 * 4.注意点:泛型的类型必须是类,不能是基本数据类型,需要基本数据类型的地方,用包装类
 * 5.如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型
 *
 *
 *
 * 如何自定义泛型结构:泛型类、泛型接口、泛型方法
 * @author YML TYUST-XDU 2019-2026
 * @create 2023-10-13 8:43
 */
public class GenericTest {

    //在集合中使用泛型之前的情况
    @Test
    public void test1(){
        ArrayList list = new ArrayList();
        //需求:存放学生的成绩
        list.add(78);
        list.add(78);
        list.add(78);
        list.add(78);
        //问题一:类型不安全
        list.add("Tom");

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

            System.out.println(stuScore);
        }
    }

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

        list.add(89);
        list.add(89);
        list.add(89);
        list.add(89);

        //编译时,就会进行类型检查,保证数据的安全
//        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>();

        map.put("Tom",87);
        map.put("Mary",100);
        map.put("Java",97);

//        map.put(123,abx);
        //泛型的嵌套
        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);
        }


    }


}

2.如何自定义泛型结构:泛型类、泛型接口、泛型方法

cpp 复制代码
package com.tyust.edu;


import org.junit.Test;

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

/**
 *  如何自定义泛型结构:泛型类、泛型接口、泛型方法
 *1.关于自定义泛型类、泛型接口
 *
 * @author YML TYUST-XDU 2019-2026
 * @create 2023-10-13 9:23
 */
public class GenericTest1 {


    @Test
    public void test1(){
        //如果定义了泛型类,实例化没有指明类的泛型,则认为
        //此泛型类型为Object类型
        Order order = new Order();
        order.setOrderT(123);
        order.setOrderT("ABC");
        //建议:实例化时指明类的泛型
        Order<String > order1 = new Order<String>("orderAA",1001,"Order:AA");
        order1.setOrderT("AA:hello");

    }

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

        SubOrder1<String >sub2 = new SubOrder1<>();
        sub2.setOrderT("order2...");


    }

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


    }

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

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

/**
 * @author YML TYUST-XDU 2019-2026
 * @create 2023-10-13 9:27
 */
public class SubOrder extends Order<Integer> {//SubOrder  不是泛型类
    public static  <E> List<E> copyFromArryToList(E[] arr){
        ArrayList<E> list = new ArrayList<>();
        for(E e:list){
            list.add(e);
        }
        return list;
    }
}
cpp 复制代码
package com.tyust.edu;

/**
 * @author YML TYUST-XDU 2019-2026
 * @create 2023-10-13 9:29
 */
public class SubOrder1<T> extends Order<T> {//SubOrder1<T>  仍然是泛型类
}

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

cpp 复制代码
package com.tyust.edu;


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

/**
 * @author YML TYUST-XDU 2019-2026
 * @create 2023-10-13 9:18
 */
public class Order<T> {
    String orderName;
    int orderId;
    T orderT;

    public Order(){
        //编译不通过
//        T[] arr = new T[10];
        T[]arr = (T[])new Object[10];
    }

    public Order(String orderName,int orderId,T orderT){
        this.orderName = orderName;
        this.orderId = orderId;
        this.orderT = orderT;
    }

    public T getOrderT(){
        return this.orderT;
    }

    public void setOrderT( T orderT){
        this.orderT = orderT;
    }

    //静态方法中不能使用类的泛型
//    public static void show(T orderT){
//        System.out.println(orderT);
//    }

    //泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系
    //换句话说,泛型方法所属的类是不是泛型类都没有关系
    //泛型方法,可以声明为静态的。原因:泛型参数在调用方法时确定的,并不是在实例化类时确定
    public static  <E> List<E> copyFromArryToList(E[] arr){
        ArrayList<E> list = new ArrayList<>();
        for(E e:list){
            list.add(e);
        }
        return list;
    }
}

三、自定义泛型类例举

cpp 复制代码
package com.tyust.edu;

import java.util.List;

/**
 * @author YML TYUST-XDU 2019-2026
 * @create 2023-10-13 9:55
 */
public class DAO<T> { //表的共性操作DAO

    //增删改查
    public  void add(T t){

    }
    public  boolean remove(int index){
        return false;
    }
    public void update(int index,T t){

    }
    public  T getIndex(int index){
        return null;
    }
    public List<T> getForList(int index){
        return null;
    }
    //泛型方法
    //举例:获取表中一共有多少条记录
    public  <E> E getValue(){
        return null;
    }
}
cpp 复制代码
package com.tyust.edu;

/**
 * @author YML TYUST-XDU 2019-2026
 * @create 2023-10-13 9:58
 */
public class Customer {  //此类对应数据库中的customer表
}
cpp 复制代码
package com.tyust.edu;

/**
 * @author YML TYUST-XDU 2019-2026
 * @create 2023-10-13 9:59
 */
public class CustomerDAO extends DAO<Customer>{  //只能操作某一个表的DAO
}
cpp 复制代码
package com.tyust.edu;

import org.junit.Test;

import java.util.List;

/**
 * @author YML TYUST-XDU 2019-2026
 * @create 2023-10-13 10:01
 */
public class DAOTest {
    @Test
    public  void test1(){
        CustomerDAO dao1 = new CustomerDAO();
        dao1.add(new Customer());
        List<Customer> list = dao1.getForList(10);
    }
}

四、泛型在继承方面的体现

1.泛型在继承方面的体现

复制代码
类A是类B的父类,G<A>和G<B>不具备子父类关系,二者是并列关系
补充:类A是类B的父类,A<G>是B<G>的父类
cpp 复制代码
@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 = null;
        //此时list1和list2不具备子父类关系
//        list1 = list2;

        //编译不通过
//        Date date = new Date();
//        str = date;




    }

    public void show(List<Object> list){

    }
    @Test
    public void test2(){
        AbstractList<String> list1 = null;
        List<String >list2 = null;
        ArrayList<String > list3 = null;
        list1 = list3;
        list2 = list3;
        List<String>list4 = new ArrayList<>();
    }

2.通配符的使用

通配符:?
类A是类B的父类,G <//A> 和G <//B> 是没有关系的,二者共同的父类是G<?>

cpp 复制代码
@Test
    public void test3(){
        List<Object> list1 = null;
        List<String >list2 = null;
        List<?>list = null;
        list = list1;
        list = list2;
        print(list1);
        print(list2);

        List <String >list3 = new ArrayList<>();
        list3.add("AA");
        list3.add("BB");
        list3.add("CC");
        list = list3;

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

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

    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的父类

cpp 复制代码
@Test
    public void test4(){
        List<? extends Person>list1 = null;
        List<? super Person>list2 = null;
        List<Student>list3 = new ArrayList<Student>();
        List<Person>list4 = new ArrayList<Person>();
        List<Object>list5 = new ArrayList<Object>();
        list1 = list3;
        list1 = list4;


        //读取数据
        list1 = list3;
        Person p = list1.get(0);

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


    }
相关推荐
juniperhan6 分钟前
Flink 系列第21篇:Flink SQL 函数与 UDF 全解读:类型推导、开发要点与 Module 扩展
java·大数据·数据仓库·分布式·sql·flink
ID_180079054738 分钟前
Python 实现亚马逊商品详情 API 数据准确性校验(极简可用 + JSON 参考)
java·python·json
c++之路28 分钟前
C++23概述
java·c++·c++23
专注API从业者1 小时前
Open Claw 京东商品监控选品实战:一键抓取、实时监控、高效选品
java·服务器·数据库
摇滚侠2 小时前
DBeaver 导入数据库 导入 SQL 文件 MySQL 备份恢复
java·数据库·mysql
keep one's resolveY2 小时前
SpringBoot实现重试机制的四种方案
java·spring boot·后端
天空属于哈夫克33 小时前
企业微信API常见的错误和解决方案
java·数据库·企业微信
摇滚侠3 小时前
VMvare 虚拟机 Oracle19c 安装步骤,远程连接 Oracle19c,百度网盘安装包
java·oracle
梁萌3 小时前
idea报错找不到XX包的解决方法
java·intellij-idea·启动报错·缺少包
Agent产品评测局4 小时前
生产排期与MES/ERP系统打通,实操方法详解 —— 2026企业级智能体自动化选型与实战指南
java·运维·人工智能·ai·chatgpt·自动化