| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> java数据结构与算法第二课——泛型 -> 正文阅读 |
|
[Java知识库]java数据结构与算法第二课——泛型 |
? 目录 一:泛型的定义????????一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。 ????????泛型是在JDK1.5引入的新的语法,通俗讲,泛型:就是适用于许多许多的类型。从代码上讲,就是对类型实现了参数化。 二:引出泛型之前我们已经学过数组,在一个数组中,只能存放指定类型的元素。例如:
? ? ? ? 基于泛型的定义,我们希望一个数组可以适用许多许多类型。因为Object类是所有类的父类,那么是否可以把数组创建为Object呢?具体示例如下:
? ? ? ? 就目前为止,这段代码似乎没有什么问题,因为数组的元素类型是Object,所以我可以放任意类型的数据,譬如在0下标的位置放入整型1,在1下标的位置放入字符串“hello”。但当我们想通过getPos()函数获取某个下标的元素时,你会发现: ? ? ? ? ?编译器报错了!这是因为数组中元素类型不确定,所以当你获取元素时,编译器无法帮你检测你当前想要获取的元素的类型,所以就会报错。而在实际中,我们很少需要把一个整型数据和一个字符串类型的数据放在同一个数组中,这没什么意义。一般情况下,我们仍希望可以自己指定类型,而非同时持有多种类型。 ????????泛型的作用就在此时体现出来:指定当前的容器,要持有什么类型的对象,然后让编译器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。 三:泛型3.1泛型的语法
? ? ? ? 单纯看这些语法可能会让你觉得头大,所以我会对上面的例子进行简单的改写,以帮助我们理解泛型的语法:
运行结果如下: ? ? ? ? ?也就是说,要将一个类写成“泛性类”,我们需要进行以下操作: 注意: 1.数组中每个元素的类型不再是Object,而变成了T。所以在创建数组,写getPos()和setPos()方法时,都要使用T而不是Object; 2.在创建数组时,要写成public T[] array = (T[])new Object[10],即在右侧new一个Object类型数组并强转为T[]。 即不能直接new泛型类型的数组; 3.类名后的<T> 代表占位符,表示当前类是一个泛型类,【规范】类型形参一般使用一个大写字母表示,常用的名称有:
4.泛型只能接受类,所有的基本数据类型必须使用包装类!即用Integer而不是int; 5.当编译器可以根据上下文推导出类型实参时,可以省略类型实参的填写;
6.泛型是将数据类型参数化,进行传递; 7.使用<T> 表示当前类是一个泛型类; 8.泛型目前为止的优点:数据类型参数化,编译时自动进行类型检查和转换。 3.2擦除机制(了解)????????擦除机制就是在编译时,所有的T都被擦除为了Object。通俗讲,就是在编译的过程当中,将所有的T替换为Object的这种机制。 3.3泛型的上界3.3.1泛型的上界的定义?????????在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束。也就是说,泛型的上界是一种对于传入的类型变量的约束。 3.3.2泛型的上界的语法
具体实例如下:
? ? ? ? 这段代码说明:传入的类型变量必须是Number类及其子类。 ? ? ? ? 根据java文档显示,我们可以传入的类型包括Byte,Double,Float...... 复杂示例:??
E必须是实现了Comparable接口的。?具体示例如下:
运行结果如下: 分析: ? ? ? ? ?我们发现,每次调用findMax()方法时,必须先实例化对象,然后才能调用findMax()方法。那么,有没有可能不实例化对象,直接调用findMax()方法呢?答案是可以的。这就要用到静态方法。 3.4泛型的静态方法? ? ? ? 明确其语法后,我们将“泛型的上界”加入,即对传入的类型变量做一定的约束: ? ? ? ? 这时候,我们就可以直接使用类名调用findMax()方法,1而不必先实例化对象了。具体示例如下:
?运行结果如下: 四:通配符4.1引出? ? ? ? 通配符,顾名思义,即适配各种类型。? ? ? ?? ????????通配符有什么作用呢?简言之,通配符是用来解决泛型无法协变的问题的,协变指的就是如果Student 是Person 的子类,那么List<Student> 也应该是List<Person> 的子类。但是泛型是不支持这样的父子类关系的。具体实例如下: ? ? ? ? ?如图所示,Student类是Person类的子类,我们认为父类引用引用子类对象应该是没有任何问题的。然而,当我们将想法付诸实践时,发现这样做不合法,这是因为型不支持这样的父子类关系,这就叫做无法协变。而要解决这个问题,就需要用到通配符。具体实例如下:
4.2通配符及其上下界1、通配符,代表未知类型,代表不关心或无法确定实际操作的类型,一般与容器类配合使用。
2、<? extends T>,定义上限,期间只有阅读能力。这种方法表明参数化的类型可能是指定的类型或子类型。 可以接受T及其子类。
3、<? super T>,下限定义,有阅读能力和部分写作能力,子类可以写入父类。这种方法表明参数化的类型可以是指定的类型,也可以是父类。可以接收T及其父类,可以写入T及其子类。
? ? ? ? 以上就是通配符及其上界、下界的全部内容了。 五:包装类在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java给每个基本类型都对应了一个包装类型。 ? ? ? ? 如图为各基本类型及其对应的包装类。 ? ? ? ? 今天我们要介绍的内容,主要是装箱和拆箱。 ?5.1装箱
????????如何自动装箱?直接将int类型变量赋值给Integer类型的变量。而手动装箱则时调用balueOf()方法。 5.2拆箱
? ? ? ? 在拆箱时,a为Integer类型,那么默认会以intValue()进行拆箱;如何想手动拆箱,则要显式调用相应的方法。 5.3一道有趣的题目? ? ? ? 对于拆箱和装箱部分,我们已经了解得差不多了。接下来我会介绍一道非常有趣的题目,其中就包含了“装箱”相关的知识。 ????????分析代码,为什么会出现这种现象呢? ? ? ? ? 在执行这几行代码时,我们知道发生了装箱。而在底层,装箱默认调用的是valueOf()方法。所以要解决这个问题,我们需要查看valueOf()的原码,看看它究竟是怎样实现装箱的。 ?????????为了验证我们的结论,我们采用特殊值法进行验证: ? ? ? ? 结论成立!解决方案也很简单,就是使用equals()方法进行比较。(引用类型的比较)
? ? ? ? ?运行结果如下: ? ? ? ? ?这告诉我们,在对引用类型进行比较时,一定要使用equals()方法或compareTo()方法。 本课内容结束! |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 1:42:58- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |