当前位置: 首页 > news >正文

泛型 和 IO流 和 网络编程

文章目录

  • 🚏 泛型
    • 🚀 泛型的概念
      • 🚬 为什么要使用泛型
    • 🚄 在集合中使用泛型
    • 🚒 自定义泛型结构
      • 🚬 泛型类
        • 🚭 自定义泛型的子类1
        • 🚭 自定义泛型的子类2
      • 🚬 泛型接口
      • 🚬 泛型方法
      • 🚬 实际开发中使用泛型DAO
    • 🚤 泛型在继承上的体现
    • 🚗 通配符的使用
      • 🚬 有限制条件的通配符的使用

😹 作者: gh-xiaohe
😻 gh-xiaohe的博客
😽 觉得博主文章写的不错的话,希望大家三连(✌关注,✌点赞,✌评论),多多支持一下!!!

在这里插入图片描述

🚏 泛型

    泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换

🚀 泛型的概念

    所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实际的类型参数,也称为类型实参)。

🚬 为什么要使用泛型

问题一:类型不安全

问题二:强转时,可能出现ClassCastException

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sdj08qTw-1664007082542)(泛型和IO流.assets/image-20220924153614007.png)]

🚄 在集合中使用泛型

  • 总结:
  • ① 集合接口或集合类在jdk5.0时都修改为带泛型的结构。
  • ② 在实例化集合类时,可以指明具体的泛型类型
  • ③ 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的泛型类型。
    • 比如:add(E e) —>实例化以后:add(Integer e)
  • ④ 注意点:泛型的类型必须是类,不能是基本数据类型。需要使用到基本数据类型的位置,拿包装类替换
  • ⑤ 如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型

未使用泛型

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

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

            System.out.println(stuScore);
        }
    }

在集合中使用泛型的情况:以ArrayList为例

    //在集合中使用泛型的情况:以ArrayList为例
    @Test
    public void test2(){
    	//问什么不能写int:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换
       ArrayList<Integer> list =  new ArrayList<Integer>();

        list.add(78);
        list.add(87);
        list.add(99);
        list.add(65);
        //编译时,就会进行类型检查,保证数据的安全
//        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("Jerry",87);
        map.put("Jack",67);

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

    }

🚒 自定义泛型结构

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

在这里插入图片描述

🚬 泛型类

在这里插入图片描述

public class Order<T> {

    String orderName;
    int orderId;

    //类的内部结构就可以使用类的泛型
    T orderT;

    public Order(){
        
    }

    public Order(String orderName,int orderId,T orderT){
        this.orderName = orderName;
        this.orderId = orderId;
        this.orderT = orderT;
    }
    
    @Override
    public String toString() {
        return "Order{" +
                "orderName='" + orderName + '\'' +
                ", orderId=" + orderId +
                ", orderT=" + orderT +
                '}';
    }
}
@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");

}

🚭 自定义泛型的子类1

    由于子类在继承带泛型的父类时,指明了泛型类型。则实例化子类对象时,不再需要指明泛型。

SubOrder1:不是泛型类

public class SubOrder1 extends Order<Integer> { // SubOrder1:不是泛型类

}

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

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

🚭 自定义泛型的子类2

SubOrder2: 仍然是泛型类

public class SubOrder2<T> extends Order<T> { // SubOrder2<T>:仍然是泛型类

}

	@Test
    public void test2(){
        SubOrder2<String> sub2 = new SubOrder2<>();
        sub2.setOrderT("order2...");
    }

🚬 泛型接口

//1.接口中静态成员也不能使用泛型
//2.泛型接口的类型,在继承接口或者实现接口时确定
interface IUsb<U,R>{
    int n = 10;
    //U name;       //name类型默认为 public static final,所以不能使用

    //普通方法中可以使用接口泛型
    R get(U u);

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

    //在JDK 8中,可以在接口中,使用默认方法
    default R method(U u){
        return null;
    }
}


//实现接口时,指定泛型类型
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) {

    }
}

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

}

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) {

    }
}

🚬 泛型方法

    方法,也可以被泛型化,不管此时定义在其中的类是不是泛型类。 在泛型方法中可以定义泛型参数,此时,参数的类型就是传入数据的类型

泛型方法的格式:

  • [ 访问权限] < 泛型> 型 返回类型 名 方法名([ 泛型标识 称 参数名称]) 抛出的异常
  • 泛型方法,可以声明为静态的。原因:泛型参数是在调用方法时确定的。并非在实例化类时确定

错误写法:

  • public static List copyFromArrayToList(E[] arr){ 编译器会认为有一个类叫E,而不是泛型
public class Order<T> {

// public static List<E> copyFromArrayToList(E[] arr){
// 错误写法:编译器会认为有一个类叫E,而不是泛型
    public static <E>  List<E> copyFromArrayToList(E[] arr){

        ArrayList<E> list = new ArrayList<>();

        for(E e : arr){
            list.add(e);
        }
        return list;

    }

}


    //测试泛型方法
    @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);
    }

🚬 实际开发中使用泛型DAO

DAO:data(base) access object DAO:可以理解为操作数据库的通用操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iZUmIqla-1664024257092)(泛型和IO流.assets/image-20220924170511373.png)]

DAO

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

}

Customer 和 CustomerDAO 测试

public class Customer { //此类对应数据库中的customers表


}

public class CustomerDAO extends DAO<Customer>{//只能操作某一个表的DAO

}

public class Student {
}

