【16-Ⅰ】Head First Java 学习笔记

HeadFirst Java

本人有C语言基础,通过阅读Java廖雪峰网站,简单速成了java,但对其中一些入门概念有所疏漏,阅读本书以弥补。

第一章 Java入门
第二章 面向对象
第三章 变量
第四章 方法操作实例变量
第五章 程序实战
第六章 Java函数库
第七章 继承与多态
第八章 深入多态
第九章 构造器与垃圾收集器
第十章 数字与静态
第十一章 异常处理
第十二章 GUI(内部类)
第十三章 Swing
第十四章 保存对象
第十五章 网络与线程
第十六章 数据结构


前言

结束了上一章,网络与多线程,真是一个超长的巨头,内容也很重要!主要学习了客户端、服务端的Socket连接,以及多线程并发的相关问题。这一章我们学习Java常用的集合框架(Collections Framework),支持大多数的数据结构!此外,也将学习泛型,这也是一个重要的概念。

这里我们需要对歌单文件进行一个排序,前文学习过ArrayList,但这个集合并没有sort方法,怎么办呢?

常用的集合
在这里插入图片描述

排序

Collections.sort()

P535~P538,先是使用该方法对ArrayList排序,后要对ArrayList排序会编译报错,为什么呢?下文详解

泛型

目的:写出有类型安全性的集合

基本用到泛型的程序都与集合有关,让编译器帮助你避免把Dog加到一群Cat中,将错误在编译器找到,而不是执行期
在泛型之前,我们把集合写成处理Object类,任何东西都可以放进去,但取出来时我们只能得到Object类的引用,这在好几章前讲过
在这里插入图片描述

如何使用泛型:
1.创建 泛型化类的实例
2.声明与分配 泛型类型的变量
3.声明与调用 存取泛型类型的方法

new ArrayList<Song>();//  1.创建实例
List<Song> songList = new ArrayList<Song>();
ArrayList<Animal> list = new ArrayList<Hippo>();//这是错误的分配
// 声明:List<Song> songList 声明了遥控 泛型类的实例 的引用变量
// 分配: = ,将ArrayList<Song> 泛型类的实例 赋给 声明的引用变量
void foo(List<Song> list);//3.声明
x.foo(songList);//4.调用

使用泛型时,我们<>中填的永远是具体的类,而不是一个符号。读完下文,再理解这句话,意思就是:告诉泛型类,其形式参数的值是传入的具体类。如List ,List接口的形参T的值为Song。

补充4. 实现 泛型类接口 的 类

在后续中,实现Comparable会强调。
其实与声明也一样,List不就是用到了List接口,无论你怎么用(创建实例、声明变量、实现接口等等),你使用到了泛型(List),编译器会去看这个接口,并且知道接口定义的T的值为Song

使用泛型的类

从ArrayList源码学起,关键两部分
1)类的声明
2)方法的声明

关键在于理解E是什么?(看了英文版更具体些)
E 表示 数组将保存元素的类型 的一个替代符号(Element,实际上你改成也可以),它会在你声明和创建泛型类的实例时 被替代为一个具体的类。
E 即 形式参数,在方法中,传入参数的类型(形式参数) 可以用E。也就是不管E最后被替换成啥,咱们都可以在这个方法传进去

在这里插入图片描述

在这里插入图片描述

运用泛型的方法

由上,泛型的类即 类的声明 用到了 形式参数;那么泛型的方法 即 方法的声明 用到了 形式参数
关于方法的形式参数的用法如下
1.使用 定义在类的 形式参数

public class ArrayList<E> {
	public void add(E o)//类声明了E这个形式参数,所以方法可以直接用
}

2.使用 未定义在类的 形式参数

public <T extends Animal> void test(ArrayList<T> list)//在 返回类型(void)之前 声明 形式参数(这里T is-A Animal)

思考:
下面这行代码,与上面有何区别?

public void test(ArrayList<Animal> list)

回到sort()

为什么不能直接Collections.sort(songList)?
观看源码,可知因为Song 不是Comparable的子类,所以不能传入对象
在这里插入图片描述
注意,对于泛型,extends 代表 IS ”是一个“。也就是T 要么是 继承了Comparable类,要么是 实现了Comparable接口。实际上这里Comparable是个接口。所以这里意思是后者。

对于类的extends,即IS-A 包含继承关系,X IS-A Y,表示X比Y可做的更多
对于类的implement,即CAN-DO,包含扮演的作用,X CAN-DO Y,表示X可以做Y做的事情,这是接口
在泛型的类,其extends,IS,包含了继承与扮演两种 含义。

为什么泛型要用extends关键词,不加入IS关键词?

会破坏旧版的程序,或许有人用了名称为is的变量

重新实现Song类

问题就出在Song必须实现Comparable接口,才能将ArrayList传给Collections.sort方法
在这里插入图片描述

