括号的区别
|
|
( )
表示 tuple,不可变类型[ ]
表示 list,可变类型
列表推导式
|
|
元组没有元组推导式
交换
|
|
输出序列以及倒序输出
|
|
加 r 不转义
|
|
格式化 对其输出 log 信息
|
|
center 表示居中的意思
单引号和双引号都可以表示字符串
|
|
都是输出 hello world
这点要注意和java区分,因为java单引号表示字符char
,双引号表示字符串string
pass的使用
如果想定义一个空函数,可以这样:
|
|
如果把上面的pass去掉是会报错的。
|
|
( )
表示 tuple,不可变类型
[ ]
表示 list,可变类型
|
|
元组没有元组推导式
|
|
|
|
|
|
|
|
center 表示居中的意思
|
|
都是输出 hello world
这点要注意和java区分,因为java单引号表示字符char
,双引号表示字符串string
如果想定义一个空函数,可以这样:
|
|
如果把上面的pass去掉是会报错的。
悉心整理校正了计算机网络的面试常用知识点,图文并茂,通俗易懂,希望对大家有所帮助。
文章链接 http://www.alijava.com/network-interview/ ,分享请保留出处。
每一层都是独立存在的,因此分配到各层的任务能够独立地执行,变更其中某层提供的方案时不影响其他层。
这也可以理解为一个松耦合的设计。
网络层 主要是 ip 协议,可以通过 ip 找到某个机器,但是机器上有很多应用程序,每个程序都占用相应的端口,传输层 不同协议有不同的端口,通过 ip + 端口 就可以确定某个机器上的具体应用程序了。
Server A 和 Server B 直接传输数据,有封装和解封装的过程。
数据从A 的应用层往下走到物理层,会在每一层都会加上头部信息,进行封装,然后再发送到B。
然后 Server B 从 最下面的物理层往上 每一层进行解封装,最后到达应用层,得到数据。
物理层:将电脑连起来,可以用光缆、电缆、双绞线、无线电波等方式
链路层:数据包会带上发送地址和接收地址,也就是MAC地址
网络层:网络地址帮助我们确定计算机所在的子网络,MAC地址则将数据包送到该子网络中的目标网卡。
因此,从逻辑上可以推断,必定是先处理网络地址,然后再处理MAC地址。
传输层:同一台主机上有许多程序都需要用到网络,端口可以确定表示这个数据包到底供哪个程序使用。
传输层建立”端口到端口”的通信,”网络层”的功能是建立”主机到主机”的通信。
(ftp 21,ssh 22,dns 53,http 80)
应用层 我们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如果没有应用层,便无法识别数据内容。
如果想要使传输的数据有意义,则必须使用到应用层协议。
TCP连接是由4个值来识别的: <源IP地址、源端口号、目的IP地址、目的端口号>
UDP 交给上层进行差错控制,可以代码对UDP的数据收发进行验证,比如发送方对每个数据包进行编号然后由接收方进行验证啊什么的
即使是这样,UDP因为在底层协议的封装上没有采用类似TCP的“三次握手”而实现了TCP所无法达到的传输效率
IP的地址字段范围是0~127,但是由于全0和全1的地址用作特殊用途,实际可指派的第一个字段范围是1~126。
A类地址范围:0.0.0.1 —— 126.255.255.254, 默认网络掩码为 255.0.0.0
B类地址范围:128.0.0.1 —— 191.255.255.254,默认子网掩码为255.255.0.0
C类地址范围:192.0.0.1 —— 223.255.255.254,默认子网掩码为255.255.255.0
0 到 128 相差128,128 到192相差64,后面192到224相差32。
A 类地址, 0 开头, 128 个
B 类地址,10 开头,16,384 个
C 类地址,110 开头,2,097,152 个
ip 地址= 网络号 + 主机号
网络号 | 主机号 | 用途 |
---|---|---|
全为0 | 全为0 | 表示本主机,用作源地址,启动时用,获取了 IP 地址后不再使用 |
全为0 | host-id | 本地网络上主机号为 host-id 的主机,只作为源地址 |
全为1 | 全为1 | 有限广播(本地网络),只作目的地址,各路由器都不转发 |
net-id | 全为1 | 定向广播(net-id标识的网络),只作目的地址 |
net-id | 全为0 | 标识一个网络 |
127 | 任意 | 本地软件回送地址 |
B类中169.254.0.0到169.254.255.255是保留地址。如果你的IP地址是自动获取IP地址,而你在网络上又没有找到可用的DHCP服务器,这时你将会从169.254.0.0到169.254.255.255中临得获得一个IP地址。
私有地址包括3组
A类:10.0.0.0~10.255.255.255
B类:172.16.0.0~172.31.255.255
C类:192.168.0.0~192.168.255.255
学校里的局域网,因为大概有几十万人,所以是10开头的局域网。
而我们买的无线路由器,也要设置局域网,一般为192开头的,比如192.168.0.1或者192.168.199.1(比如极路由就是这个地址)
我们建企业网(单位网络)时,一般是使用私有地址来分配内部主机,小企业使用C类的192.168.0.0网络,中型企业使用172.16.0.0网络,如果还不够用,还有10.0.0.0 网络。
以C类网络为例,原有8位主机位,2的8次方即256个主机地址,默认子网掩码255.255.255.0。
借用1位主机位,产生2个子网,每个子网有126个主机地址;借用2位主机位,产生4个子网,每个子网有62个主机地址……
把子网掩码为255.255.0.0的网络40.15.0.0分为两个子网,假设第一个子网为40.15.0.0/17,则第二个子网为?
40.15.0.0/17 表示网段是40.15.0.0,子网掩码是17位。
子网掩码为:255.255.128.0,用二进制表示为:11111111 11111111 10000000 00000000 ,斜杠后面的17表示子网掩码前17位为1.
答案:
划分为两个子网的话子网掩码应该为255.255.128.0
第一个子网是40.15.0.0/17,可用地址范围是40.15.0.1~40.15.127.254
第二个子网是40.15.128.0/17,可用地址范围是40.15.128.1~40.15.255.254
解析:
掩码的前两个八位是255,第三个八位是128,有2的一次方个子网(因为第三个八位只有一个1,后面七位都是0),所以ip 地址第三个8位是0000,0000或者1000,0000,即0或者128。
因为第3个8位是1000,0000,可以区分开头第一个数是0还是1, 区分了两个子网。所以这两个子网是40.15.0.0和40.15.128.0
NAT(Network Address Translation,网络地址转换)是一种网络地址翻译技术,将内部私有IP地址改变成可以在公网上使用的.
静态地址转换:一个公网IP对应一个内部IP,一对一转换
动态地址转换:N个公网IP对应M个内部Ip,不固定的一对一IP转换关系.同一时间,有M-N个主机无法联网.
端口多路复用:对外只有一个公网IP,通过端口来区别不同内部IP主机的数据.
网关(gateway)能在不同协议间移动数据
路由器(router)是在不同网络间移动数据
相当于传统所说的IP网关(IP gateway)
3 次是双向通信的最小值,也就是 SYN, SYN ACK, ACK ,两个发送、两个接收 ,其中第二次把接收和发送合在一起了
如果两次握手的话,客户端有可能因为网络阻塞等原因会发送多个请求报文,这时服务器就会建立连接,浪费掉许多服务器的资源。所以要增加第三次握手。
第三次失败,只有客户端处于成功状态(因为第2次服务器返回了ACK),服务器端没有接收到客户端的 ACK。
这要分几种情况讨论:
In other words, if the ACK is dropped but the next packet is not dropped, then everything is fine.
也就是说客户端发出的 ACK 丢失了,发出的 下一个数据包 没有丢失,则服务端接收到下一个数据包(这个数据包里也会带上 ACK 信息),能够进入正常的 ESTABLISHED 状态
如果服务端和客户端都没有数据发送,或者服务端想发送数据(但是发不了,因为没有收到客户端的 ACK),服务器都会有定时器发送第二步SYN+ACK数据包,如果客户端再次发送ACK成功,建立连接。
如果一直不成功,服务器肯定会有超时设置,超时之后会给客户端发RTS报文,进入CLOSED状态,防止SYN洪泛攻击。
(1)主机 A 关闭 A主机的 端口1 到 B主机的 端口2 的传输连接:
(2)主机 B 响应:
(3)主机 B 关闭 端口2到端口1的传输连接:
(4)主机 A 响应:
TCP是全双工模式,关闭连接时,每个方向都必须单独进行关闭。
当 主机 B 收到主机 A 的FIN报文时,仅仅表示主机 A 不再发送数据了但是 A 还能接收数据。
如果主机 B 全部数据都已经发送给 A 了,B 可以立即close;也可以发送一些数据给 A 后,再发送 FIN 报文关闭连接。
因此, 主机 B 的 ACK 和 FIN 一般都会分开发送。
最近想自动发帖回帖,拿某论坛试验了一下,发现可行,不过后续没有再使用,以免影响论坛正常运行。
本文链接 http://www.alijava.com/simulate-bbs/ 转载请注明出处
帖子链接的格式为
http://bbs.***.***.**/forum.php?mod=viewthread&tid=774210
最后面774210数字变化, 就可以得到不同的帖子
防止帖子发表会又被删了的情况, 进行判断帖子是否存在
递增后面的 id 数字, 对每个链接做回帖的 POST 请求
回帖需要用户登录信息
一种是利用Cookie
另一种是进行模拟登录
本文采用前者
有可能用户发了帖子,比如 url 为 http://bbs.***.***.**/forum.php?mod=viewthread&tid=774200
后来该帖子用户删除了或者被管理员删除了,虽然帖子不在了,但是该 tid=774200
还是存在的
|
|
代码比较简单,注意事项是找到自己的Cookie
,赋给String yourCookeie
用post发送一个回帖,回帖信息在 mapData.put("message", "友情帮顶了")
中
|
|
还有一个工具方法,将输入流转化为字节
|
|
本文总结了自己实际开发中的常用命令,不定时更新,方便自己和其他人查阅。
如有其他提高效率的使用技巧,欢迎留言。
本文地址 http://www.alijava.com/linux-basics/ 转载请注明出处
cd -
返回到上一次的工作目录
export LANG=en_US
,export 对于环境变量的设置也能作用于子shell
ps -ef | grep nginx
,搜索,这儿用到了管道
passwd root
修改密码
top
监控CPU 内存等
$?
上一个命令执行的退出状态,成功为0,不成功为非0
hostname
获取 ip
alias vi="vim"
在/etc/profile (用户登录自运行配置文件)的末尾添加vi的别名设置
-a
列出所有(含隐藏文件等): -ltr
按照时间升序 -lt
按照时间降序
统计文件数目
wc -l
输出文件行数,也就是文件的个数
可以通过 grep
过滤文件
|
|
locate
find . -name "*.sh" -or -name "*.c"
netstat -tnpl | grep 12
kill -9 42312
杀掉进程,-9 表示强制杀sed '$d' datafile
除最后一行,其余行都被显示sed '/my/d' datafile
除包含 my 的行,其余行都被显示sed -e 's/\.md$//'
去掉后缀 .md
sed -e 's/^/http:\/\/www.alijava.com\//'
加上网站前缀sed 's/old/new/'
将 old
替换为new
$#
表示接收到的参数个数$1
表示第几个参数
|
|
h, j, k, l
分别代表向左、下、上、右移动
在这些j前加一个数字,表示移动的倍数。例如,”10j“表示向下移动10行
^
移动光标到行首 0(数字0)也可以实现相同功能
^ 是移到第一个到行首的第一个非空白字符
0 只是移动到行首,不区分空白或非空白
$
移动光标到行尾
gg
回到文件开头 H
也可以回到文件最上面
G
到最下面dd
删除,前面加上数字表示删除多少行,比如100dddw
删除单词 d$
删除到这行末尾的单词yy
复制p
粘贴i
当前文字位置插入 inserta
当前文字的后面插入 appendo
下一行插入w
光标到下一个单词的词首e
移动光标到下一个单词的结尾/string
查找 n
查找下一个匹配的:set nu
显示行号:wq
写入并退出:q!
强制退出 不保存修改推荐一个在线学习vim网站 http://www.atool.org/vim.php
http://easwy.com/blog/archives/advanced-vim-skills-basic-move-method/
项目想把图片上传到七牛云存储上,笔者把七牛最简单的用法示范一下,方便初学者。
如果您还没有注册七牛,可以通过我的邀请链接注册 https://portal.qiniu.com/signup?code=3lpzf1unpyr0y,可以享受特有优惠以及免费空间。
比如上面的 beautiful girl 图片的 url 是
http://img.blog.csdn.net/20160119111734404
我们最终用代码上传到七牛图床后,七牛云存储的 url 为
http://7xq7ik.com1.z0.glb.clouddn.com/testimage
本文地址 http://www.alijava.com/qiniu-fetch/ 转载请注明出处
注册一个七牛账户
网址 https://portal.qiniu.com/signup?code=3lpzf1unpyr0y
登录七牛开发者自助平台,查看 Access Key 和 Secret Key (这两个 Key 代码会用到)
图片会上传到某个空间里,代码里会用到空间名,本项目空间名为 seenews
。
我们的项目需求是抓取网络图片:
输入图片原始的的 url,然后利用代码抓取到七牛图床上,返回图片在七牛上的 url 。
首先定义变量存放你的 Key 和空间名。
|
|
|
|
代码思路很简单,根据 key 获取到空间管理器,再指定图片的原始 url、空间名、图片的 key,就可以把图片上传到七牛上了
在七牛的空间内容管理部分可以看到图片已经上传好了,新的 url 为 http://7xq7ik.com1.z0.glb.clouddn.com/testimage
那么问题来了,如何获取图片新的 url 呢?总不能每次都通过浏览器访问七牛的网站,如何在代码里获取我们图片在七牛上的 url 呢?
还记得刚才的代码里我们给图片指定了 key 吗,只是图片在七牛空间里的唯一表示。
刚才我们指定的 key 为testimage
,看新的图片 url 为http://7xq7ik.com1.z0.glb.clouddn.com/testimage
,新url就是刚才的 key 结尾的。
前面一大串的字符是七牛给我们的默认域名,你也可以自定义域名。
那么代码思路也很简单,定义一个变量存放空间的域名,然后域名拼接图片的 key 就得到图片上传后的 url。
|
|
输出信息
|
|
如果您还没有注册七牛,可以通过我的邀请链接注册 https://portal.qiniu.com/signup?code=3lpzf1unpyr0y,体验用户有一些免费空间。
项目源代码地址(欢迎star) https://github.com/studychen/SeeNewsV2
本文链接 http://www.alijava.com/random-image/ 转载请注明出处
在实现APP 过程中,有些文章没有图片,想随机获取一张图片作为封面。
网上找到一个 API,访问 https://unsplash.it/300/200/?random 可以获取一张随机产生的图片。
后面笔者为了方便国内网络访问,把图片转移到了七牛云,共享给大家。
把图片的 src 设为 https://unsplash.it/300/200/?random ,图片是随机的了,但是两张随机图片是一模一样的,参加下面的代码和效果图。
|
|
你可以刷新本博客文章,两张图会随机变化,但是两张图依然保持一样。
不知道这是不是和浏览器缓存有关系,请大神赐教。
该网站也提供了根据 id 来获取图片,使用方法在 url 后面加上 ?image
参数。
https://unsplash.it/200/200?image=100 的图片内容为:
笔者使用下面的代码来随机产生 id,从而获取随机图片
|
|
但是测试发现,一小部分id对应的图片不存在,比如 https://unsplash.it/200/300?image=86 、 https://unsplash.it/200/300?image=105 等等。
笔者把该 API 提供的图片抓取到了七牛云上,保证图片的 id 是连续的。
可以通过我的邀请链接 https://portal.qiniu.com/signup?code=3lpzf1unpyr0y 注册七牛,享受优惠及免费空间。
|
|
可以访问 http://7xr4g8.com1.z0.glb.clouddn.com/671 获取图片,后面数字671是图片编号
目前有效图标编号的是 0 到 964,可以通过随机产生 id 来获取随机图片
|
|
项目源代码地址(欢迎star) https://github.com/studychen/SeeNewsV2
代码检测某个端口是否被占用,从而找出多个连续空闲的端口,由于需要 Windows、Linux 都能运行,所以选择了 Python,而不是 shell。
思路是 try 尝试连接某个端口,如果能连接上,表示端口被占用,否则端口空闲。
|
|
在try
模块中 如果 s.connect((ip, int(port)))
如果能成功, 说明端口被占用.
否则, connect
不成功, 会进到except
中, 说明端口不被占用.
|
|
源 ip 、源端口 + 目的 ip、目的端口 可以确定一条 tcp 连接。
本来以为 s.connect((ip, int(port)))
,只需要检测 "127.0.0.1","0.0.0.0"
后来发现还有可能是局域网ip 如 10.170.70.87
等等
可以通过这个方法根据远程 hostname 获得其 ip
|
|
从某个端口 port 开始,进行检测,port + 1、port + 2 … ,如果连续的空闲端口数目达到需求的 N,则 port ~ port + N 为需求的端口。
如果中途某个 port + L 端口被占用,那么从新的端口 port + L + 1 开始寻找。
本代码只针对 ipList = ("127.0.0.1","0.0.0.0",getLocalIp())
这3个 ip 进行 connect
|
|
第一种方法的准确性依赖于 connect((ip, int(port)))
中的 ip,
需要找到完备的 ip 集合的, 才可以确定这个端口不被占用,难度较大
**在 linux 用 netstat -tnpl
可以得到端口监听信息,
观察 tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 11563/java
出现了 0 0.0.0.0:8080
所以 8080端口是被占用的
对这些输出的字符信息进行搜索 :8080
, 如果存在, 就表示 8080 端口是LISTEN.
如果输出结果中不存在 :8080
的相关字符,表示这个端口不被占用.
WINDOWS、 LINUX 这几个平台查看端口信息的方式不同,
先进行机器平台的判断,然后调用各个平台的端口占用判断函数
因为需求是找出连续的空闲端口,当中途只要有一个端口占用, 就跳出循环
|
|
|
|
可以调用系统的一些shell命令
|
|
读取调用shell命令后的回显信息
|
|
工欲善其事,必先利其器。下面总结了这些年开发中使用的一些还不错的小工具,希望能够提高编码效率
本文链接 http://www.alijava.com/common-tools/ 转载请注明出处
优点在于开源、无广告、免费,缺点界面有点丑
可以通过这个网站 https://www.processon.com/ 在线制作流程图
当然 visio 更加专业了,可惜收费
支持实时预览,自带实时保存效果,不小心关了这个网页,重新打开后会恢复上次内容
微软出的一款编辑器,很轻量,没有繁琐的功能,界面酷炫,黑色背景,支持 markdown实时预览
下载地址 https://code.visualstudio.com/download
主要是为 Gitbook 服务,可以生成章节、目录,还可以利用 git 进行版本控制,对于团队发布整理 wiki 很有帮助,也可以用它基于 markdown 编写文档
chrome 扩展,可以很方便输入数据模拟 get post 请求
windows 下的抓包工具,它是在 web server 和 web 客户端 之间搭了一层 代理,所有的请求都会经过它
用过的很惊艳的功能如下:
www.alijava.com/web/test.js
,当无法修改服务端 js 文件或者部署到服务端 js 文件麻烦时,可以在本地修改该文件,然后将 www.alijava.com/web/test.js
重定向到本地 /usr/local/web/test_01.js
类似Fiddler,mac 下的抓包工具
终端远程连接 linux ,支持鼠标选中复制,右键粘贴
有时候需要连接多个linux机器,使用putty接环不方便。mtputty把putty当作标签显示,切换方便很多,提高效率
FTP客户端,图形用户界面(GUI),方便 windows 连接 linux 机器传输文件,类似的软件还有很多
同上,FTP客户端
安装结束使用 http://ip:8888 来打开 vpsmate 的后台
可以通过浏览器网页端编辑文件、修改文件等,可视化操作
上面的 vpsmate 停止更新了,现在有个升级版 AppNode
命令行使用 git 虽然很棒,而 SourceTree 提供了图形化,可以更方便查看提交记录log、对比文件的修改
当 git 仓库 有主模块、子模块,注意 SourceTree 可能会分支漂移,当主模块切到某个分子,子模块可能并没有切到某个分支,这时候需要手动切下子模块。
Java 字符串在面试、笔试中都是常考知识点,下面进行相关知识点讲解。
|
|
String的equals()是比较字符串的内容。故equals得到true很容易理解。
==是比较内存地址的,第一个true说明strOne 和strTwo的地址相同。
为什么呢?
java有常量池,存储所有的字符串常量。
String strOne = “testString”
java首先会在常量池查找是否有 “testString”这个常量,发现没有,于是创建一个 “testString”,然后将其赋给strOne。
String strTwo= “String”;
java同样会在常量池中查找 “testString”,这次常量池中已经有strOne 创建的 “testString”,故不创建新的常量,将其地址赋给strTwo。
如此,strOne和strTwo便有了相同的地址。
Java 字符串对象创建有两种形式:
String str = "testString"
String str = new String("testString")
|
|
|
|
而用new String(“testString”)创建的两个字符串,用equals()比较相等,用==比较则不相等。
为什么呢?
new String()每次会在堆中创建一个对象,每次创建的对象内存地址都不同,故==不相等。但字符串内容是相同的,故equals()相等。
看下官方文档的说明,大致意思是:
如果常量池中存在当前字符串, 就会直接返回当前字符串. 如果常量池中没有此字符串, 会将此字符串放入常量池中后, 再返回。
|
|
|
|
String strOne = "testString"
这行代码使得常量池中已经存在了"testString"
,intern() 从字符串常量池中查询到当前字符串已经存在,返回常量池中的字符串
|
|
如文档里所说 s.intern() == t.intern() is true if and only if s.equals(t) is true
。
strOne.intern()
先查找常量池中是否存在当前字符串,发现不存在,于是会把字符串放入常量池中。strThree.intern()
也先从常量池中查找,找到了刚才放入的字符串,所以两者相等。
new 创建的String对象使用intern方法,intern方法,若不存在就会将当前字符串放入常量池中。
intern() 底层实现也是维护了一个hash表,保持字符串。
|
|
查看源码可知,intern() 是使用 jni 调用c++实现的StringTable的intern方法, StringTable的intern方法跟Java中的HashMap的实现是差不多的, 只是不能自动扩容。默认大小是1009。
注意,数据量规模很大时,如果程序将很多字符串常量(类名、方法名、key值等)存入intern()的常量池,当池大小超过了默认值后,性能可能会急剧下降。
源码可以看到 public final class String
,所以 String 也不允许继承。
|
|
如果对一个已有字符串进行修改,不会在原来内存地址上修改数据,而是重新指向一个新的对象。
|
|
使用 substring 改变字符串,也是返回一个新的字符串,而不是原地修改。
String 内部使用 private final char value[];
来保存值,而且也没有暴露关于value的引用。虽然数组value
一旦赋值后,不允许修改,但是这仅仅是不能指向新的数组,数组的内容其实可以修改。
我们可以利用反射得到 value ,从而改变 value 的值。
|
|
看下面这段代码
|
|
x
和 y
本来都是"123456"
,我们只利用反射改变了x
的值,却发现y
的值也跟着变了,因为这两者都是指向常量值中的字符串,所以修改一个,另外一个也变了。
不推荐实际生产环境中使用反射改变字符串,违背String不可变行
软引用 在内存不足时回收
弱引用 在垃圾回收时不管内存是否充足都回收
public final class String extends Object
finally 常于 trt/catch 语句块配对使用,即使有异常抛出,也能确保某段代码一定能执行。
finally 常用于关闭流资源或者数据库连接等。
overload 重载,是指两个方法的名称相同,但参数类型或者个数不同,即方法的签名不同。注意:方法的返回值不能作为其签名
override 重写,是指某个方法与父类的方法拥有相同的名称和函数签名。比如实现某个接口,需要进行 override 其中的抽象方法
原因:
java按照hashCode来访问小内存块,所以hashCode必须相等。HashMap获取一个对象是比较key的hashCode相等和equal为true。HashMap比较对象时先通过hashcode缩小范围,然后再使用equal方法比较是否相等
原因:
比如对象 A 和 对象 B 有 id 和 name,hashCode 按照name 来计算,但是 equal 按照 id来进行比较. 可能出现 name 相同,id 不同的情况. (公司员工同名同姓的情况). 这时候 hashCode 相同,equal 不同
成员函数只有声明,没有方法体,自动都是 public 修饰的 (我们 code 时候 可以省去),成员变量默认都是静态变量 static final。
抽象类更相当于 is-a (是不是) 的关系 。接口是 has-a (有没有)的关系
比如抽象类 Bird 和 Plane 表示鸟、飞机,可以继承它们实现更具体的鸟(老鹰、麻雀等),更具体的飞机(直升机、战斗机)。
用 Fly 表示接口,一组抽象的飞行行为,不能设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。此时可以将 飞行 设计为一个接口Fly,包含方法fly( ),然后Airplane和Bird分别根据自己的需要实现Fly这个接口。
java.util.Collection 和 java.util.Collections
Collection 是接口
The root interface in the collection hierarchy. A collection represents a group of objects,
Collections 里面包含了一些 处理 集合的静态方法
This class consists exclusively of static methods that operate on or return collections.
HashSet无序
LinkedHashSet 按照 插入顺序 排序,使用链表维护元素的次序。
java.lang.Comparable 和 java.util.Comparator
从英文名字也可以看出,Comparable是一种 able,表示该对象可以比较,是 对象自身的属性,其中要Override的方法 compareTo,compareTo 是 同种对象 之间 比较。
Comparator是一个名词,如果一个对象没有实现 Comparable 时,就要外部实现 一个 单独的 Comparator 接口,传递给 sort 方法,其中要Override的方法 是 compare,compare 像是 外部 对两个对象比较。
sort(Object[]),所有对象都必须实现Comparable接口,它用来确定对象之间的大小关系 。
sort(Object[],Comparator) 对象不必实现Comparable接口,各个对象根据 Comparator 确定大小关系。