public class StudentDAO extends DAO<Student> {//只能操作某一个表的DAO
}


    @Test
    public void test1(){
        CustomerDAO dao1 = new CustomerDAO();

        dao1.add(new Customer());
        List<Customer> list = dao1.getForList(10);//查询多条记录


        StudentDAO dao2 = new StudentDAO();
        Student student = dao2.getIndex(1);//查询一条记录
    }

🚤 泛型在继承上的体现

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

   @Test
   public void test1(){

       // 类层面的展示
       Object obj = null;
       String str = null;

       obj = str; // 子类赋给父类的引用 多态

       // 数组层面
       Object[] arr1 = null;
       String[] arr2 = null;

       arr1 = arr2;        

   }

   @Test
   public void test1(){

       //此时的list1和list2的类型不具有子父类关系
       List<Object> list1 = null;
       List<String> list2 = null;
       
       //编译不通过 
       list1 = list2;  // 错误
       
       // 类似于   错误
       Date date = new Date();
       String str = null;
       
		str = date; // 错误
       /*
       反证法:
       假设list1 = list2;
       list1.add(123);导致混入非String的数据。出错。 所以是错误的
        */

   }

补充:类A是类B的父类,A 是 B 的父类

   @Test
   public void test2(){

       AbstractList<String> list1 = null;
       List<String> list2 = null; //  List interface(接口)
       ArrayList<String> list3 = null; // 继承 AbstractList

       list1 = list3;
       list2 = list3;

       List<String> list4 = new ArrayList<>();

   }

🚗 通配符的使用

通配符:?

  • 类A是类B的父类,G和G是没有关系的,二者共同的父类是:G<?>
    @Test
    public void test3(){
        List<Object> list1 = null;
        List<String> list2 = null;

        List<?> list = null; // 相当于  List<?> 作为 List<Object>、List<String> 的通用父类

        list = list1;
        list = list2;
        //编译通过
        print(list1);
        print(list2);
    }

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

使用通配符结构时

  • 添加(写入):对于List<?>就不能向其内部添加数据,只能添加null(无意义)

  • 获取(读取):允许读取数据,读取的数据类型为Object。

    @Test
    public void test3(){
        
        List<String> list3 = new ArrayList<>();
        list3.add("AA");
        list3.add("BB");
        list3.add("CC");
        
        List<?> list = null; 

        list = list3;
        //添加(写入):对于List<?>就不能向其内部添加数据。
		//list.add(capture of ? e);
//        list.add("DD"); 错误
//        list.add('?'); 错误
        //除了添加null之外。
        list.add(null);

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

    }

🚬 有限制条件的通配符的使用

  • ? extends A: 理解为小于等于
    • G<? extends A> 可以作为G和G的父类,其中B是A的子类
  • ? super A: 理解为大于等于
    • G<? super A> 可以作为G和G的父类,其中B是A的父类
    @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 = list5;

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

        System.out.println("---------------------");
        
        //读取数据:
        list1 = list3;
        Person p = list1.get(0);
        //编译不通过
        //Student s = list1.get(0);

        list2 = list4;
        Object obj = list2.get(0);
        编译不通过
//        Person obj = list2.get(0);

        //写入数据:
        //编译不通过
//        list1.add(new Student()); 子类可以赋给父类 父类不可以赋给子类
//        list1.add(new Person());
//        list1.add(new Object());

        //编译通过
        list2.add(new Person()); //  Person 和 Person的子类能存放 多态
        list2.add(new Student());

}

相关文章:

  • js 复制内容到剪切板
  • redis中的锁,通过UUID防止误删
  • 生命在于折腾——浅谈羊了个羊
  • 微雪树莓派PICO笔记——6. I2C(集成电路总线)
  • 容斥原理
  • RealityCapture摄影测量软件
  • TransBigData:一款基于 Python 的超酷炫交通时空大数据工具包
  • 矩阵理论复习部分——线性代数(1)行列式
  • 3 MyBatis 级联操作
  • Vue项目的部署(服务器)
  • 什么是 Docker 镜像层?
  • 0922 理论知识
  • 信号采集之传感器信号学习笔记
  • CS:APP第九章 虚拟内存
  • Android Tile快捷设置
  • 【Linux系统编程】快速查找errno错误码信息
  • C++入门教程(10):for 语句
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • java第三方包学习之lombok
  • JS笔记四:作用域、变量(函数)提升
  • leetcode388. Longest Absolute File Path
  • npx命令介绍
  • RxJS: 简单入门
  • 订阅Forge Viewer所有的事件
  • 分享几个不错的工具
  • 技术胖1-4季视频复习— (看视频笔记)
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 漂亮刷新控件-iOS
  • 前端面试之CSS3新特性
  • 前端之Sass/Scss实战笔记
  • 如何实现 font-size 的响应式
  • 物联网链路协议
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • Spring第一个helloWorld
  • 进程与线程(三)——进程/线程间通信
  • ###C语言程序设计-----C语言学习(3)#
  • #Spring-boot高级
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (C语言)二分查找 超详细
  • (NSDate) 时间 (time )比较
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (考研湖科大教书匠计算机网络)第一章概述-第五节1:计算机网络体系结构之分层思想和举例
  • (四) Graphivz 颜色选择
  • (五)MySQL的备份及恢复
  • (转)C#调用WebService 基础
  • .naturalWidth 和naturalHeight属性,
  • .NET 5种线程安全集合
  • .net core webapi Startup 注入ConfigurePrimaryHttpMessageHandler
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .net core使用RPC方式进行高效的HTTP服务访问
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .NET Framework 服务实现监控可观测性最佳实践
  • .NET 回调、接口回调、 委托