返回负数,传入对象大;正数,传入对象小。

class Song implements Comparable<Song> {//普通的类Song 实现 泛型的类Comparable接口
	String title;
	public int compareTo(Song s) {
		return title.compareTo(s.getTitle());//String类有compareTo方法
	}
}

原文:按规定,这里泛型类的<> 中内容 必须是Song,或者其他可以与Song比较的类

误区:public class Song implements Comparable ,把E当作类!E只是定义泛型类时声明了一个形式参数,实际运用泛型时,我们要指定具体的类。
注意,这里是普通类 实现一个接口,没有定义形式参数E,E是在接口定义那定义的
类比创建实例时ArrayList,创建泛型类实例时,指明集合元素的类型;编译器对该实例,E都会替换为Song,add等方法传入实际参数即对象只能是Song类
这里实现接口,同理 指明与Song类(这里的实现类)可比较的元素的类型是Song;编译器对该实现类,E都会替换为Song,覆写方法时传入实际参数即对象必须是Song类

在这里插入图片描述

自定义Comparator(比较器)

那如果要根据歌星名排序呢?

在song类中加 flag变量,再在compareTo中加上if判断即可——这样不好,内管外,不合理

查询API,可知sort的重载版本——传入Comparator参数
在这里插入图片描述

根据调用sort的版本
1.元素的类 实现Comparable接口 ,使用compareTo方法
2.自定义比较器类 实现Comparator接口,使用compare方法

使用比较器的点歌系统
class box {
	ArrayList<Song> songList = new ArrayList<>();
	class titleCompare implements Comparator<Song>  {//用 内部类 实现 接口类,并指定接口形参为Song
		public int compare(Song one,Song two) 
			return one.getTitle().compareTo(two.getTitle());
			
