当前位置:

首页 > 编程开发 > Java泛型与包装类实例分析

Java泛型与包装类实例分析

1、什么是泛型泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。先看以下的例子:我们以前学过的数组,只能存放指定类型的元素。如:int[]array=newint[10];String[]array=newString[10];而Object类是所有类的父类,那么我们是否可以创建Obj数组呢?classMyarray{publicObject[]array=newObject[10];publicvoidsetVal(intpos,Objectval)

本文目录

    1、什么是泛型

    泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。

    先看以下的例子:

    我们以前学过的数组,只能存放指定类型的元素。如:int[] array=new int[10];String[] array=new String[10];而Object类是所有类的父类,那么我们是否可以创建Obj数组呢?

    class Myarray{
        public Object[] array=new Object[10];
        public void setVal(int pos,Object val){
            this.array[pos]=val;
        }
        public Object getPos(int pos){
            return this.array[pos];
        }
    }
    public class TestDemo{
        public static void main(String[] args) {
            Myarray myarray=new Myarray();
            myarray.setVal(1,0);
            myarray.setVal(2,"shduie");//字符串也可以存放
            String ret=(String)myarray.getPos(2);//虽然我们知道它是字符串类型,但是还是要强制类型转换
            System.out.println(ret);
        }
    }

    以上代码实现后,我们发现:

    • 任何类型的数据都能存放

    • 2号下标本来就是字符串,但是必须进行强制类型转换

    以此引出泛型,泛型的目的就是:指定当前的容器要持有什么类型的对象,让编译器自己去检查。

    2、泛型的语法

    class 泛型类名称< 类型形参列表>{

      //这里可以使用类型参数

    }

    泛型的使用:

    泛型类<类型实参> 变量名=new 泛型类<类型实参>(构造方法实参)

    MyArray  list=new MyArray<>();

    【注】

    • 类型后的<>代表占位符,表示当前类是一个泛型类

    • 在实例化泛型时,<>中不能是简单的类型,需要是包装类

    • <>不参与泛型的类型组成

    • 不能new泛型类型的数组

    • 使用泛型不需要进行强制类型转换

    一个简单的泛型:

    //此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
    //在实例化泛型类时,必须指定T的具体类型
    public class Test{ 
        //key这个成员变量的类型为T,T的类型由外部指定  
       private T key;
     
        public Test(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
            this.key = key;
        }
     
        public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
            return key;
        }
    }

    擦除机制:编译时会将<>中的类型擦除掉,所以<>中的东西不参与类型的组成。会将T擦除为Object。

    为什么不能实例化泛型类型的数组?

    数组和泛型之间的一个重要区别是它们如何强制执行类型检查。数组在运行时存储和检查类型信息,而泛型是在编译时检查类型错误。

    返回的Object数组里面,可能存放着任何类型的数据,如string,通过int类型的数组来接收,编译器认为是不安全的。

    3、泛型的上界

    语法:

    class 泛型类名称{

    }

    例:

    public class MyArray{} //E只能是Number或Number的子类

    public class MyArray>{}

    //E一定实现了Comparable接口的类

    【注】没有指定边界的E,可以看作 E extends Object

    4、通配符

    ? 用于在泛型的使用,即为通配符。通配符用来解决反泛型无法协变的问题。

    如下两段代码:

    代码一:
    public static void printList1(ArrayList list){
       for(T x:list){
          System.out.println(x);
       }
    }
     
    代码二:
    public static void printList2(ArrayList list){
       for(Object x:list){
          System.out.println(x);
       }
    }

    代码2中使用了通配符,和代码1相比,此时传入代码1的具体是什么数据类型,我们是不清楚的。

    (1)通配符的上界

    语法:

    //可以传入的实参类型为Number或Number的子类

    例:对于以下关系,我们需要写一个方法来打印存储了Animal或者Animal子类的list。

    Animal
    Cat extends Animal
    Dog extends Animal

    代码一:

    public static  void print1(List list>{
        for(T animal:list){
            System.out.println(animal);//调用了T的toString
        }
    }

    此时T类型是Animal的子类或自己。

    代码二:通过通配符实现

    public static void print2(List list){
        for(Animal animal:list){
           Syatem.out.println(animal);//调用了子类的toString方法
        }
    }

    两种代码的区别:

    • 对于泛型实现的方法来说,对T进行了限制,只能是Animal的子类。传入Cat,就是Cat。

    • 对于通配符实现的方法来说,相当于对Animal进行了规定,允许传入Animal的子类。具体哪个子类,此时并不清楚。如:传入Cat,实际上声明的类型是Animal,使用多态才能调用Cat的toString方法

    通配符上界→父子类关系:

    //需要使用通配符来确定父子类型

    MyArrayList是MyArrayList或者MyArrayList的父类

    MyArrayList是MyArrayList的父类

     ArrayList arrayList1 = new ArrayList<>();
     ArrayList arrayList2 = new ArrayList<>();
     List list = arrayList1;
     //list.add(1,1);//报错,此时list的引用的子类对象有很多,再添加的时候,任何子类型都可以,为了安全,java不让这样进行添加操作。
     Number a = list.get(0);//可以通过
     Integer i = list.get(0);//编译错误,只能确定是Number子类

    【注】

    • 不能对其进行添加,list中存储的可能是Number也可能是Number的子类,无法确定类型。

    • 通配符上界适合读取,不适合写入。

    (2)通配符的下界

    语法:

    //可以传入的参数类型是Integer或者Integer的父类

    通配符下界的父子类关系:

    MyArrayList是MyArrayList的父类类型

    MyArrayList<?>是MyArrayList的父类

    通配符下界适合写入元素,不适合读取。

    5、包装类

    在Java中,由于基本类型不是继承自Object,为了在泛型中可以支持基本类型,每个基本类型都对应了一个包装类。除了Integer和Character,其余基本类型的包装类都是首字母大写。

    拆箱和装箱:

    int i=10;
     
    //装箱操作,新建一个Integer类型对象,将i的值放入对象的某个属性中
    Integer ii=i;  //自动装箱
    //Integer ii=Integer.valueOf(i);
    Integer ij= new Integer(i);//显示装箱
     
    //拆箱操作,将Integer对象中的值取出,放到一个基本数据类型中
    int j=ii.intValue();//显示的拆箱
    int jj=ii;//隐式的拆箱
    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java
    相关文章 更多
    Java单元测试入门:使用JUnit 5编写第一个测试用例
    Java单元测试入门:使用JUnit 5编写第一个测试用例

    面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

    Java变量未初始化报错解析:局部变量与成员变量默认值差异
    Java变量未初始化报错解析:局部变量与成员变量默认值差异

    深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

    详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

    Java中final与static final常量的定义及初始化规则
    Java中final与static final常量的定义及初始化规则

    深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

    Java抽象方法与接口方法的区别及选型建议
    Java抽象方法与接口方法的区别及选型建议

    深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

    Java实现HTTP请求与JSON解析的完整代码示例
    Java实现HTTP请求与JSON解析的完整代码示例

    本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

    Java递归出现StackOverflowError的原因分析及栈空间优化方案
    Java递归出现StackOverflowError的原因分析及栈空间优化方案

    详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

    Java空指针异常(NPE)的代码排查与修复实例
    Java空指针异常(NPE)的代码排查与修复实例

    针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。