	class ArtCompare implements Comparator<Song>  {// 为什么用内部类?实现同一个接口多次 + 面向对象的意义
		public int compare(Song one,Song two) //
			return one.getArt().compareTo(two.getArt());
	public void test() {
		Collections.sort(songList,new titleCompare());//调用sort的第二版
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/587997.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT:按钮类控件

文章目录 PushButton快捷键Radio Buttion PushButton 这个类继承自QAbstractButton&#xff0c;是所有按钮的父类 创建一个带有图标的按钮&#xff1a; 假设这个图片是这个 那么我们就可以创建按钮并进行设置了&#xff1a; #include "widget.h" #include "u…

继续有效通知发文,撤三的商标保住了!

今天普推知产老杨看到年前协助贵州一位朋友处理的撤三答辩有结果了&#xff0c;在商标局官网上检索到“继续有效通知发文”&#xff0c;说明这个已注册商标保住了。 现在商标已注册量突破4000万&#xff0c;可以想到的好点的名称基本让别人都注册了&#xff0c;所以会对已注册商…

Linux专栏06:Linux基本指令之文件处理指令

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Linux专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Linux基本指令之文件处理指令 编号&#xff1a;06 文章目录 Linux基…

C 408—《数据结构》图、查找、排序专题考点(含解析)

目录 Δ前言 六、图 6.1 图的基本概念 6.2 图的存储及基本操作 6.3 图的遍历 6.4 图的应用 七、查找 7.2 顺序查找和折半查找 7.3 树型查找 7.4 B树和B树 7.5 散列表 八、排序 8.2 插入排序 8.3 交换排序 8.4 选择排序 8.5 归并排序和基数排序 8.6 各种内部排序算法的比较及…

Springboot+vue+小程序+基于微信小程序的在线学习平台

一、项目介绍    基于Spring BootVue小程序的在线学习平台从实际情况出发&#xff0c;结合当前年轻人的学习环境喜好来开发。基于Spring BootVue小程序的在线学习平台在语言上使用Java语言进行开发&#xff0c;在数据库存储方面使用的MySQL数据库&#xff0c;开发工具是IDEA。…

IDA pro动态调试so层初级教程

一、开启服务 adb push D:\MyApp\IDA_Pro_7.7\dbgsrv\android_server64 /data/local/tmpadb shell cd /data/local/tmp chmod 777 android_server64 ./android_server64二、IDA附加进程 十万个注意&#xff1a;IDA打开的so文件路径不能有中文 手机打开要调试的app 附加成功

【C++容器map】map的相关用法

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; C进阶 &#x1f389;其它专栏&#xff1a; C初阶 | 初阶数据结构 | Linux 本篇文章主要讲解 C容器之map相关用法 的相关内容 文章目录 1. map的介绍2. map的使用<font size5 color #…

【Docker】搭建一个媒体服务器插件后端API服务 - MetaTube

【Docker】搭建一个媒体服务器插件后端API服务 - MetaTube 前言 本教程基于群晖的NAS设备DS423的docker功能进行搭建&#xff0c;DSM版为 7.2.1-69057 Update 5。 简介 MetaTube 是一个媒体服务器插件&#xff0c;主要用于 Emby 和 Jellyfin 媒体服务器。它的主要功能是从互…

PS车票的两种方法

方法一&#xff1a;界面有需要的数字 1.使用矩形选框工具&#xff0c;对要修改的数字进行框选 2.使用修补工具&#xff0c;把选框拖到想要的数字 方法二&#xff1a; 1.先找到需要的字体&#xff0c;使用矩形选框工具对字进行框选&#xff0c;在菜单栏找到文字的匹配字体。 …

Pandas入门篇(二)-------Dataframe篇5(进阶)(Dataframe的时间序列Dataframe最终篇!!)(机器学习前置技术栈)

目录 概述一、pandas的日期类型&#xff08;一&#xff09;datetime64类型的特点&#xff08;二&#xff09; 时间序列的创建1.从字符串创建datetime64类型2. 整数&#xff08;Unix时间戳&#xff09;创建datetime64类型3.导入数据时直接转换 &#xff08;三&#xff09;dateti…

【MATLAB画图】如何绘制图像坐标系

首先我们需要图像坐标轴的原点在左上角&#xff1a; set(gca,ydir,reverse,xaxislocation,top); 然后我们需要坐标轴上加上箭头 quiver(0, 0, 0, 520); % 在(x1, y1)处绘制一个箭头&#xff0c;其方向和长度由(dx, dy)确定 quiver(0, 0, 700, 0); % 在(x1, y1)处绘制一个箭头…

C#技巧之窗体去鼠标化

简介 在窗体程序中不用鼠标&#xff0c;直接使用键盘完成想要的操作。 实现的方法有两种&#xff0c;一种是使用键盘上的Tab键使控件获得焦点&#xff0c;然后用enter键触发该控件上的事件&#xff08;一般为click事件&#xff09;。另一种是&#xff0c;为控件添加快捷键&am…

LeetCode热题100:双指针

283.移动零 题目链接&#xff1a;移动零 题目描述&#xff1a;给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 解题思路&#xff1a; 创建两…

VTK 的可视化方法:等值面

VTK 的可视化方法&#xff1a;等值面 VTK 的可视化方法&#xff1a;等值面VTK 中的数据表达VTK 等值面提取类实例1&#xff1a;模型数据的等值面提取空间函数数据的等值面提取参考 VTK 的可视化方法&#xff1a;等值面 等值面是指一组具有相同标量值的点所构成的表面。 等值面…

54.HarmonyOS鸿蒙系统 App(ArkTS)tcp socket套接字网络连接

54.HarmonyOS鸿蒙系统 App(ArkTS)tcp socket套接字网络连接 import socket from ohos.net.socket; import process from ohos.process; import wifiManager from ohos.wifiManager;import common from ohos.app.ability.common;let tcp socket.constructTCPSocketInstance();…

接收区块链的CCF会议--APSEC 2024 截止7.13 附录用率

会议名称&#xff1a;APSEC&#xff08;Asia-Pacific Software Engineering Conference&#xff09; CCF等级&#xff1a;CCF C类学术会议 类别&#xff1a;软件工程/系统软件/程序设计语言 录用率&#xff1a;2023年&#xff0c;90 submissions were recommended for accep…

智能指针解决多线程访问共享对象的线程安全问题

以下代码&#xff0c;在对象A被析构后&#xff0c;去访问A的成员对象&#xff0c;显然是不合理的。 class A { public:A() { cout << "A()" << endl; }~A() { cout << "~A()" << endl; }void testA() { cout << "非常…

OPA657运算放大器调研

运放是一种直流耦合&#xff0c;差模&#xff08;差动模式&#xff09;输入、通常为单端输出&#xff08;Differential-in, single-ended output&#xff09; [1] 的高增益&#xff08;gain&#xff09;电压放大器。运算放大器能产生一个比输入端电势差大数十万倍的输出电势&am…

Microsoft.NET 框架程序设计 —— 共享程序集

文件版本是一个很难解决的问题。实际上,如果仅仅在一个文件中将其某一位从0改变到1、或者从1改变到0,我们便不能绝对保证使用原来文件的代码和它使用新版文件时的行为一样。这是因为许多应用程序都会有意或者无意地引入bug。如果一个文件的后续版本修复了一个bug,应用程序便…

缓存分享(1)——Guava Cache原理及最佳实践

Guava Cache原理及最佳实践 1. Guava Cache是什么1.1 简介1.2 核心功能1.3 适用场景 2. Guava Cache的使用2.1 创建LoadingCache缓存2.2 创建CallableCache缓存 缓存的种类有很多&#xff0c;需要根据不同的应用场景来选择不同的cache&#xff0c;比如分布式缓存如redis、memca…