cqhh

目录

说在前面的话

前言

内容介绍

介绍 JavaSE 基础的基本语法知识,不会包含特别难以理解或更深层次的内容,通俗易懂。

前提

本书的所有例子使用 JDK8 在 Windows10 系统下完成;若你与我的不一致,快捷键、源码都有可能不同,但网上无偿资源十分的多,搜索了解不同之处即可。

受众人群

区别于教材,不会设问不答,而是十分详细,不会为读者留出思考和遐想的空间;目的只为节省时间,算是入门的自学读物吧。

主要让小白快速了解或回顾 JavaSE 的基础语法知识,随看即用,无阅读门槛。

如果你的目的是应对面试,想要掌握更深层次的内容,这本书不适合你,叉掉换一个吧,CSDN 中好文章多的去了。

主要内容

本书共 20 章,涵盖了如 Java 基础语法、变量、运算符、流程控制语句、面向对象、常用类、集合、IO 等部分,基本囊括作为后端开发人员必学的知识点。

另外把那些不常用的知识自成一章,移入扩充内容

本书示范中,将可能使用到的软件、工具网址放入资源地址中。

章节编排

每章共有 3 级目录,取名尽量保持唯一性;第 2 级目录随后跟着内容导视,用来统领第 3 级目录的内容;若第 3 级目录中还有大量知识点,会提取到内容如下

对于讲源码的部分,先抛出结论,自成一节,在它的下一个目录,粘贴全部源码,逐行分析。

每章的结尾会插入总结回顾与习题;习题的平均难度分级:脑海练习、实战演练、掀起波澜、头脑风暴、大脑宕机、空空如也。

此外正文中可能会以课堂练习思考的形式发问。思考的答案紧跟题目后面,课堂练习答案在文章末尾,参考答案自成一章。

如何使用

因为人的大脑很特别,会自动屏蔽掉日常普通、枯燥乏味的事情,目的是保持内存充足。它只记住比较特别的,其它的都会慢慢遗忘。

什么是比较特别的?

  • 重复,一直重复;重复到大脑认为这不该忘记。
  • 新奇的、有趣的、充满致命危险的、富有挑战性的、特殊的。

所以我加入了总结回顾,记录了这一章的重要内容,怕你看着看着就全忘了。放心,只有一点点,不会对你的大脑造成负担。看完后,记得休息一会。

更新内容

第 3 版的更新内容

新增 switch case 分支、补码、二进制转换、字符编码常识、值传递、String 字符串常量池和 intern 方法的解析、第三代日期类、UUID、正则表达式等一系列内容。

将双向链表移入 LinkedList 这节中。

取消了 b 标签的使用,因为无法在 CSDN 中无法做到与博客园一样的显示。

取消了 img 标签的使用,因为在 CSDN 中无法显示图片。

取消了 gif 动图的使用,因为打印 pdf 文件后就是静图;

取消了超链接使用,统一使用网址代替。

发现每章的内容过多,将每章继续拆分为几个小节。(希望以后别分了)

移除了强类型语言、进制转换、字符编码、原码补码等内容。

第 2 版的更新内容

将所有目录重新整合,改名,保证标题的唯一性,否则博客园可能跳转错误。

将 字符编码 部分内容移到 常用类 一章中;将 Eclipse 移至扩充内容中;将下载与准备工作合二为一,修改 \(\xi\) 符号的显示问题;用 ① 替换 1. 避免格式乱码。

由于章节过多,只得拆分成 20 章,否则浏览器加载不过来,之后再考虑吧。

其他说明

小问题

博客园有时会出毛病,在同一篇文章中,如果两个标题名相同,点击只会跳转到第一个标题;虽然已经开始在标题前面加 1.1.0 让标题名唯一,但是还不够,请从点击如图展示的标题列表中跳转。

在这里插入图片描述

封面制作

封面是用 win10 3D 画图制作的。

致谢

首先感谢父母给我一个好的身体,感谢母亲耐心的支持,否则我早就坚持不下去,直接灰溜溜地提桶进厂了。

其次感谢遇到的挫折与不堪,及时纠正我前进的方向。好吧我还是讨厌它,为什么我总要给自己的生活添堵呢?

最后感谢在网上无私奉献知识的大家,我是在家自学的,不懂就上网搜,算是野生吧。你们对我带来了很大的帮助,可以说脑海中的知识体系都是网上博客园一篇篇的文章,一段段视频堆砌而成的,真的很感谢你们。生活在和平的中国,享受如此丰富的资源,挺幸运的,我会把文章知识来源链接放在参考文献中,但可能有遗漏,不能一一列出,但你们对我帮助也挺大,感谢。

这些在网上搜集的资料,如有侵权,烦请告知。

编者:cqh
2022 年 3 月 4 日,于湖北安陆

勘误

笔者也只能算是新手,学识尚浅、水平有限,有些抽象、底层的东西以目前的功力无法一眼看破,找不到合适的方法去验证结论,只能是凭第一感觉得到具体的规律,所以也可能是想当然,看法比较片面。你就当成强行解释,笑一笑吧,对身体好。

部分解释可能不详细或不清楚(词不达意),如果你有更好、更通俗易懂的语言,欢迎留言指出。

在阅读文章时,请你时刻持有一种质疑的态度,这样既能帮助自己思考,也能发现我文章的不足之处,如果文章中有什么错漏的地方,还请不吝啬指教与批评,十分感谢!

若有帮助,会将你列入鸣谢名单中。

(其实我也忐忑不安,一是私,浅薄如尘土;二是公,接受审视,如同架到火上烤)

书中源码地址

https://gitee.com/ccqqhh/java-se

爱好

喜欢养鱼(草金鱼)、养龟(草龟);看奥特曼;看优秀的国漫,如伍六七、凡人修仙传;喜欢听梁博的歌;欢迎交流。(你觉得好笑就好笑,幼稚就幼稚吧,爱怎么想,我控制不了)

最大的梦想:远离纷争,自由地躺着摇椅上晒太阳。

求职

本人联系方式

QQ:2675385031

微信号:cqhjava

邮箱:2675385031@qq.com

博客园:https://www.cnblogs.com/cqhh/

CSDN:https://blog.csdn.net/cqh123hh

求职

不讲什么本人勤奋热爱好学这套老掉牙的事了,这玩意就是你情我愿,一拍即合,不行就拉倒,谁也没有必要低声下气,彷佛占了什么便宜。

我不想通过招聘网站(我不信任,还是需要线下跑来跑去,精力都耗没了),什么一面二面,还要花时间背没有用的题目,互相试探,装的很牛的样子;也不想一个个线下到处漫无目的地找(没有渠道),因此在各大网站上发布信息亲自验证就是十分便捷的选择。

若你想要了解我掌握的东西,那你看看我写的博客就行,也不会超出这个博客内容太多,忘了很正常,看看就捡起来了,我又不是电脑,没必要一直存储到脑海中,超时就丢掉。

要求:

  • 工作地址:限在中国,离湖北越近越好。

  • 工作内容:与电脑相关,敲字什么的无所谓,有口饭吃就行。(不当客服、销售,谢谢)

  • 工作地点:公司、团队搭伙、工厂、私活、兼职、在家都无所谓。(我的小鱼出生了,在家方便照料)

  • 工作要求:

    1)连续工作一段时间(半小时 ~ 1 小时),笔者现在码字,眼睛不是很好,很干涩需要流泪才能缓解,需要休息 5 分钟远眺。(你要是从白天到黑,跟流水线一样,想上厕所都还要憋着;对不起,我拒绝)

    2)可以接受重复性劳动,但是要留出自己学习进步的空间,留出时间看书。(你如果把我当成不知疲倦的螺丝钉,还要对你溜须拍马,我拒绝)

    3)不接受喝酒、陪聊、抽烟、送礼、聚会等行为。(你们的团建要是就这,那我还是自己看书吧)

    4)人员更新不能太频繁。(要是跟韭菜一样,一月换一批人,对不起,我拒绝)

    5)年纪很大的老员工不能太多,很简单,有代沟。我做的一切你不能理解;我讲的所有话都被认为是借口,为什么别人能够做到;我发表的观点被认为是只晓得说别人而不自省;时间长了,不能说话自然很憋屈。

    什么叫年纪不大?(不是指生理年龄)

    不古板,思想年轻,有活力;而不是一天到晚唉声叹气,怪这怪那,自以为看透了一切社会运转规律指点江山而劝别人屈服或放弃,那我非常欢迎你,因为你就是正能量,不会让我心发慌。

  • 工资要求:无所谓(维持基本生活就行),不要勾心斗角、气氛紧张、人人胡思乱想,过的舒服就行。(你要是因为我走到跟前,没打招呼,就给我穿小鞋;对不起,我拒绝)

人才多的是,不稀罕我。的确,没错,但那也不是你消遣我的理由。我的要求苛刻吗?等我快饿死时再考虑降低要求吧。

你如果有意向,可以列出岗位的技术相关要求,若我有不熟悉的,我直接自学完了,再到你那来,给你干活去,这对我小菜一碟。

不爽,想开我,请直接提出来,这有什么大不了的。别把我调来调去,突然增大压力,不行就换人呗,还怕我提出劳动仲裁要求赔偿吗?这样耍手段、阳谋、试探,浪费双方时间?我现在还是太弱了,每一次错误都是一次进步吧。

(有人问,有工作就不错了,怎么还提要求?漫画附图:)

image-20220320104756421

当然我很清楚,能够看到这篇文章的,要么是小白急于寻找信息,要么是好奇;我这罗里吧嗦的,这写了也是白写,所以没有寄托太多的希望。

本书由来

本人就不是正儿八经的程序员,你就把我当成一个天真的菜鸟吧。疫情大家都被困在家中,只能慌着想另谋出路。

培训机构天天打广告,制图、CAD、编程、剪辑...,于是抱着试一试的心态,他们都说学 Java 好找工作,我怎么感觉教人赚钱的人最赚钱?

当然我没去培训机构,而是在网上一篇篇的看文章,因为学习路线图挺多,你在知乎上随便搜下,就有一大群打广告,引流到自己的微信公众号;让我不禁感慨那些熟手竟然都混的这么艰难。

我越看,越觉得自己太滞后了,太脱节了。Java 是上个世纪末出现的,我到现在才知道,仿佛我们这个地方的时间流速比发达城市慢了几千倍。我可能会想,如果要是早点知道就好了。年龄越大越感觉似乎有一道屏障阻碍,不,不对,应该是高中时就有了。

所以感觉自己就像困在茧中发育迟缓的儿童,或者像是一排纽扣,某个纽扣系错位,其它全都错位了。真担心,还没长起来,就 gg 了。我很明白,如果你也能感同深受,我祝你早日挣脱束缚,突破自己的局限性。

由此推出,可能我习以为常的概念,但其他人却一无所知。有人有可能又把不努力、找借口、年轻人吃不得苦、活该落后挂在嘴边,自己这么努力就应该踩在其他人的头上,其他人被淘汰如何如何...那么你已经被彻底异化,自成一个坚不可摧的逻辑系统,你牛行了吧,不想与你多费口舌。

那些本科、985、211 出来的,我不知道他们学校是否与社会脱节,还是不需要培训直接就能胜任工作;又或者那些高材生早就摸索出了属于自己的道路,只待毕业后就能大展身手;真是年轻有为啊。

对我而言,也许受眼界或目光局限,看不远,但我并不认为这是遗憾,种树的最好时期除了十年前就是现在。所以我的目标压根就不是教小白前沿知识,因为当一个新概念传到我们那,可能都不知道被多少人玩烂了;我只是相信还有一些人如同曾经的我一样,没来得及,视野受限,四处碰壁,我希望用自己的时间,能够节省他们的时间。

当然我可没有那么高尚,我很坏的,像是与世界格格不入的异类,缺点也是一大堆,我只是不希望有人跟我一样,踏同一个坑,浪费生命,消耗最美的年华。这个学习时间太长了,还不容易上手,可能学不出什么名堂。(如果你很久以后才看到这篇文章,这本书介绍的内容、软件可能也会过时,2021/07/15 19:29)(没错我还在家啃老,一事无成,十分惭愧啊)

也许这我都已经落后了,但我还是依然要做,我的信念是不会过时的。

没错,我能够帮助到别人,自然很开心。但是如果做老师,我深感责任重大,这是影响学生的终身大事,万一说出来有了疏漏,时间不再来,很难补缺。

但写笔记不一样,某天晚上突然想起,觉得哪里言语不妥,真是语文没学好啊,还可以再优化,脑海中记下来,明天就可以改。

(前几天有人在追问:你做这个有意义吗?我不知道你这个意义是什么意思,是指不能赚钱的事就没有意义,还是其它?这个问题,不能深究,深入一想,你会发现这世上所有的事情都没有意义,还是糊涂一点吧)

帮助说明

你帮助了我,我自然很乐意回馈你。但是请客赞,我不知道你是真心的感到开心,还是出于礼貌,很拘谨,不好意思拒绝,说不出口,又或者只是人的本性如此,不受控制地开心,而不是你的本心;这样猜来猜去的,我看不透,很累。所以我拒绝聚餐,你不能理解觉得我不可理喻那是你的事,这句话放在以前我是不会说的,我只会恭维你而伤害自己,但我现在已经看开了。

我很少出去,一般不喜欢做客,吃饭也不能大口吃,原谅我吧,礼仪修养不到位。你可以透露自己的喜好,我在网上搜罗一下礼物,送给你。(但是现在疫情就算了)

你如果有什么难处,力所能及下,我会帮助你的。

至于借钱就算了,借钱后要么了无音讯,要么就忘了这件事。
我那段时间天天吃白米饭,差点饿死,营养不良;我是不会相信你的,我看人不准,现在很小气、很节省了。当然我没怪谁,是自己的原因,不该轻信任何人。

我听力不好,医生说是脑神经损伤,不可逆了(不可恢复):听力的衰弱、接收频率的丢失、无法被解析,说人话就是你叫我,我听不见;听见了声音,不认为是人在喊我;知道你在喊我,但不知道你在讲什么,需要重复几次,所以不喜与人交流。(放心,文字还是看得懂滴)

所以语言沟通能力方面不是很好,每当亲戚叫我多接触人,出去找个好工作,不要好高骛远,实在不知道说什么好。按我现在的情况,又不想进旁边黑白颠倒的工厂,怕猝死。现在这个鬼样子,像半死不活的游民。如果网上发布信息没用的话,再考虑线下找吧。我不知道我这种情况,到底该如何才好,真希望别饿死。

所以你要热情好客,想拉我四处转转,或者劝我要开朗一点,我其实很困扰的,还要装弄明白了你的意思或愣在一旁,很累,实际南辕北辙。能够忍受我重复问直到听明白的,除了我妈就是我姐,再没有人了,其他人会嫌烦。所以我面对不熟的人,一遍听不懂,问第二遍还是听不懂,就会假装听懂了。由于不怎么接触人,时常感觉自己不近人情,只在家的附近活动,逢年过节不送礼,又不嘘寒问暖走个表面形式,生病也不带礼物看看,没有那些乐呵呵的人受欢迎,我自认为挺讨人嫌。

哦,你如果想招聘我,想好这一点,我不适合与客户打交道的。希望以后不会饿死吧,否则在全中国也是独一份笑话。突然想到了笨手笨脚像一个陀螺,用来形容我茫然失措的样子真贴切。

有人就说,为何要说出来呢?这事不是应该瞒着吗?你还指望有人可怜你吗?是不是博同情?

比如网络评论,对于旁观者,感觉自己说出的话就好似一滴水,不会对别人造成影响,每个人都是如此想,肆无忌惮地发表自己的猜测,被有心人牵着鼻子走,又或者抱着看热闹的想法,不下水,站在岸边,很清高;恶终于汇集在某个地方,超出了承载极限,谁来谁直接淹死。但是人唯一能够吸取的教训是人永远不会吸取教训,只会认为与自己无关。

也不排除很强的煽动性,情绪急于发泄。都是普通人,我也难免犯错,时常告诫自己,别冲动,仔细想想,是不是又被人带节奏了。

首先我不知道你为何会有如此的想法,或许你已经心被污染变质了,那么我讲什么都会被认为是理由与借口,你可以关闭这个页面,我不想与你浪费时间去争论对与错。

其次,我之前一直都是这么做的,深深的掩埋,并以它和内向为耻,当作人生的缺陷,埋了二十多年,经历过多少风风雨雨,内心翻过多少次惊涛骇浪。认为我受过的欺负、犯过的错、所有负面不幸的源头都是来源于它,就像多米诺骨牌,是它让我不快乐、不自信直到变了样子,否则应该有更好的人生,至少可以有信心找到工作。

我很早之前就听说过:不要试图改变他人,因为他人无法改变,要从自己身上找原因。每次出现问题,不用别人说,自己就开始把矛头指向自己。现在发现改变自己也很难,之前一直对自己耿耿于怀,发现只会让事情变得越来越糟,因为与最了解自己的自己对抗,这是一件多么愚蠢的事,它总能找到内心最柔弱处,给你致命一击。

于是学会了拥抱自己,接纳自己;哪怕自己有太多的缺陷与不足,拥有这个身体已经值得了,没有必要追求过多,生和它一起,逝也和它一起,它才是最了解我的人,其它都是浮云,没有必要与它不愉快。

于是担子自然就放下了一大半。它再差劲那也是我,不必撇清关系,并且它还是挺好用的,就是忘得快。

如果你看到这,你还是认为是理由,是借口,猜这猜那,心理的压力彷佛无法释放,关了吧,何必浪费时间呢?我与你讲不清楚,要辩论都是你对,什么可怜之人必有可恨之处,你这么好辩,就别来影响我,我好不容易才走出来,不想听你唧唧歪歪。作为普通人的我们活着本来就不容易,生活如此艰难,没必要互相针对。

当然你如果说想同情我,那倒没有必要啊,我这不是聋,只是偶尔听不懂,还可以对话,谢谢你的关心,祝你天天开心,岁月安好。

image-20220319211226182

image-20220319211414076

image-20220319211515985

image-20220319211547033

image-20220319211629972

在最终尝试下,发现数学还是挺简单的。

image-20220319211711191

image-20220319211802840

image-20220319211850676

image-20220319211921329

image-20220319211946650

于是买了几本书,老师明明在视频上讲的通俗易懂,由浅入深,但是编写的大学教材是真的劝退人,几千页啊,战线拉得太长了。并且那段时间在学 Java,于是没再继续了,我只知道一点,不用的知识一定会忘记,所以现在干脆不学了,等用时再补。果然忘才是人类最大的法宝。

image-20220319212006864

自序

第 3 版自序

之前是想要找文献与资料,四处找不到;现在是资料漫天飞,四顾茫然;曾经的我反复横跳,浪费了很多时间与精力,干脆把曾经所做的学习笔记整合起来,方便大家。并且这期间,如果另有收获,会持续更新此书的内容。(学海无涯苦作舟)

本人专科毕业。我始终认为只有自己喜欢的(因为耳朵有问题听不懂讲的啥,只能看书自学吧),才需要学,忽略了高中这不是专项发展,而是筛选人才;那么多的人,企业正好设置为本科门槛可以节省筛选时间;此外你通不过本科,企业难道不会怀疑你的学习能力有问题?(不够努力服从学习命令或智商有问题,二选一,真难抉择啊)既然是为了赚钱,那为什么不选更好的?人才多的去,谁稀罕你这一个。

我倒是不后悔,因为学历与钱对我而言不太重要(本来想说丝毫不重要,但那不行,太装了),还比不上自身学会了写代码的那种喜悦;只是觉得大多数人经过 18 年的学习,转眼间淘汰了一半人,估计都流向工厂的流水线了,太浪费了。

(关于钱,不是没有欲望,只是欲望被削去了;比如我当然也想住大房子,一看要这么多钱,自然就没念头了;然后一看四周,基本生活都解决了,饿不死、冻不死、渴不死;往上看,看不到尽头,填不满的洞;哦,那就没追求了;所以特此声明,别把我当成淡泊名利的高人,我俗不可耐,又酸又穷)

(关于后悔,我的字典中没有后悔两个字,因为回到过去是不可能的,我还感谢这些事对我带来的影响,能够避免我再次犯错,时时让我警惕是否有陷阱,然后帮助其他原地打转的人;备注:我真的讨厌这些错事,还要假装说感谢它,也不能爆粗口)

一直笑着说大不了回家种田,但其实要是真的能够维持生活,没有人愿意背井离乡,出去打工的。我之前提到过滞后性,上一辈人因为这种滞后性,吃够了亏,于是只让我们专心学习,自己在外辛苦打工,承受所有的风险,只为了子代不再重蹈覆辙,以为我们考上大学了以后就能赚很多钱,可以享福了,却忽略了其它方面。

我们都以为学成了,考上了好大学,也许前途就顺了(对不起,我不了解你们到底顺了没有)。但总还有一半人被淘汰了,比如我,父母还是抱有期望的,至少是个大学生啊!至少比我们强吧,结果期望越大,失望也就越大。

其实学校教的东西可用的很少,大多数就是纯粹应付考试。等上了大学后,被忽略的其它方面,弊处就开始显现;上一辈人突然觉得这么聪明的大学生,这点生活常识都不懂?人际交往、整理内务、洗衣做饭、修电脑啥都一团糟?你们在学校学了个啥?换我来吧!废物!你们 90 后当家了,这个社会要完蛋!

我不太在意,我知道他的局限性,他所在的小地方,也就只能看到我,误以为我就是大学生的缩影。但是网上有才有能力的人多了海了,否则你们找工作怎么这么难找。当然工厂、销售...等岗位还是挺需要人的。

(当然不能说,否则又被认为是好高骛远,吃不了苦;这是铁规矩,因为我不够权威,说什么事,发表了什么意见,都会被反对,已经习惯了;人本来就在否定别人的观念中得到真理,所以我认为这没什么,自己默默承受就好了;直到发现自己莫名其妙下本能开始驳斥别人的观念,不能求同存异时,我才明白自己也开始变质了,是因为被反对多了,自然下意识反对别人,我不敢想是否还有其他方面也受到了影响,或许我还不自知,但人都是会改变的,希望往好的地方改吧)

我认为有这些高智商的人材们,社会只会越来越好,但是嘛,对自己的命运不是特别乐观,也许是天天听到:“哎呀,麻搞啊!”。

我希望以后不会固步自封,局限自己的认知,觉得自己经历过这么多的事情,可以一言堂,断定周围人的秉性。因为经验有时效性,且与个人息息相关,在别人身上不一定适用。传递的观念如果别人不听后吃亏掉坑,我就在旁边暗笑,那样太可怕了,那说明我已经变质了,经验此时反而束缚住了我前进的脚步。

警告自己的一句话:当你看到这曾经写下的这句话,如果觉得很幼稚可笑,不想前进了,就说明你已经融化了。那么狠狠地抽自己,往死里抽,别让我瞧不起你,你欠我的。我现在拼死累活地,下决心改变,不是为了让现在的你心安理得的阻碍其他人的梦想,嘲讽其他人,也不是让你吃老本,坐吃山空,别以为这是理所当然,好好想想自己该做什么,是在楼下打麻将与其他人夸天?

当初实习没找好工作,没积累可用的工作经验。辞职后开始学 Java,跟着网上的步骤一步步来,觉得这有什么难的,我好勇的。

那段时间,父亲和亲戚不再问读书成绩的事了,时常问我学了什么名堂,答:我学的这个集合很厉害,底层用多种数据结构存储数据,你看这个双向链...停停停,别跟我讲这个,我听不懂,这么有用,什么时候出去找事?可以赚多少钱?答:额...

得,赶进度吧,花了5个多月的时间,数据结构与算法、MySQL、JDBC、HTML、CSS、JavaScript、Tomcat、Http 协议、Servlet、JSP、AJAX、JQuery、Maven、MyBatis、SVN、Git、Spring、SpringMVC、Dubbo、Linux、SpringBoot、SpringCloud、Nginx、SpringSession、FastDFS、RabbitMQ、SpringSecurity、Shiro、Swagger、CRM 项目...

期间为了方便翻阅和复习,加页码、加目录、记时间、正字复习、画星星、康奈尔...方法效果甚微。

所以以我为反例,别用纸质笔记,很不方便的。

(之前有人问我,5 个月怎么这么慢?其实我之前太贪心了,还想学数学、英语、物理...)

觉得学的也差不多了,开始看招聘,清一色的本科以上要求,这还玩个毛啊。再从网上看看题目,倒是不难,但想流利的说出,还是要背;语文、英语对我还是有点难,真不想把时间花在这无用的试探之上。所以我降低了要求,不得非要与代码搭边,随便啊,别进工厂黑白班、天天 12 小时就行。说到底,我的信心一直被摧残,没被培养起来,所以畏手畏脚,一想到工作,哎呀都是我不行的,干不了,主动失去信心,下贱自己。那么别人看到这个样子,没有一点正能量,只会让现状越来越坏,犹如囚笼之兽。

也不是没有人劝我,江山易改本性难移,固定的思维就像茅坑里的石头难以改变。每次听到劝导,又开始神经发作,万一呢?你到底怕什么呢?谁会吃了你?这是否已经成了本能?我想不通,也说不清了...

我的理智告诉我,我只是害怕未知,本能拒绝去尝试,害怕再次失败,只能尽力维持现状,一旦没有了父母的支撑,把我投入到大海中,要么四肢扑腾,学会游泳,要么淹死。说到底,我还是有很好的父母,坚实的后盾,实在太幸福了,所以才令人感到如此悲哀。再结合到三和大神、26 岁成人被饿死之类的,我能理解亲戚他们的想法。算了,不说了,混成这个小孩样子,也是没谁了,希望能在饿死之前,主动寻求改变吧。没想到还真自证了自己初中时的想法,讽刺啊。

回顾,自己表面掌握了什么高大上的框架,但框架用起来很简单的,底层屏蔽了繁琐细节的具体实现,从配置多个 XML 文件到约定大于配置直接启动,增删改查就增几个注解,改下 SQL 语句,越学越简单,只是要背注解、方法名、操作步骤...才发现我其实也就是只会调下 API,太浅显了,一遇到稍微深层次的问题就扑街。忘了代码就在网上搜索复制粘贴,这不就是搬砖吗?我学到这之后就没学了,就是觉得太浅了,简直把我当做硬盘在用。这些方法名,记流程有个鬼用,时代一换,又得重新开始。

我觉得是基础没打好,也许是哪里走错,之前学的不够系统,又把 JavaSE 内容看了一遍,尚硅谷、动力节点、狂神说...,收获不大。

终于下定决心,这 Java 内容之多,之繁杂,总得有人要整理一下节省小白的时间吧,反正我也找不到工作,还在鲤鱼打挺,拼命扑腾,还不如把时间花在小白身上;为了帮助和我一样的人,避免踏入同一个坑,开始本书的第 1 版制作:

在这里插入图片描述

在这里插入图片描述

当时正是过年,前前后后忙了几个月。又被打击了一顿,我在家里游手好闲、不学无术?算了吧,反正也没用,不搞了,自闭中。

但是越看越觉得这个笔记不对劲,写的这么粗略,新手能够看得懂吗?强行驱动自己。

然后又看了韩顺平老师的课程,他总结的学习方法很不错,先 demo 再写注意事项。然后由此编写了第 2 版:

初入门时 JDK 安的是 15,(应该是 8,做第一版教程时才应该把 8 删了,重新下了 15)当我重新准备下载时,发现页面找不到了,这才知道长期支持版本是什么东东。

好吧,为了回顾当初下载软件时遇见的问题,场景重现,方便截屏,狠心格式化了电脑,把之前的 Node.js、Linux、MySQL、Navicat、Maven仓库、Tomcat 等一切全部删了,直到现在都还没下载回来。之前放入 GitHub 仓库的代码,比如数据结构,被我认为代码写的太垃圾了,直接清空了(现在就没有参照了,真是白给)。

只剩下 FastDFS、RabbitMQ、SpringSession 的 demo 了。

好,没关系,大不了重新开始。

花了好几个月,废了很大心血,删了改,改了删,半夜突然醒来,打开电脑就只为修改一句话,信心满满,没有多少评论,想着是不是网络上资源太多,唾手可得,根本就不缺我一人的努力,此时突然觉得我都没有找到工作,所学知识之浅,路之狭窄已到头,还敢斗胆发文章,觉得这不是误人子弟吗,于是把之前的所有博客都删了,秉持了不尝试就不会失败的鸵鸟原则。

过年时,想着要不就放弃了,进厂吧?但是我依然记得韩老师的一句话,要勇于分享,还是不可以放弃,不怀疑自己了,相比继续学习下去一条道走到黑看不见归途、在招聘网上浏览不可知深浅的公司,背无用的面试题,相互试探,还不如帮助小白。于是又开始整理了笔记,既然别人没有评论,就证明自己做的还不够好。(提醒小白,JavaSE 只是基础,学完是找不到工作的)

我现在想明白了,去追赶那些前言技术,学习语法,如何使用;只会流于表面,疲于奔命;干脆放弃掉,重新开始。我觉得就连 Java 语法,也变得不太重要,毕竟只是背别人定义的规则,还是表面;但是要写程序,没有办法。

根据纸质资料和粗略的第 1 版,以及网上的博客资料,拼拼凑凑得来了第 3 版,至此只完成到集合部分。并且我还是不满意,决定抽出时间,继续重置。

现在又要看最开始的老版笔记重新写一遍,还好现在没工作,否则抽不出时间写。由于删了之前的博客,有很多都是后来在最初版的基础上修修补补地,可能有很多疏漏、没来得及添加的,恳请大家提出宝贵的批评和建议,以便改正。学习路线就按韩老师的来,先 demo 再声明课堂注意、出题目,按部就班的点还是挺不错的。

(集合那个哈希表实现被我删了,如果想看的话,在 CSDN 与博客园中查看之前的文章,也许之后能补吧)

2022.3.11

第 2 版自序

接受现实,痛定思痛,干脆抽出时间,整理曾经写过的纸质笔记与博客,为尚未踏出校门的同学节省一点时间。

有的地方根本没必要学,直接复制粘贴看看 API 就行,没啥技术含量的。对于那些性格内向的人,心里有很多内容与墨水,但嘴里吐不出话的人,我特别能够理解你的苦衷,珍惜校招吧,避免毕业就是失业的尴尬局面。

有些人的确很聪明,在这里我不想扯勤奋与努力,以前也讲过,这只是表象,何况对于有些人也真的很难,考虑到通用性,内容稍微细一点,不要嫌我啰嗦。

我已经很知足了,阳光、空气、可以动的四肢、能计算 1 + 1 的大脑,没用什么遗憾了。对我而言,健康远比时间、金钱、技术重要。不对,这该死的技术,这抵挡不住的魅力啊!!!

真的好怀念魔兽,如果阿尔萨斯王子没走屠杀线一定会有美好的结局吧。

2021.7.4

第 1 版自序

最近学习了 MarkDown 语法与五笔打字,打算把纸质笔记整理成书,帮助大家。

经过一段时间的摸索中,得出了以下结论,希望对新手有帮助。

1、删除无效的软件

比如一直让你刷刷刷,停不下来的。因为你每次刷,都在期待下一个视频对你有用,但很大的可能只是满足了你的多巴胺分泌。

这种大量占用时间碎片,令人上瘾的软件,可以说是一种毒瘤,我想不通为什么要研发它,钱真的很重要,但也不至于这样吧。

2、工作与学习之间的平衡

公司都是重复性劳动,没有实际上的经验提升,还要担心上级领导的试探,同事的打压,构建话术。下标后自学也只能学习 1、2 个小时,并且还不包括动手尝试的环节,能够学到手的知识十分浅显。等学完,天都换了。

并且公司本质上是私人组织的、有了好点子想变现、以盈利为目的的结构;你想想你要是老板,谁不行直接替换掉,反正人才多的是,为何还要等你慢慢成长,真以为自己是潜力股吗。

但是辞职也不可取,长时间在家,没有了生活来源;走在路上还要被婆婆们嬉笑。(我不知道农村上一辈人是否都是这样想,一个人在家时间长了,就会被认为好吃懒做,窝囊废)

此外亲戚们都不会理解,最亲的人也会骂你不中用,你给他也讲不明白,还会被觉得十分可怜。一开始还可以打哈哈,说自己已经毕业了,在学习编程;但之后呢?这条漫长的学习之路,不同于进厂教教就能直接上手,上一辈人无法理解的。

我想提醒你,你是否也感觉大学的课完全没必要上,但我们也许还如同高中一样,按部就班,讲什么就听什么,那么到了毕业就等于失业,你应该抽空把自己的爱好发扬光大。如果等到上班再学,比如高代,其他人会怎么想?不会觉得你太装?

结论:请好好珍惜大学的时光,那是唯一适合自学的时候。否则你要承担额外的精神压力,扛不住人就废了。

3、适当约束自己的好奇心

不要看到什么都想学,什么都想买,一直在搜,知识太多,你学不过来的。你先在网上搜索,比如后端的整套知识点,按顺序来,一心一意,一套教程为主,有疑惑的再去别的地方比对。不要没事就搜索一大堆资料收藏,又不开始,资料一定要精简,那些看上去有用的知识但短期用不上的,直接取消收藏。等你到了这步,再找资源,别做松鼠。

关于难度高的,可以先跳过,记录下来,后面再补上,比如数据结构、JVM 底层、多线程与高并发、GUI 等等...别把初学时间浪费在这上面。

不要背代码,要掌握原理,方法可以到 API 文档上查。之前基本都是概念上的东西,理解就好了,但学到集合、IO、常用类如 String,只背方法名一定会消灭你学习的兴趣。

如果学习资料抛出一大堆让人心痒痒的新名词,操作不讲规则与原理,没有容易理解的例子,只是像背或粘贴似的敲打代码以及一大堆的命令控制流程,那么我劝你趁早跳过,用时再翻阅。

4、管理好精力

并不是一直在同一个地方枯坐,工作效率才会高。

要合理分配精力,因为精力是有限的。学习并不是生活的全部,如果你整天扑到学习上,只会感动自己。随着精力的消耗,自控力的减弱,一定会在某天突然崩掉,开始变得什么都没有兴趣,行动力拉到最低,即使强迫在学,也只是枯坐原地,享受着左耳进右耳出的枯燥感。

早起别熬夜,每天一定留至少 30 分钟的时间午睡。(为了第 2 天的精神良好)学习时推荐使用番茄钟,每过半小时就休息一小会,合理分配精力。(休息时不要看电子产品与动脑筋,要适当远眺)

此外,揣测他人的想法,也会大量消耗自己的精力(不要内耗,不要管内心的负面想法,让它无能狂吠);如果没有人支持你、理解你,别理会,做出成绩给他们看。

5、学好英语

没什么说的,英语真的很通用很重要,为了阅读懂优质的国外资料。看着机翻的我太拉跨的,简直是哑巴英语。学不会也没关系,就算关了一扇窗,把开这扇窗的力量用到别的地方去,一定不会浪费的。

6、必学的知识点

从大多招聘岗位的要求取出交集:

IO、集合、JVM、多线程、Spring、SpringBoot、SpringMVC、MyBatis、Dubbo、SpringCloud、JavaScript、Vue、MySQL 与 Oracle 取其一、SQL 调优、Redis、Tomcat、Nginx、Docker、Zookeeper、RabbitMQ、Kafka、Linux、HTTP 与 TCP / IP 协议、Socker、Maven、Git、AJAX、ElasticSearch

剩下的知识,应聘意中岗位时再选择性补全。

7、选择书籍还是视频

视频时间看完所需时间更长,但可以一步步来,如果章节内容划分合理,每个视频时常合适,学习者更轻松完成每个目标,掌握自己的进度。适合初学者。

书籍花费时间较少,但经常有断节之处,初学者搞不明白缺少哪一个环节,看着晦涩难懂的文字,翻不了几页就草草放弃,适合耐得住性子的人。

8、不要过分追求完美(承认自己的不足之处)

想做就直接放手干,不要计划的那么周全,稍微一有变动,就放弃目标,想明天再做。是吧,别觉得只有从容不迫、不慌不忙、按部就班地才叫做事,而达不到自己的心理预期就不做了,大多数人都是计划赶不上变化,被搞得灰头土脸的。

另外人都是有惯性的,如果设置了太高的目标难度,只要有一天没坚持下来或不想做了,那么最终结果一定是放弃。

这不禁让我怀疑,以前对生命的定义。我本来以为生命是一种奇迹,我感到自豪,超脱于物质之上;比如从下坡推一个石头,它只会毫无疑问的滚落下去,而我们可以做出反应。

但经过太多的事后,我发现生命的本质与死物没有太大区别;生命就像是一台精密的操作仪器,如同电脑、机器人,只不过比它们先进点。

接收输入做出反应,将应对方式与最终结果存储;等下一次事件再发生时,可以不断优化脑海中存储的应对危机的方法,达成自我学习的本领。

9、学会分享

不要闭门造车,要发在各大网站上分享,Markdown 语法如果你都会了,直接发在博客网上。不要觉得自己技术菜。

第一,人人都有开始,你发出来了,别人才能纠正你的错误,避免成为井底之蛙。

第二,你又开始自耗了,不停地在脑海天人交战,一顿脑补:会不会万一发出来被人嘲笑怎么办?...于是藏着掖着,生怕别人知道,出丑,事情还未做,就想一系列的后果,别人有多可恶。我觉得世上还是好心人多,当然不要被零星几个恶评就忽略了大多数支持你的人。

第三,百分之 99.9 的人根本刷不到你的文章,或者一下就 × 过去了,即使刷到了,那还有 9.9 成人浏览刷的一下就关了,评论的那是少之又少,凤毛麟角。如果帮助不到他,谁还关心你是谁,最多充当局外客感到可笑。当你还在纠结别人的看法时,纠结要不要做时,别人根本记都不记得你。我们在网络时代那是十分渺小,沧海一粟,很快被淹没,就算有弄潮儿掀起了几朵浪花,也会很快平息,所以别再纠结丢不丢脸了。

10、关于努力与勤奋

有人经常说,要自律,要吃苦,要努力,才能成功,你看看这些成功人士都是这样...努力才能得到一切,才能成功。但我抛出一个结论:努力与吃苦,并不能成功,也不能改变命运。

他们忽略了一个东西,自律、吃苦等只是个表面行动展现出来的结果,并不是成功的原因。比如你打王者,技术很菜,但是你就想升段位,不用别人提醒,开了一把有一把,一直连跪,日夜颠倒,身体早就向你警告了,这种违反本能的行为真够自律的。不打一定不会上王者,打了无数盘由于技术太菜,也不一定能上王者。

如果你真心地想要完成某个目标,你不会觉得这是折磨的。再次声明,不是自律、努力才会成功,它们实际是想到达成目标,而自发控制自己身体机能活动的行为。

友情提醒:全身心很耗精力,记得番茄钟打断此状态(半小时),休息的时间眺望远方,不要看电视、玩智能设备,否则越来越累。

11、学完要多久?

如果你不复习,不怎么练,只看视频的话,最多半年。能够记住多少看命。

正常一年半(每天 8 小时以上不间断)

12、是不是很难?

相比越到后面越抽象,一环扣一环的数学,Java 其实还算好,小白也能调用方法完成工作,理解一下就行,屏蔽了底层如何实现的繁琐细节,看看 API 即可拿来用。

至于为什么一看就会,一敲就废?是不是我没有天赋?

说实话,这些东西不会就跳过,以后再补,只要学会调用方法,看看 API 就行。还没有达到拼天赋的地步,努力也无需拼,努力只是外表展现的结果,而不是因,若你感觉自己很努力了,很痛苦,就像我之前说的这样,你想想哪里出现了问题,是不是真的不感兴趣,居然会觉得要强逼自己,努力才会成功?想着人只有逼逼自己才行?

话说回来,不会不是真的完全不会,而是你看时觉得很正常,但一到做时脑海中缺少一些关键片段,甚至连思绪的头都没有,无法串联成珠,往往出错,其他人只不过是由于过往经历(熟能生巧)或者下自然地就补齐了这个漏洞。

没必要担心,如果你接触它的时间过长,会弥补的。不用特意寻找解决它的办法,多看看就行。(把同一个知识点学三遍差不多就熟了)

此外我觉得人略微笨些,是好事,意味着你能够帮助这世界绝大多数人,不会出现理所当然,而一些人却不能理解的事,知道哪里有槛,知道一些人哪里有误区。只要你走通了,其他人就能走通。

花自己的时间,让更多人节省了时间,值。努力活完短短的一生,将所得成果留给后代分享,人类真的是很了不起呢。

2021.2.11

第 0 版自序

今天是网上学习 Java 的第一天,我都是自学,根据学习路线图一篇篇在网上搜来的知识。

本人才疏学浅,感悟还不够深,只能根据些许痕迹揣摩出背后道理。主要是臆想成分居多,如果有什么不对的地方,还请各位大师指点,大家一起共同进步。

另外希望把已建立的认知体系撕开一个口,推倒。包容,承认自己的失败,不要斗气就认这个死理,大不了掌握其它方法重头再来。

2020.6.13

第一章 JDK 下载及准备工作

内容导视:

  • Java 介绍
  • JDK 下载
  • 编写代码前的准备
  • Typora 软件简单使用
  • 常用的 DOS 命令
  • 总结回顾
  • 脑海练习

1.1 Java 介绍

内容导视:

  • Java 简介
  • Java 技术体系
  • 前后端的工作内容
  • Java 语言特性
  • Java 用途

看不懂就跳过,这里不是重头戏,说实话,挺无聊的,直接跳过也没问题。(我只教如何开车,不教车的来历、发动机缸数、如何运转;你觉得只是浮于表面,没办法啊,又不是科班)

1.1.1 Java 简介

Java 最早是由 SUN 公司(已被 Oracle 收购)的 James Gosling(詹姆斯·高斯林)在 1992 年开发的一种编程语言,最初被命名为 Oak,目标是针对小型家电设备的嵌入式应用,结果市场没啥反响。谁料到互联网的崛起,让 Oak 重新焕发了生机,于是 SUN 公司改造了 Oak,在 1995 年以 Java 的名称正式发布,原因是 Oak 已经被人注册了,因此 SUN 注册了 Java 这个商标。随着互联网的高速发展,Java 逐渐成为最重要的网络编程语言。

有兴趣查看以下文章,了解 Java 发展历史

此外 JDK1.5 与 JDK5 是一样的意思。因为比之前版本的变化大,以此作为区分,表示与众不同。就像美猴王自封齐天大圣,都是一个人(猴)。

此外还有 J2EE 、JavaEE,只是叫法不同,不必纠结。

正式发行名称 昵称
JDK 1.0.x Java 1.0
JDK 1.1.x Java 1.1
Java 2 Platform,Standard Edition,v1.2 Java 2
Java 2 Platform,Standard Edition,v1.3 Java 3
Java 2 Platform,Standard Edition,v1.4 Java 4
Java 2 Platform,Standard Edition,v5.0 Java 5
Java Platform,Standard Edition 6 Java 6
Java Platform,Standard Edition 7 Java 7
Java Platform,Standard Edition 8 Java 8

1.1.2 Java 技术体系

分成了三个技术体系

(以前被称为 J2SE、J2EE、J2ME)

JavaSE(Java Standard Edition):Java 标准版,包含核心的类库,主要开发桌面应用(如 Windows 下的应用程序)。允许您在桌面和服务器上开发和部署 Java 应用程序。JavaSE 和组件技术提供了当今应用程序所需要的丰富的用户界面、性能、多功能性、可移植性和安全性,并为 JavaEE 提供基础。

JavaEE(Java Enterprise Edition):Java 企业版,为开发企业环境下的应用程序提供的一套解决方案,包括 Web 网站后台开发等。该技术体系包含的技术:Servlet、JSP 等。企业版本帮助开发和部署可移植、健壮、可伸缩且安全的服务端Java 应用。JavaEE 是在 JavaSE 的基础上构建的提供 Web 服务、组建模型、管理和通信 API。

JavaME(Java Platform Micro Edition):Java 微型版,JavaSE 的瘦身版。主要做嵌入式开发。 JavaME 是专门为资源受限的设备设计的,如为 M2M、工业控制、智能电网基础设施、环境传感器和跟踪等的无线模块、手机、PDA、电视机顶盒和打印机上运行的应用程序提供一个健壮且灵活的环境。自从安卓系统出来后, JavaME 就用的比较少了。

JavaSE 是整个 Java 平台的核心,做 Java 后端先学 JavaSE。

1.1.3 前后端的工作内容

前端

编写 html 代码搭建一个框架展现网页内容,如图片、文字、视频...,打开浏览器的任意网页,按下 F12 可以看到网页对应的 html 文件

用 CSS 技术美化页面,指定 html 标签的位置、样式等;

用 JavaScript 语言控制与用户的交互,比如网页弹窗、动态改变网页内容、验证登录信息、跳转页面等。

例:点击登录页面,输入用户名与密码,按下回车,会触发事件执行 JavaScript 代码,给用户响应(登录失败或成功)。

可以说前端相当于前台,是可以看的见的内容。

后端

接收从前端页面或其他后端服务传递过来的请求,处理业务逻辑,对数据库中的数据增删改查 CRUD。

给调用者一个响应,如把数据返回给调用者、操作是否失败、返回对应的 html 代码等,用户是看不见的。

例:接收到前端传过来的用户名与密码,查询数据库中是否存在,若不存在返回用户不存在。前端接收到后,改变页面信息给用户提示。

不限于使用哪种编程语言,只要能把正确的数据返回给调用者即可。

要保证访问量很大时(同一时间内能够处理尽可能多的请求)而服务器不宕机、响应时间短不至于用户长时间等待、多个用户访问时保证数据的一致性等。(高可用、高并发、分布式、自动化)

1.1.4 Java 语言特性

Java 是一门编程语言,特性如下:

1、面向对象

Java 以类为结构组织代码,对对象、继承、封装、多态、接口、包等均有很好的支持。为了简单起见,Java 只支持类之间的单继承,但是可以使用接口来实现多继承。使用 Java 语言开发程序,需要采用面向对象的思想设计程序和编写代码。

如果不想使用此特性,Java 也可以写出面向过程的代码。

2、平台无关性

一次编写,到处运行(Write Once,Run any Where)。因此采用 Java 语言编写的程序具有很好的可移植性,而保证这一点的正是 Java 虚拟机。在引入虚拟机之后,编译后的 class 文件可以在不同的平台上运行,不需要重新编译。

3、简单性

Java 语言的语法与 C 语言和 C++ 语言很相近,使得很多程序员学起来很容易。对 Java 来说,它舍弃了很多 C++ 中难以理解的特性,如操作符的重载和多继承等,而且 Java 语言不使用指针,加入了垃圾回收机制,解决了程序员需要管理内存的问题,使编程变得更加简单。

4、解释执行

Java 程序在 Java 平台运行时会被编译成字节码文件,然后可以在有 Java 环境的操作系统上运行。在运行文件时,Java 的解释器对这些字节码进行解释执行,执行过程中需要加入的类在连接阶段被载入到运行环境中。

解释型的转换工具称为解释器,程序在运行时使用解释器。每翻译一句,就执行一句,效率低,但跨平台性能好。

编译型的转换工具称为编译器,事先把源代码交给编译器,它一下子全部翻译,得到编译后的代码,可以直接被机器执行。

例如 JavaScript 语言有编译型的转换工具,如 chrome 的 V8 引擎,也有解释型的转换工具如 Netscape Navigator 的 JS 引擎。

5、多线程

Java 语言是多线程的,这也是 Java 语言的一大特性,它必须由 Thread 类和它的子类来创建。Java 支持多个线程同时执行,并提供多线程之间的同步机制。任何一个线程都有自己的 run() 方法,要执行的方法就写在 run() 方法体内。

6、分布式

Java 语言支持 Internet 应用的开发,在 Java 的基本应用编程接口中就有一个网络应用编程接口,它提供了网络应用编程的类库,包括 URL、URLConnection、Socket 等。Java 的 RIM 机制也是开发分布式应用的重要手段。

7、健壮性

Java 的强类型机制、异常处理、垃圾回收机制等都是 Java 健壮性的重要保证。对指针的丢弃是 Java 的一大进步。另外,Java 的异常机制也是健壮性的一大体现。

8、高性能

Java 的高性能主要是相对其他高级脚本语言来说的,随着 JIT(Just in Time)的发展,Java 的运行速度也越来越高。

9、安全性

Java 通常被用在网络环境中,为此,Java 提供了一个安全机制以防止恶意代码的攻击。除了 Java 语言具有许多的安全特性以外,Java 还对通过网络下载的类增加一个安全防范机制,分配不同的名字空间以防替代本地的同名类,并包含安全管理机制。

1.1.5 Java 用途

1、Android 应用

许多的 Android 应用都是由 Java 程序员开发者开发。虽然 Android 运用了不同的 JVM 以及不同的封装方式,但是代码还是用 Java 语言所编写。相当一部分的手机中都支持 Java 游戏,这就使很多非编程人员都认识了 Java。

2、在金融业应用的服务器程序

Java 在金融服务业的应用非常广泛,很多第三方交易系统、银行、金融机构都选择用 Java 开发,因为相对而言,Java 较安全 。大型跨国投资银行用 Java 来编写前台和后台的电子交易系统,结算和确认系统,数据处理项目以及其他项目。

3、网站

Java 在电子商务领域以及网站开发领域占据了一定的席位。开发人员可以运用许多不同的框架来创建 Web 项目,如 MyBatis、Spring 全家桶。

4、嵌入式领域

Java 在嵌入式领域发展空间很大。是指各种小型设备上的应用,包括机顶盒、车载的大屏影音娱乐设备、POS 机等。在这个平台上,只需 130KB 就能够使用 Java 技术。(在智能卡或者传感器上)

5、大数据技术

Hadoop 以及其他大数据处理技术很多都是用 Java,例如 Apache 的基于 Java 的 HBase 和 Accumulo 以及 ElasticSearchas。

6、框架

解决企业应用开发的复杂性,让开发更加方便。

7、软件

制作小游戏、开发工具 IDE 。

1.2 JDK 下载

内容导视:

  • JDK 与 JRE 的区别
  • JDK 下载与安装
  • 如何卸载
  • 如何禁止 JDK 检查更新

即使编写了 Java 源代码,系统也无法直接执行,需要 JDK 提供编译和运行 Java 程序的环境,将代码解释为系统可识别的机器码。

1.2.1 JDK 与 JRE 的区别

JRE(Java Runtime Enviroment):是 Java 的运行环境。面向 Java 程序的使用者,而不是开发者。

如果你仅下载并安装了 JRE,那么你的系统只能运行 Java 程序。JRE 是运行 Java 程序所必需环境的集合。它包括 JVM(虚拟机)、Java 平台核心类库(如 rt.jar)和支持文件。它不包含开发工具(编译器、调试器等)。

JVM(Java Virtual Machine):Java 虚拟机。是整个 Java 实现跨平台的最核心的部分,能够运行以 Java 语言编写的程序。其中的虚拟机屏蔽了底层运行平台的差别。

JDK(Java Development Kit):是 Java 开发工具包,它提供了 Java 的开发环境(提供了编译器 javac.exe 等工具,用于将 java 文件编译为 class 文件)和运行环境(提供了 JVM 和 rt.jar 即 Runtime 辅助包,用于解析 class 文件使其得到运行)。

如果你下载并安装了 JDK,那么你不仅可以开发 Java 程序,也同时拥有了运行 Java 程序的平台。JDK 是整个 Java 的核心,包括了 JRE 和 开发工具 jar 包,如 tools.jar。

核心类库:主要是开发经常使用的类库,避免重复造轮子。如 java.lang 下的 String、包装类等,已经被编译成了 .class 文件,需要时直接拿来用,不用自己重新写一份。

JDK > JRE > JVM

如果你只是想运行 Java 程序,就只安装 JRE 即可。

1.2.2 JDK 下载与安装

JDK 下载地址:https://www.oracle.com/java/technologies/downloads/

有 JDK7、8、11,通常使用的是 JDK8、11,因为它们是长期支持版本,一般的版本支持半年就不再显示。此时的你点开链接,说不定已经看不到 JDK7 了。

LTS 代表长期支持的版本。

Oracle 产品支持的三个策略:https://blog.csdn.net/iteye_21199/article/details/82305640

版本的有效时间:https://www.oracle.com/java/technologies/java-se-support-roadmap.html

JDK8 扩展支持到 2030 年,Oracle 将每三年指定一个版本作为长期支持版本。

查看自己电脑位数

x86 是 32 位,x64 是 64 位。

打开文件资源管理器,右键此电脑属性查看系统类型是 64 位操作系统,还是 32 位。

根据自己的系统、位数决定下哪个

比如我的电脑是 windows 系统 64 位,我使用的是 JDK8,按图选。

特别说明

需要自己创建账户,若不想可在网上搜索 JDK8 下载,或下载最新版本,此时是 JDK16,下载 zip 和 exe 格式的都行。我将网盘链接放在了资源地址这章中,需要自取。

安装

如果下载的是 exe 文件,直接双击,指定安装目录,一直下一步,就安装成功了;


(安装后我又卸了,使用了 zip,所以地址前后不一致)

是 zip 解压即可,点击解压后的文件夹,地址栏上显示的就是安装目录,要看到 bin 和其它目录,如图:

认为安装目录是 D:\cqh_environment\Java 就错了。

记住 JDK 的安装目录,配置环境变量要用

安装好后,看看目录:

bin 目录存放命令,如常用的 javac.exe、java.exe,用于编译,运行程序。

lib 存放着 jar 包,如 dt.jar 是运行环境类库,存放了 Swing 组件;tools.jar 是工具类库,用来编译与运行 java 文件。

src.zip 存放着 Java 源代码压缩文件。

rt.jar 在 jre\lib 中。

解释

我们编写源代码使用的文件后缀为 .java,这种 .java 文件经过编译生成 .class 文件,多个.class 打包放在 .jar 包中。

1.2.3 卸载

呃,这只是教你如何卸载,并不是现在让你卸载...

打开控制面板/卸载程序,找到 Java。

或者打开 Windows 设置/应用/应用和功能,单击要删除的软件,会弹出卸载字样。

如果你不知道如何打开它们,请用百度搜索,如如何打开Windows设置;其实由很多问题都已经得到回答,没必要重复造轮子。学会使用搜索,对自学很有帮助。

卸载成功后,所有目录名带 Java、Sun、Oracle 的一律删掉,如:

删除安装 JDK 的目录、删除 C:\Program Files (x86)\Common Files 和 C:\Program Files下的的 Java 和 Oracle 目录、C:\Users\用户名\AppData\LocalLow 下的 Oracle 和 Sun 目录、C:\Users\用户名\AppData\Roaming\Sun。

1.2.4 禁止 JDK 检查更新

这是可选项,不是必须要做的,因为我觉得挺烦。

打开控制面板\程序\Java,取消勾选自动检查更新,不检查;

高级\应用程序安装\从不安装。

1.3 编写代码前的准备工作

如果你是什么都不懂的新手,请别慌着写代码,还有如下几件事要做:

内容导视:

  • 为什么要写笔记
  • 使用记事本编写源代码
  • 如何学会双手打字
  • Windows 系统常用的快捷键
  • 一点建议

1.3.1 为何要写笔记

为了对抗遗忘,可以快速回顾、促进理解、加深记忆,将知识有条不紊地归类,提炼反思应用。

不建议使用纸质的笔记,记录麻烦,不方便携带,有老化被撕毁的风险,摘抄代码时不能 ctrl+c 快速复制粘贴。

推荐使用 typora 软件、博客、等各大网站记录。

1.3.2 编写源代码使用的记事本

使用系统自带记事本编写程序,按下 tab 缩进一大节,逼得我每次使用 4 个空格,回退也难;关键字没有颜色,不易于识别与查看。

下面介绍几个更好的工具,安装后,右键文件选择打开方式即可。

EditPlus

建议网上搜下汉化版的,下面是官方的收费的。

下载页面:https://www.editplus.com/download.html

有 30 天的试用期,过后要购买许可证。

Notepad++

下载页面:https://notepad-plus.en.softonic.com/download

Download 就是下载的意思。

如何设置主题

设置\语言格式设置\选择主题,此外还可以根据不同语言设置样式。

image-20220314193213707

image-20220314192900107

Sublime Text

官网:https://www.sublimetext.com/

Visual Studio Code

官网:https://code.visualstudio.com/

Atom

官网:https://atom.io/

不能指定安装目录;这种是以项目的方式管理文件。

image-20220315100638692

也可以搜索一下其他的文本编辑器,看哪款适合你。

编写代码

打开刚刚下好的软件,输入源代码,最后 ctrl+s 保存,另存为 First.java。但是现在还不到写代码的时候,下一章好吗?

1.3.3 练习双手打字

一个指头敲字,一边看键盘,一边看输入的代码,很容易出差错。

既然选择了在电脑上打字,就要提高自己的指法速度,敲代码和写笔记才会快,两只手共同配合。

不用担心,我也这么走过来的,虽然一开始没有单只手指头快,但坚持下来,不看键盘,手势正确,打字速度会有明显的提升。

推荐使用金山打字通。

下载页面:http://www.51dzt.com/

从第一步,跟着图中手势位置慢慢打,差不多跟着敲一个星期,就基本实现盲打了。

页面上有金山打字通的下载,点击下载。

下载好后,双击执行 exe 文件,安装界面会跳出是否安装其它软件,根据自己需要确认是否勾选。

安装好后点击新手入门,练到不用看键盘,打字速度超过 30~60 字/分钟差不多够用了。(只需练习英文部分即可)

1.3.4 Windows10 系统常用快捷键

掌握常用的快捷键,能够极大地提升效率,节省时间。

如果是有触摸板的笔记本电脑。单击是鼠标左键,双击是鼠标右键。

请打开 windows 设置\设备\触摸板查看:(Windows + i 打开设置)

下面是我总结的常用几个快捷键。如 Ctrl + A,在电脑键盘上找到这两个键,同时按下去即可触发全选操作。

如果打不出中文,怀疑是按 Caps Lock 开启了大写或者连续按下 Shift 启动了粘滞键,再次按下此键即可恢复。

提前说明:

Ctrl + + 指同时按下 Ctrl、+ 这个键,别看见两个加号就懵了。

文本相关

先选中文字,Windows 键是 Alt 左边的

内容如下:

  • 常用的粘贴、选中、删除文字的快捷键
  • 翻页、浏览文字的快捷键
  • 切换输入法、中英转换
操作 快捷键
跳过单词 Ctrl + 左右箭头,可配合 Shift 使用选中文字
选中文字 Shift + 箭头、Shift + Home/End/Pgup/Pgdnd
复制 Ctrl + C
粘贴 Ctrl + V
全选 Ctrl + A
撤销 Ctrl + Z
查找 Ctrl + F
替换 Ctrl + H
删除文字 Del、Backspace
上翻 Pgup Pause
下翻 Pgdn Break
行首 Home
行尾 End
页首 Ctrl + Home
页尾 Ctrl + End
切换当前语言下的输入法 Shift + Ctrl
切换输入法 Windows + 空格
中英文切换 Shift、Ctrl + 空格
切换语言 Shift + Alt

热键相关

若桌面崩了,使用快捷键打开任务管理器,运行新任务,输入 explorer 后回车。

内容如下:

  • 创建文件、查看文件属性
  • 切换窗口,窗口最大化、最小化
  • 切换桌面,查看桌面
  • 截屏
  • 放大镜
  • 快捷方式打开应用、资源管理器

有的快捷键按下去时讲究先后顺序。

例:如 Alt + Tab ,先按住 Alt 键不要松,再按 Tab,有先后顺序(同时按也行),自己试试就知道我在讲什么了。

← 指的是左箭头。

说实话我向来很反感背知识,随用即取就行。但是那面试题人人都背,你不看看,万一被难倒了怎么办?算了不考虑这些,下面这些快捷键你只看看经常使用的即可。

操作 快捷键
改变桌面图标大小 按住 Ctrl + 鼠标滑轮滚动、触摸板两指缩放
将文件放入回收站 Ctrl + D 、 Del
永久删除文件 Shift + Del
创建文件夹 Alt + 2
查看当前文件属性 Alt + 1
所有窗口最小化 Windows + D 、 Windows + M 、三指下滑
所有窗口最小化又还原 双击 Windows + D 、三指下滑又上滑
当前窗口最小化 Windows + ↓
当前窗口还原、最大化 Windows + ↑
查找文件 Alt +空格
浏览器打开新的标签页 Ctrl + T
浏览器查看下载文件 Ctrl + J
浏览器当前页面静音 Ctrl + M
浏览器切换页面 Ctrl + 数字、 Ctrl + Tab +(Shift)、 Ctrl + Pgup 和 Pgdn
打开新的窗口 Ctrl + N
使当前窗口失去焦点,图层置于底下 Alt + Esc
打开任务管理器 Ctrl + Shift + Esc
锁屏 Windows + L
关闭文件 Ctrl + W
强制关闭文件 Alt + F4
关机 Alt + F4
打开文件资源管理器 Windows + E
将焦点定位到地址栏 Alt + D 、 F4
后退 Alt + ←、 Backspace
前进 Alt + →
返回上一级 Alt + ↑
在窗格、功能区域之间切换 F6
重命名 F2
切换至下一个,配合 F2 有奇效 Tab
有些快捷键再加上此键,实现逆向选择 如 Shift + Tab
即时切换应用 按住 Alt 不要松开单击 Tab 、三指左右滑动
来回切换引用 同时按下 Alt + Tab
切换应用 Alt + Ctrl + Tab 松开,单击 Tab 选择应用后回车
刷新 F5 、 Ctrl + R 、 Ctrl + F5
同一应用不同窗口切换 Ctrl + Tab
浏览器不同窗口切换 Ctrl + Pgup Pause 、 Ctrl + Pgdn Break
创建新桌面 Ctrl + Windows + D
关闭新桌面 Ctrl + Windows + F4
查看已有桌面 Windows + Tab (再按还原)、三指上滑(下滑还原)
切换桌面 Windows + Ctrl + 左右箭头
两个应用分屏 Windows + ←、 Windows + →
放大缩小屏幕 Windows 加 +/-
浏览器放大缩小 Ctrl 加 +/-
打开/关闭管理通知 Windows + A
打开 Windows 设置 Windows + i
锁定、切换用户、注销、打开任务管理器 Ctrl + Alt + Del

截屏

1)快捷键打开截全屏的工具

Windows + W

2)区域截屏

Windows + Shift + S

若点击了截图,照片会在 C:\Users\你的用户名\AppData\Local\Packages\Microsoft.ScreenSketch_8wekyb3d8bbwe\TempState 下保存。

3)截全屏

Windows + PrtScSysRq

PrtScSysRq 键在 F12 右边,保存的图片在 C:\Users\自己的用户名\Pictures\Screenshots 下。

PrtScSysRq

打开画图工具,Ctrl + V 将截屏捕捉。

4)截屏,范围限制在当前工作页面(得到焦点的页面)

解释,比如你打开了 QQ,正在使用它聊天,按下了这个快捷键,只会截 QQ 界面。

Windows + Alt + PytScSysRq

5)录屏,范围限制在当前工作页面

Windows + Alt + R

捕获的图片和视频在 C:\Users\用户名\Videos\Captures 里。

6)游戏栏工具

Windows + G

Alt

打开软件,按一下 Alt ,会有字符提示,并且将焦点定位到菜单栏,此时可按左右键切换功能区,上下(不行就 Enter 回车)键打开功能区。

字符提示会显示出功能的快捷键,例:文件功能区会显示出 F ,代表只需要 Alt + F 就可以打开此功能,弹出的下拉列表一般也有字母提示,按下对应字母即可。(有时需同时按下 Alt )

总结: Alt + 划下划线的字母,可以快速打开菜单。

快速启动任务栏上的软件

你看看你的任务栏(屏幕的最下方),打开应用后可以右击任务栏上的应用图标,将其固定到任务栏,下次直接单击此图标就可以打开应用。或者 Windows键 + 数字,比如

浏览器在任务栏的第 1 个位置,只需 Windows + 1 就可以打开。或者 Windows + T,左右箭头选择后回车。

1.3.5 给初学者的一点建议

我希望你能后来居上,分享你的经验让我开开眼界。

下面是本人经过大量时间总结的经验,但你可以不看,因为没有什么规则可以量身定制。

1、约束好奇心,停止收藏资源

我直接说,你是学到死都学不完的。

资源无穷尽也。不要看到什么都想学,什么都想买,一直在搜,知识太多,你学不过来的。你先在网上搜索,比如后端的整套知识点,按顺序来,一心一意,一套教程为主,有疑惑的再去别的地方比对。不要没事就搜索一大堆资料收藏,又不开始,资料一定要精简,那些看上去有用的知识但短期用不上的,直接取消收藏(也包括我)。等你到了这步,再找资源,别做松鼠。

关于难度高的,可以先跳过,记录下来,后面再补上,比如数据结构、JVM 底层、多线程与高并发、GUI 等等...别把初学时间浪费在这上面,这些东西都是唬人放弃的。

不要背代码,要掌握原理,方法可以到 API 文档上查。之前基本都是概念上的东西,理解就好了,但学到集合、IO、常用类如 String,只背方法名一定会消灭你学习的兴趣。

这东西是一回生二回熟,第一遍不要想着要弄的多明白,简单过一下即可。下次复习的时候,无师自通,我敢说人就是最强的智能机器人。

至于看视频还是阅读书籍,我感悟如下:

视频时间看完所需时间更长,但可以一步步来,如果章节内容划分合理,每个视频时长合适,学习者更轻松完成每个目标,掌握自己的进度。适合初学者。

书籍花费时间较少,但经常有断节之处,初学者搞不明白缺少哪一个环节,看着晦涩难懂的文字,翻不了几页就草草放弃,适合耐得住性子的人。

2、管理好精力

人一天能够利用的时间极其有限,所以要学会合理分配精力。学习并不是生活的全部,要参与家务,如果你整天扑到学习上,只会感动自己。随着精力的消耗,自控力的减弱,一定会在某天突然崩掉,开始变得什么都没有兴趣,行动力拉到最低,即使强迫在学,也只是枯坐原地,享受着左耳进右耳出的枯燥感。

早起别熬夜,每天一定留至少 30 分钟的时间午睡,为了第 2 天的精神良好。学习时推荐使用番茄钟,每过半小时就休息一小会,合理分配精力。(休息时不要看电子产品与动脑筋,要适当远眺)

3、学会分享

不要闭门造车,要敢于发在各大网站上分享,Markdown 语法我会在下节中讲到,你学会了,注册个号,把笔记直接复制粘贴,发在博客网上;不要觉得自己技术菜。理由如下:

  1. 人人都有开始,你发出来了,别人才能纠正你的错误,避免成为井底之蛙。

  2. 你又开始自耗了,不停地在脑海天人交战,一顿脑补:会不会万一发出来被人嘲笑怎么办?...于是藏着掖着,生怕别人知道,出丑;事情还未做,就想一系列的后果,别人有多可恶。我觉得世上还是好心人多,当然不要被零星几个恶评就忽略了大多数支持你的人,这么大的林子总会有几个脑残。

  3. 百分之 99.9 的人根本刷不到你的文章,或者一下就 × 过去了,即使刷到了,那还有 9.9 成人浏览刷的一下就关了,评论的那是少之又少,凤毛麟角。

  4. 对于四处搜索资源的人,是没有精力留下痕迹的,没有用的直接毙掉,有用的看完理解后也直接毙掉;这么快节奏的生活,没人关心你是谁,最多充当局外客。当你还在纠结别人的看法时,纠结要不要做时,别人根本记都不记得你。我们在网络时代那是十分渺小,沧海一粟,很快被淹没,就算有弄潮儿掀起了几朵浪花,也会很快平息,所以别再纠结丢不丢脸了。

  5. 帮助别人就是帮助自己。虽然这个地球少了谁都能转动,但我愿意相信天生我材必有用,自己的不可替代性。

  6. 你已经落后别人太多了,得到的都不是最新的知识;不要求自己跑的更快,但是也要有行动的勇气吧,就算有 1000 个人从众笑你、反对你,我也不会笑你,只会支持你,为你的敢于行动喝彩。

  7. 或者你担心教会了徒弟饿死了师傅,认为自己凭什么白白让别人分享自己的辛苦所得,让那些白嫖怪轻而易举获取到所有。

    呃,我也不反对你,曾经的我认为那些动不动说要分享,文章标题、内容弄得很吸引人;结果在文章底部放了个二维码,说要关注才能获取验证码与资源,我一向嗤之以鼻,这不就是引流吗,能赚多少钱啊?但是现在觉得别人有权力这么做,没有人必须无偿满足你,既然付不了金钱,就只能搭进你的时间和人脉。

    对于那些开源的人,要不是他们的分享,让我窥见一斑,那我现在应该不在家,而是进厂做流水线去了,是不会发文章的,或许抱怨这个世界不公平。所以再次感谢开源的人,感谢你们的无私奉献,你们就是一道光,照亮被淘汰看不见希望的我,至于我的信念就从此转变为萤火虫也可与日月争辉。(不禁想起了一句话:为众人抱薪者,不可使其冻毙于风雪;为大众谋福利者,不可使其孤军奋战;为自由开路者,不可使其困顿于荆棘)很抱歉我现在捉襟见肘,无法回馈你们。

    说实话,现在当我使用手机、电脑、冰箱、自来水等一切产品时,都会惴惴不安,一是因为怕现在习惯了离不开了,但是不了解底层原理,要是他们以后技术垄断,坐地起价...;二是当我还在感叹新技术新发展新气象,日新月异,这些东西如此方便快捷,被制作被运送,傻瓜都能轻松使用。但是到底以牺牲了多少人的自由空暇为代价,令他们如同机械一般麻木,我们却理所当然,嘻嘻哈哈,嘲笑着都是因为不努力,教导下一辈不要学他们,要成为人上人...扪心自问,真的能够心安理得使用吗?平等或许只是伪命题。

4、承认自己的不完美

人无完人,总有顾及不到,犯错的时候。想做就直接放手干,不要计划地那么周全,稍微一有变动,就放弃目标,想明天再做。是吧,别觉得只有从容不迫、不慌不忙、按部就班地才叫做事,而达不到自己的心理预期就不做了,大多数人都是计划赶不上变化,被搞得灰头土脸的。

5、调整心态

如果你学这个只是为了找工作,那么你一定会很痛苦。为了以后不再工作而工作,为了以后享福而选择现在吃苦(为了不再吃苦而吃苦),为了将来而牺牲现在;这种矛盾的做法,并且大部分人实现不了财务自由,如果你只靠出卖自己的时间换来金钱的话。

你想得又得不到,或追赶不上前面的事物,你会处于十分焦虑的状态。你真想财务自由,那么就要垄断其他人的时间,给自己带来利益(用金钱换他们的时间,创造价值收入囊中),或者搭上顺风车。

但我不一样,我写这个,并不奢求得到回报,因为我写这个同时,我就很满足了。

但也不要担忧,如果企业家全都使用机器人或者雇很少的人,短时间的确能够让利润增加,因为减少了给员工那一项的支出;但是员工既是生产者也是消费者,如果他们没有时间买或者没有钱买,就算降低商品的价格,但为了有利润可赚,员工的工资也会降,那就更没有钱买,继续降低商品价格...如此反复,就倒闭了;所以他们是不会让穷人更穷的。

(我只是安慰你,这些玩意早被研究透了,说不定命运都被安排的明明白白)

6、相信自己

可你也与我有着同一样的感受,为什么这些大佬如此牛逼,而自己什么都看不懂,不能理解,沮丧睡不着觉。我觉得这不是你的问题,而是每个人的必经之路。希望你能够坚持下来,最后祝你学业有成,找个好饭碗。

1.4 Typora 软件使用

内容导视:

  • 下载与安装
  • 如何创建 Markdown 文件
  • 常用的 Markdown 语法
  • 常用的设置
  • 官网打不开原因
  • 其它替代软件
  • 自动上传图片

1.4.1 下载与安装

下载地址:https://www.typora.io

往下翻,点击 Windows(我的是 Windows 系统 64 位),点击 Donwload Beta(x64),就会自动下载;

双击下载好的 .exe,

指定安装位置,

下一步next,

选中复选框代表创建桌面快捷方式。

1.4.2 如何创建 Markdown 文件

创建以 .md 结尾的文件,如 test.md,鼠标右键新建/文本文档,双击打开发现怎么还是记事本?

打开文件资源管理器,把文件扩展名和隐藏的项目打上对勾,就可以看到隐藏的后缀和文件夹如 AppData;

此时刚刚创建的文件显露真身,原来还是 txt 文件;右键重命名,把 .txt 去掉,再双击点进去。

1.4.3 常用的 Markdown 语法

此软件使用的是 Markdown 语法,一种纯文本格式的轻量级标记语言。通过简单的标记语法,它可以使普通文本内容具有一定的格式。

md 语法的出现不是为了替代 html,而是更方便书写。如果让我写那么多的 <>,不停思索如何嵌套,写一大堆长长的 css,我会疯掉的。

这款软件它可以你更加关注内容,而不是注意怎么摆弄格式。Word 是边写边在上面的边栏调字体大小、颜色、格式,很不方便。

内容如下:

  • 字体格式:如标题、斜体、加粗
  • 跳转链接:如超链接与图片
  • 内容排列:如表格、有序无序列表、各种图表、分割线

标题

一个 # + 空格,跟上标题内容即可。(Ctrl + 1 是一级标题,以此类推)

# 我是什么人
## 我是第2种人

一个 # 是一级标题,两个 # 是二级标题,依此类推,直到 6 级标题。(越来越小)

复选框

一个减号 + 空格 + [ ] + 空格

- [ ] 锻炼

粗、斜、斜加粗等字体

1、被两个星号包裹的字自动变粗(Ctrl + B);

**我是粗**

我是粗

2、被一个星号包裹的字是斜体(Ctrl + i);

*我是斜*

我是斜

3、被 3 个星号包裹的字是粗斜;

***粗斜体***

粗斜体

4、Tab 上面有一个键,按住 Shift,再按住它,可以打出 ~。

~~废弃~~

废弃

引用

大于号 + 空格 + 内容

> 摘抄自大文豪张三的一句话

摘抄自大文豪张三的一句话

键盘风格

被成对的 kbd 标签的内容。

<kbd>ctrl</kbd>

ctrl+c是复制

超链接和图片

这些地址就是网址。

![图片名](图片地址)
[超链接名](超链接地址)

百度(右击打开链接或按住 Ctrl,再单击此链接)

表格

Ctrl + T 快捷键创建表格,Ctrl + Enter 添加新行,Shift + Ctrl + Del 删除一行。

名称|性别|生日
--|--|--
赵三|男|1213.2.1
名称 性别 生日
赵三 1213.2.1

代码

单行使用`,多行三个`,指定代码语言:

`单行代码`
```java
多行代码
```
```javascript
//实际写法var foo = \'bar\';
```

单行代码

多行代码
//实际写法var foo = \'bar\';

列表

1、无序列表

单个星号 + 空格 + 内容

* 语文
* 数学
* 英语
  • 语文
  • 数学
  • 英语

2、有序列表

数字. + 空格 + 内容

1. 起床
2. 刷牙
3. 吃饭
  1. 起床
  2. 刷牙
  3. 吃饭

3、列表套列表

* 起床  
    * 睁开眼睛  
    * 我是沙福林
* 刷牙
  • 起床
    • 睁开眼睛
    • 我是沙福林
  • 刷牙

大纲

可以把标题列出来,即 # 后的内容。

[TOC]

分割线

三个减号+回车(Enter)


以下内容不需要了解,几乎不用。

甘特图

```mermaid
gantt
        dateFormat  YYYY-MM-DD
        title 这是标题,上面是日期格式年月日
        section 计划表
        准备行李(已完成)               :done,    des1, 2014-01-06,2014-01-08
        买机票(进行中)               :active,  des2, 2014-01-09, 3d
        拍照(计划)               :         des3, after des2, 5d
```
gantt dateFormat YYYY-MM-DD title 这是标题,上面是日期格式年月日 section 计划表 准备行李(已完成) :done, des1, 2014-01-06,2014-01-08 买机票(进行中) :active, des2, 2014-01-09, 3d 拍照(计划) : des3, after des2, 5d

UML图表

```mermaid
sequenceDiagram
张三->> 李四: 你好!李四, 最近怎么样?
李四-->>王五: 你最近怎么样,王五?
李四--x 张三: 我很好,谢谢!
李四-x 王五: 我很好,谢谢!

李四-->>张三: 打量着王五...
张三->>王五: 很好... 王五, 你怎么样?
王五->>张三: 不好
```
sequenceDiagram 张三->> 李四: 你好!李四, 最近怎么样? 李四-->>王五: 你最近怎么样,王五? 李四--x 张三: 我很好,谢谢! 李四-x 王五: 我很好,谢谢! 李四-->>张三: 打量着王五... 张三->>王五: 很好... 王五, 你怎么样? 王五->>张三: 不好

流程图

```mermaid
graph LR
A[长方形] -- 链接 --> B((圆))
A --> C(圆角长方形)
B --> D{菱形}
C --> D
```
graph LR A[长方形] -- 链接 --> B((圆)) A --> C(圆角长方形) B --> D{菱形} C --> D

1.4.4 常用的设置

内容如下:

  • 常用的快捷键:如加粗、标题、表格等
  • 更改风格:如字体颜色、样式,显示代码行号
  • 将笔记导入导出
  • 支持数学符号

快捷键

直接点击上方,查看快捷方式,如点击视图、段落,上面显示了快捷方式更方便触发;或者按住 Alt + O,即可打开格式:如 Ctrl + B 是加粗的快捷键,Ctrl + \ 是清除样式,Ctrl + T 是创建表格的快捷方式,Ctrl + / 是查看源代码...

主题

Alt + T 选择自己想要的主题。

偏好设置

Ctrl + ,

如通用的自动保存选上,每次修改自动保存,不用按下 Ctrl + S。

高级模式选中调试模式,关闭文件后重新打开,右键检查元素(或 Shift + F12),会发现此软件就是一个浏览器,(浏览器按住 F12 键,会打开开发者模式,与这差不多)我们看到的笔记,实际是 md 语法被解析后生成的 HTML 标签与 CSS 相配合展现的页面;现在你再看看 md 语法到底有多方便了吧,这些标签要你自己写该多麻烦。

代码块显示行号

Markdown,将显示行号复选框勾选。

你看左边的1
你看左边的2    

更换主题

学了 CSS 后,再来。

之前创建 md 文件时,给隐藏的项目了打上对勾,代表显示隐藏的项目。其中 AppData 就是隐藏的项目,一般存放软件的配置文件。

C:\Users\你的用户名\AppData\Roaming\Typora\themes 下的几个 CSS 文件代表着不同的主题,如果不满意页面样式,可以修改对应主题 CSS(记得留个备份)或自定义 CSS,重新打开笔记后,可以在主题中看到你的 CSS,随便更换。

补丁:蓝色背景下的 gif 动图字体会模糊,必须在纯色红或白色背景下,gif 动图字体才会清晰,所以取消动图的使用。

将笔记转成其他类型的文件

PDF、HTML 等类型的都行,(without styles 是不带样式即没有 CSS 修饰,自己试试就知道区别了)

或者打开浏览器,使用打印功能(Ctrl + P),无渲染与解析,很差劲。

支持数学公式

按下 Ctrl + , 快捷键打开偏好设置/Markdown/Markdown 扩展语法/勾选内联公式,再用 $某某字母$ 显示不同的符号。

常用的的数学符号写法:

恢复未保存的文件

打开偏好设置,点击恢复未保存的草稿。

image-20220314195918762

1.4.5 官网打不开的原因

它升级到了 1.0 版本了!收费了。

不要惊讶,能够开源一定要有其它稳定的收入作为支撑;否则没钱,功能不会太强大,作者都快饿死了,当然没有功夫贡献自己的力量,进行频繁更新,跟上时代。

不能坚守本心的人会过的很苦:动摇,时刻怀疑自己的决定是否正确;后悔,要是当初如何...现在就...

Typora 代理商:https://typoraio.cn/

最后一个免费版,分享者:王炳明,https://wwe.lanzoui.com/i8PP3wzahrg

其实从来都没有说过免费,之前只是 Beta 测试版,类似于游戏中的公测吧。

作为一个即时渲染,所见即所得,按下 Ctrl + / 就可以看源码,简洁实用,早已习惯,离不开它了。其它的软件花里胡哨,什么功能都往里面加,试图想代替其它同类型的软件,结果搞得不伦不类,十分臃肿。

像其它 md 编辑器,大部分都是双栏丑丑的大屏幕,十分占空间,并且滚动内容时,左右视图不一致,还得分心同时看两边,真的是种折磨。应该让软件配合人,而不是让人记住软件的用法,主次关系要分清。

如果下载的是收费版,记得打开偏好设置\通用,将 Typora 服务器使用国内服务器复选框勾选一下,我怕你连不上服务器,激活不了此软件。

1.4.6 其它不错的软件

下面几个软件几百兆,下载速度也挺快,没有必要存到网盘了。

Joplin

官网:https://joplinapp.org

github下载地址:https://github.com/laurent22/joplin/releases

往下翻,选择一个版本,点击 Assets 选择 exe 文件下载。

与其说是 Markdown 编辑器,倒不如说它是一个同步小云盘、整理目录的大师,不与 Typora 冲突。我暂时还没用,因为我使用了坚果云同步备份文件。你们要是总结了使用经验,欢迎分享。

后续增加

设置中文:Tools\Options\Language,拖到最下面,选择简体中文。

Alt + ?打开对应的菜单栏:


F:文件
E:编辑
V:视图
G:跳转
B:笔记笔记本
N:笔记
T:工具
H:帮助


导入 Markdown 文件:文件\导入,选择导入的是 Markdown 文件还是目录。(不要选带文章前言的,导出时会自动在文章前面加标题、创建和修改日期、时间)

同步

给同步目标上的备份文件加密:选择了中文后,工具\选项\加密,自己启动加密吧。

如何同步到本地:选项\同步,同步目标设为 File system,设置同步目录。


如果删除了同步目标的文件,为了安全(故障保护默认开启),
是不会删除本地文件。

如果删除了本地文件,同步时间一到,同步目标的文件也会被删除。
可以趁着这时间差,从同步目标导入数据到本地。

显示高级选项,自己手动上传数据或从同步目标中导入数据。


如果两个终端数据不一样(同时修改一个文件,为不同内容),会把冲突的文件移到新创建的"冲突"笔记本中,等你处理。

使用外部编辑

使用自己的 Markdown 编辑器:选项\通用选项\文本编辑器命令,选一个能够打开 md 文件的 exe 命令,如 Typora.exe。(你还记得此软件的安装目录吗?)

在 Joplin 上任意选一个笔记,按下 Ctrl + E,自动转用外部编辑器编写文件。

笔记本自定义图标

右键笔记本,编辑 Select emoji,选一个表情。

其他人的使用心得

其他人的 Joplin 软件使用心得:
https://www.zhihu.com/question/436251626/answer/1909305492
https://segmentfault.com/a/1190000038918737

打开扩展语法,在选项\Markdown,根据需要勾选,详细请看:https://lightzhan.xyz/index.php/2020/03/31/joplin-extension-usage/

让我试下:©(c)著作权所有人

把自己电脑当作服务器,同步到手机:https://lightzhan.xyz/index.php/2020/11/15/joplin-webdav/

手机上自己搜索 Joplin app 吧,因为谷歌你们可能访问不了。

Mark Text

下载地址:https://marktext.app/

我安装时报有病毒,就没继续了。我感觉应该没有 Typora 能打。

1.4.7 自动上传图片

你如果使用久了,经常在网上发布文章,一定会遇见这个问题。

把写好的 md 文件,复制粘贴到博客园中。结果你发现图片加载不出来,一看地址,C:\Users\自己的用户名\AppData\Roaming\Typora\typora-user-images\xxx。

这才知道原来图片被保存到了本地中,也难怪网上读取不到。那么你发现了,将图片直接拖拽到博客园的编辑页面,会自动生成网络上的 URL,可以在全网都能访问到。

但是时间长了,一张、一张拖拽也不是事啊。这时就需要图床替我们自动保存图片。

smms 图床

打开偏好设置\图像,

image-20220314203029567

意思是当本地图片被你拖进 md 文件中,会自动上传图片。

点击下载或更新,下好了后会出现打开配置文件按钮,点击弹出 JSON 文件,将以下代码粘贴到这个文件中。

{
  "picBed": {
    "uploader": "smms",//代表当前的默认上传图床为 SM.MS
    "smms": {
      "token": "LFJLSJljlfaoFJOLAF"//这里面的token换成自己生成的token,一定要换
    }
  },
  "picgoPlugins": {}//为插件预留
}

这个 token 如何填?

打开 SM.MS 图床:https://sm.ms/register
自己注册账号后,再登陆:https://sm.ms/login

点击 User\Dashboard\API Token,进入:https://sm.ms/home/apitoken

点击 Generate Secret Token 按钮生成 token,将其填入 JSON 文件。

填完后,保存 JSON 文件。将图片拖拽 md 文件时,如有 Uploading 字样,就成功了。

在 Pictures 可以管理或删除这些文件,可惜根本没法根据 URL 找到图片,时间长了,定位删除图片还是不方便。

说实话我很担心,手贱全删了,导致 md 文件图片全部失效,还是放在博客园中保险些。

Typora 在 Windows 下自动上传图片

目前支持上传的方式有:自建服务器、腾讯云 COS、阿里云 OSS、七牛云 、Github、Gitee(码云)...

作者:thobianhttps://www.zhihu.com/question/56641227/answer/810364545

阿里云

作者:夏2同学https://zhuanlan.zhihu.com/p/138878534

其它图床

免费图床整理,https://withpinbox.com/explore/collection/332056

1.5 常用的 DOS 命令

内容导视:

  • 打开 DOS 窗口的几种方式

  • 进入目录内:使用绝对路径与相对路径演示

  • 常见的 DOS 命令

写出来的 Java 代码,需要在命令窗口中执行编译与运行命令,需要知道如何打开此黑窗口(Disk Operating System)。

1.5.1 打开 DOS 窗口的几种方式

  1. 屏幕最左下方,右击 Windows图标,点击 Windows PowerShell,管理员权限更高,可以修改系统关键文件。
  2. 点击 Windows 图标,往下翻在所有程序中找到 Windows 系统,点击命令提示符。(可以右键以管理员权限运行)
  3. Windows + R 输入 cmd 回车。(最常用
  4. 打开文件夹资源管理器,在地址栏输入 cmd 回车。(其次常用)
  5. 按住 Shift 别松,鼠标右击,在此处打开 PowerShell(S)。

作者:「已注销」,内容:将 Windows10 中的 WSL 添加至右键菜单,https://blog.csdn.net/gulang03/article/details/79177500

1.5.2 进入目录内:使用绝对路径与相对路径演示

下面说的目录和文件夹是一个意思。
输入命令后按下回车才能执行,回车键是 Enter。

由于不是可视化界面,不能像之前一样,点到哪里就跳到哪个文件夹下,需要使用 cd 命令,跳转到某路径下。

路径分为绝对路径相对路径

打开文件资源管理器(Windows + E),随便打开某盘下的文件夹,可以看到地址栏上的路径。假如以 D: 开头,D: 称为盘符,显示的路径称为绝对路径,D:\ 称为 D 盘的根目录(最上一级,不能再上了)。

绝对路径:从盘符开始的路径,能够完整的描述文件位置的路径就是绝对路径。(唯一确定资源位置)
如路径 D:\cqh_environment,指向 D 盘下的 cqh_environment 文件。

相对路径,是以当前路径作为出发点的路径,比如进入当前路径的 a 目录。

首先打开 DOS 窗口,切换盘符。

例:想要到 E 盘下,就输入 E: 后回车,输入 dir 回车查看当前路径下有那些子文件(没有就在该盘手动创建文件夹),使用 cd 文件夹名称 进入此文件夹。

使用 cd a 时,单看这个 a,鬼才知道这是哪个地方的文件夹,在哪里才能找到它,需要结合当前路径 E:\ 才能知道,原来是要到 E 盘下去找 a,那么这个 a 就是相对路径。

可以这么理解,我说北京市某某地址的小区,你马上理解了要在哪去找,这是绝对路径;但我说我家旁边的一家店,你必须先知道我家在哪,再根据我家的位置确定这家店的位置,这就是相对路径。


..:上级目录

.:当前目录

现在回到上级目录,使用cd ..,现在演示一下绝对路径,cd 绝对路径,使用绝对路径时,必须是当前所在盘下的路径。

注意:路径必须存在,你需要把目录创建出来,才能使用 cd 命令进去。

如果使用相对路径,先切换到根目录,再执行 cd a\b\c\d

怎么回到根目录?使用 cd E:\ 吗?或者 cd ..\..\..\..?

还有一种简单的方式 cd \ 即可


一个 cd .. 是回到上级目录,
cd ..\.. 是回到上上级目录。


若文件名太长记不住,可以打出首字母,再按下 Tab 键,也可上下键切换已经输入过的命令,或者你直接将文件拖入这个黑窗口,地址就出来了。

通过刚才的例子,发现跳转路径时,必须是当前盘下的路径,那么还不如使用相对路径,反正盘名写其它盘也没用。解决办法:加个参数 /d 即可。

例:现在在 C 盘下,我要直接到 E:\a\b\c\d,输入 cd /d E:\a\b\c\d 即可。

1.5.3 常用的 DOS 命令

内容如下:

  • 进入目录、返回上级目录
  • 打开常用的软件
  • 清空屏幕
  • 新建、删除文件
  • 查看系统变量
#切换盘符 C:
#查看当前目录下的文件 dir
#改变目录 cd /d C:\a\b\c
#返回上一级 cd..
#直接回到根目录 cd \
#进入子目录 cd 文件夹名称
#清空屏幕 cls
#退出 exit
#查看ip ipconfig
#查看ip详细 ipconfig/all

#打开软件
#打开计算器 calc
#打开绘图 mspaint
#打开记事本 notepad

#查看网络 ping www.baidu.com
#网络诊断 ping www.baidu.com -t
#终止 Ctrl + C

#新建文件夹 md 文件夹名
#新建文件 cd>文件名.后缀
#删除文件 del 文件名.后缀(可带*,*表示任意,小心别把所有东西删了)
#删除文件夹 rd 文件夹名
#打开文件 文件名.后缀

#打包
#把当前的路径下所有打包进a.jar
jar cvf a.jar .
#把当前的路径下所有打包进b.war
jar cvf b.war .
#可以使用绝对路径
jar cvf E:\cqh\b.war .

#查看系统变量的值,如第一个是C:\Windows
echo %SystemRoot%
echo %ProgramFiles%
echo %Path%

#咳咳,你打开环境变量(网上搜,下节也有),左边是变量,右边是值

总结回顾

(不要惊讶怎么这么少,我说过别把大脑当成硬盘,记一个 cd 命令就足够了,记得看完后休息一会,欲速则不达)

Java 介绍与下载

Java是最早由 SUN 公司的 James Gosling 开发的编程语言。

SUN 在 2009 年被 Oracle 收购;2014 年 3 月 19 日发布了 JDK8。

常用的 DOS 命令

cd 当前目录下的文件夹名 进入目录

脑海练习

1.1 JDK 和 JRE 的区别?

1.2 什么是编程?

1.3 Swing 组件是什么?

1.4 JAR 包是什么?

1.5 软件与程序指的是什么?

1.6 什么是编译型语言和解释型语言?

1.7 Java 语言特性?

1.8 能说下 JavaSE、JavaEE、JavaME 吗?

第二章 编写第一个程序

  • 编写源代码并运行
  • 代码书写规范
  • 注释
  • 总结回顾
  • 脑海练习

2.1 编写源代码并运行

内容导视:

  • 创建 .java 文件编写源码
  • 配置环境变量
  • 查看命令使用帮助
  • 解释代码含义
  • 编译与运行

2.1.1 创建 .java 文件编写源码

我们要开始写源代码啦!但只是在 DOS 窗口中输出一句话而已...

创建以 .java 结尾的文件,如 Hello.java。(以后统称为后缀或扩展名,打开文件资源管理器,查看,勾上文件扩展名)文件右击选择打开一种打开方式。(EditPlus 或其他文本编辑器,找不到选择其它应用,然后选中“始终使用此应用打开此类型的文件”复选框)这样你以后双击 .java 文件就可以直接使用此软件打开啦。

双击此文件,输入如下。还是直接复制、粘贴吧,记得保存。(Ctrl + S)

public class Hello {
	public static void main(String[] args) {
		System.out.println("hello world!");
	}
}

打开 DOS 窗口,使用 cd 命令切换到此文件的所在目录

(如果你在桌面上创建的文件,路径是 C:\Users\自己的用户名\Desktop,你可以自己打开文件资源管理器,点击左边的桌面图标,在地址栏上输入 cmd 后回车)

屏幕截图 2022-03-22 113317

在 DOS 窗口中输入 javac Hello.java,得到如下诡异的结果。

\'javac\' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

你可能会疑惑?怎么没有找到这个命令,不是在 JDK 的安装路径\bin 目录下有 javac.exe 命令吗?你说找不到?那为什么之前 DOS 窗口查看 IP 时,也就是C:\Windows\System32下的 ipconfig 命令就可以执行?

此电脑右键/属性/高级系统设置/环境变量/系统变量/Path 下看到了 %SystemRoot%\system32,即 C:\Windows\System32

(如果桌面上没有此电脑图标)

  • 打开文件资源管理器,此电脑的图标在左边。
  • 或者 Windows + i打开设置,点击系统/关于,往下翻,相关设置/高级系统设置。
  • 右键/个性化/主题/桌面图标设置,勾选计算机图标后点击应用和确定。

猜想:难道系统只会在 Path 指定的路径下寻找命令吗?我随手就删了它(别试,否则手动还原),确定保存刚刚的修改操作,重新打开 DOS 窗口,再次执行 ipconfig,很明白了。

得出结论:执行的程序如果在当前目录下不存在,系统会在名为 Path 的环境变量指定的目录下查找

好的,大概明白了,但我的电脑上有多个用户,那么为了不影响其他用户,我只配置用户变量的 Path,优先级当然没有系统变量的高。(系统变量针对所有用户生效)

2.1.2 配置环境变量

上节知道了 Path 变量的作用,现在该把命令地址添加到 Path 中了。

双击 Path,添加 javac 命令所在路径。(如果你还记得 JDK 安装的位置,打开 bin 目录,复制地址栏上的地址)

如果这个 JDK 安装目录,以后会重复使用(不用怀疑,肯定了)。为了方便,新建变量 JAVA_HOME 保存 JDK 安装目录,供其它地方使用。

再把之前的 javac 命令所在路径替换成 %JAVA_HOME%\bin

%JAVA_HOME% 代表变量 JAVA_HOME 对应的值。以后 JavaEE、开发工具需要获取 JDK 的安装目录,这样就不需要再手动设置了。

有的人可能版本较老,Path 变量值在一行文本框上显示。那么添加路径时,注意路径与路径之前使用;分隔,注意这个分号是英文状态下的半角符号,你按下 Shift,看看电脑右下角是否中英在切换。写成就错了。以后如果不说明,统一使用英文状态下的符号。

例:

检查自己是否配置好了:

打开 DOS 窗口,输入 java -version 和 javac 等命令
如果显示版本信息,证明 java.exe 是可以用的

再输入 echo %Path%
查看刚刚配置的 JDK的家\bin 路径是否在其中

有的人可能有疑惑,明明自己没配环境变量,为什么 java.exe 可以使用?

答:使用 exe 文件安装 JDK 后,会自动在系统变量 Path 添加如下图路径:

C:\Program Files (x86)\Common Files\Oracle\Java\javapath

所以没有手动配置环境变量时,java 命令可以用,但 javac 不行。

每次改动,都需要重新打开 DOS 窗口,配置才能生效。输入 javac Hello.java,如果你的语法正确,就会在当前路径下生成 class(字节码)文件,再输入 java Hello ,此时别带后缀。

有人就说了,每次运行 class 文件,都要使用 cd 命令进入此目录,再执行命令很麻烦。那么可以通过 classpath 变量指定字节码文件所在位置。

新建环境变量 classpath:

.是英文输入的句号,代表当前路径,如果不写就不会从当前路径寻找 class 文件。
由于我习惯把 class 文件放在桌面上,于是新增了桌面的路径,路径和路径直接使用;分隔,别使用中文的分号

这样不管在任何地方,输入 java Hello 就可以执行了。

总结

Path 是 Windows 查找 .exe 文件的路径;classpath 是 JVM 查找 .class 文件的路径;如果你以后学会了如何打 jar 包,假如它的绝对路径为 E:\a\c\d\Tool.jar,如果想任何位置敲 java -jar Tool.jar 让 jar 包执行,就可以把 E:\a\c\d\Tool.jar 加到 classpath 变量值里。

2.1.3 查看命令使用帮助

也许你总是会忘记,此命令应该携带什么参数...

想要执行的命令 -help,例举了可加的参数,如 -encoding。(对不起,我要给你埋坑了,如果你事先不知道此参数的作用...)

javadoc -helpjavac -help。(其实不加 -help 也行)

看,这不就出来了:

image-20220322120929241

2.1.4 解释代码含义

看不懂很正常,学完面向对象就懂了。突然遇到看不懂的不要怀疑自己智力有问题,只是还没到这步而已,大不了直接跳过。

public class Hello {
    // args 是变量名,可以根据标识符的命名规则取名
	public static void main(String[] args) {
		System.out.println("hello world!");
	}
}

从头开始说吧。

  • 关键字 public 是访问修饰符,表明该类是一个公共类,可以控制其他对象对类成员的访问。
  • 关键字 class 用于声明一个类,其后所跟的 Hello 是类名。
  • Hello 后跟的 {} 称为类体,包含了方法、字段...
  • public static void main(String[] args) {}:这个是 main 方法,由于被 JVM 调用,也被称为主方法、入口方法。所有 java 代码都是最先从入口方法开始执行的。
    • main 后的 {} 称为方法体,包含了 java 语句。
    • 关键字 static 表示该方法是一个静态方法,无须创建类的实例即可调用。
    • 关键字 void 表示此方法没有返回值。
    • void 后面的是方法名 main。
    • main 后的括号包含一个形式参数,这个形参是 String 类型的数组,参数名是 args。
    • System.out.println(""); 是 java 语句,代表打印(输出)括号中的内容到控制台(DOS 窗口)。
    • "hello world!" 是一个字符串。
    • ; 代表一条 java 语句的结束。

2.1.5 编译与运行

(字节码文件是 class 文件,由源代码中定义的 class 生成)

过程如下:

首先新建后缀为 java 的文件,编写出符合语法规则的代码。

编译:经过 javac 源文件名.java 命令编译生成字节码文件;

运行:使用 java 类名 命令在 JVM 虚拟机上运行此字节码文件,JVM 会调用此类的 main 方法。

(补充:因为一个源文件可以定义多个类,编译后生成多个 class 文件,所以 java 命令后面跟的不一定是源文件名)

编译

.java 文件是 java 的源文件,但是不能直接运行,必须先被编译成为 .class 文件才能够执行。别问,问就是电脑太笨,看不懂。

class 文件也称为字节码文件,上面的 javac 源文件名.java 就是编译的过程。

编译期将源码交给编译器,编译成可以被 JVM 识别的字节码,如果源代码不符合语法规则,就会报错(错误提示很智能,可以根据报错信息相应找到原因,自己试试比如删除一个大括号、引号等,看看 javac 命令给你报什么错)

运行

(当源文件修改后,必须重新编译才能生效)

编译后生成 class 字节码文件,使用 java class文件名 运行,别加 .class 后缀。

运行期类加载器(Class Loader)找字节码文件(如果没有配 classpath,默认从当前路径下找),找到了就加载字节码文件到 JVM 虚拟机,JVM 启动解释器对字节码文件进行解释,生成的二进制码读到内存中,由操作系统进行二进制码的执行。

字节码文件是一种和任何具体机器环境及操作系统环境无关的中间代码,编程人员和计算机都无法直接读懂字节码文件。它是一种二进制文件,是 Java 源文件由 Java 编译器编译后生成的目标代码文件。它必须由专用的 Java 解释器来解释执行,因此 Java 是一种在编译基础上进行解释运行的语言。

C 语言中文网下的解释,我觉得还行吧。我没玩过 C 语言,说什么就先听着,之后再忘掉就 OK 了。


1)将所有源代码一次性转换成二进制指令(也就是生成一个可执行程序,如 Windows 下的 .exe)
的转换工具称为编译器

比如 C 语言、C++ 的 GCC、Golang 的 GCC GO 等,源代码改动需要重新编译一次。

2)翻译一句,执行一句,不会生成可执行程序。
比如 Python 的 CPython 等,这种的转换工具称为解释器。

3)Java 和 C# 是一种比较特殊的存在。
如 java 有编译器 javac,但编译后的 class 文件计算机无法执行,还需要 java 解释器进行翻译。

它们的源代码需要先转换成一种中间文件(字节码文件),然后再将中间文件拿到虚拟机中执行。
Java 引领了这种风潮,它的初衷是在跨平台的同时兼顾执行效率;

C# 是后来的跟随者,但是 C# 一直止步于 Windows 平台,在其它平台鲜有作为。


Java 解释器负责将字节码文件翻译成具体硬件环境和操作系统平台下的机器代码,以便执行。因此 Java 程序不能直接运行在现有的操作系统平台上,它必须运行在被称为 Java 虚拟机的软件平台之上。

Java 虚拟机(JVM)是运行 Java 程序的软件环境,Java 解释器是 Java 虚拟机的一部分。在运行 Java 程序时,首先会启动 JVM,然后由它来负责解释执行 Java 的字节码程序,并且 Java 字节码程序只能运行于 JVM 之上。这样利用 JVM 就可以把 Java 字节码程序和具体的硬件平台以及操作系统环境分隔开来,只要在不同的计算机上安装了针对特定平台的 JVM,Java 程序就可以运行,而不用考虑当前具体的硬件平台及操作系统环境,也不用考虑字节码文件是在何种平台上生成的。

JVM 把这种不同软、硬件平台的具体差别隐藏起来,从而实现了真正的二进制代码级的跨平台移植。JVM 是 Java 平台架构的基础,Java 的跨平台特性正是通过在 JVM 中运行 Java 程序实现的。

Java 语言这种“一次编写,到处运行”的方式,有效地解决了目前大多数高级程序设计语言需要针对不同系统来编译产生不同机器代码的问题,即硬件环境和操作平台的异构问题,大大降低了程序开发、维护和管理的开销。

提示:Java 程序通过 JVM 可以实现跨平台特性,但 JVM 是不跨平台的。也就是说,不同操作系统之上的 JVM 是不同的,Windows 平台之上的 JVM 不能用在 Linux 平台,反之亦然。

2.2 代码书写规范

内容导视:

  • 代码细节
  • 代码规范
  • 标识符与关键字

2.2.1 代码书写细节

看不懂没关系,只挑能理解的。

1)字母严格区分大小写,如 class 不等于 Class。

2)在 java 中任何有效的代码必须写在“类体”中,就是 public class Hello 后的一对大括号 {} 中。

3)大括号必须要成对写,防止漏掉。

4)为了增加代码的可读性,大括号里的内容需要使用 tab 缩进,如 main 方法就比 class Hello 低一个层次。

class Hello {
    // 被 {} 包裹的部分选中,按下 tab
    public void some1() {
        // 被 {} 包裹的部分选中,按下 tab
        int i = 10;
        if (i > 10) {
            // 同理
            System.out.println("为何");
        }
    }
}

5)main 后的 {} 包裹的内容称为方法体,由一行行的 java 语句构成,任何一条 java 语句必须以分号结尾;。若无特别说明,默认为英文状态下的符号。

6)方法体中代码遵循自上而下的顺序依次逐行执行,不可随意颠倒顺序。

System.out.println(i);// 执行到这句时,还没有 i 变量
int i = 10;

7)一个 java 源文件可以定义多个类。编译后,每一个类对应一个 class 文件,如以下编译后会生成 A.class、B.class、C.class 三个字节码文件

class A {
}

class B {
}

class C {
}

8)有 public 修饰的类可以没有,但如果有,被 public 修饰的类名必须与源文件名一致
例:源文件名为 Hello,则 public class 后的类名也应该为 Hello。

9)被 public 修饰的类如果有,则最多只能有一个。类似一个家只有一个主人吧。

10)运行时,只会调用对应类的入口方法里面的内容,入口方法有固定的书写格式:

public static void main(String[] args) {}

那我偏不信邪,改下,再运行。

E:\cqh_demo\01-JavaSE>java A
错误: 在类 A 中找不到 main 方法, 请将 main 方法定义为:
   public static void main(String[] args)
否则 JavaFX 应用程序类必须扩展javafx.application.Application

好吧,再改回去了。

2.2.2 代码规范

规范与规则不一样,不是必须遵守。但是如果你不遵守,代码可读性会很差。反例如下,虽然可以通过编译,但你看起来感觉如何?

class
Hello{
public
    static
void
    main
    (String a[]){
System.
       out. println("你好")
       ; 
    int i=2
        ;
    			if
                    (i>
                     1&&i
                     <29){
                    System.out.println("e");
                }
}
	}

1)类和方法上的注释,以 javadoc 的方式,方便生成文档注释。

class Test {
    /**
     * 这个注释下节有讲,现在只是测试
     *
     */
    public void some() {}
}

2)非 javadoc 注释,用于给代码的维护者和读者看。(为什么这么写,如何修改,注意事项)

// 这就是注释,解释下面是将 10 赋给了 int 类型的变量 i;
int i = 10;

3)运算符如 <、= 的两边使用空格与字符隔开,举出正反例:

int a = 10;
int b=10;

if (a < 20 && b > 5) {}

if(a<20&&b>5){}

4)代码编写使用次行风格或行尾风格。你可以理解对整齐风格的追求吧。

// 行尾风格
public void add(int num) {
    if (num < 0) {
        this.age = 3;
    } else if (num < 6) {
        this.age = 33;
    } else {
    	this.age = 333;
    }
}
// 次行风格
public void add(int num)
{
    if (num < 0)
    {
        this.age = 3;
    } else if (num < 6)
    {
        this.age = 33;
    } else
    {
    	this.age = 333;
    }
}

2.2.3 标识符与关键字

声明:由于每次使用 import、带上完整类、main 方法比较繁琐。于是进行了简化,只提供关键部分,外面的类、方法等其它代码以后自己加吧,别直接复制代码,发现怎么跑不起来啊?

class Hello {
    public static void main(String[] args) {}
    
    public int add(int num1, int num2) {}
}

凡是程序员有权利命名的单词都是标识符

比如:类名、方法名、参数名、变量名、接口名、常量名。(这些是什么,以后就知道了,现在只是看看)

// add 是方法名有权利命名
public int add(int num1, int num2){
    // n 是变量名
    int n = num1;
}

你可以试试哪里可以修改,比如修改 public、int 等单词,是否会报错。你就明白,你可以动的地方有哪些。可以动而不报错的那些单词就是标识符,不可以动的就是关键字。


切换到英文输入,输出下划线、美元符号。

_:Shift 加 -
$:Shift + 4


命名规则

  • 标识符只能由数字、字母、_、$ 组成。(标识符中不能有空格)
  • 标识符不能以数字开头。
  • 关键字和保留字不能做标识符。
  • 标识符严格区分大小写,理论上没有长度限制。(如 Public 与 public 不一样)

命名规范

A)见名知意,如 day 代表天数。

1)别用拼音与英语混合,那样很难理解。

反例:tianKongBlue

2)杜绝完全不规范的英文缩写,避免望文不知义。

反例:AbstractClass “缩写”成 AbsClass;
condition “缩写”成 condi;
Function “缩写”成 Fu;
此类随意缩写严重降低了代码的可阅读性。

B)驼峰命名,多个单词连在一起时,单词首字母大写,增加识别和可读性,下面是阿里巴巴开发手册(黄山版)详细:

1)类名使用 UpperCamelCase 风格(首字母大写,后面每个单词首字母大写),以下情形例外:DO / PO / DTO / BO / VO / UID 等。

正例:ForceCode / UserDO / HtmlDTO / XmlService / TcpUdpDeal / TaPromotion
反例:forcecode / UserDo / HTMLDto / XMLService / TCPUDPDeal / TAPromotion

2)方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格(首字母小写,后面每个单词首字母大写)。

正例:localValue / getHttpMessage() / inputUserId

C)其它命名风格

1)常量名全部大写,单词间用_连接,力求语义表达完整,不要嫌名字长。

正例:MAX_STOCK_COUNT / CACHE_EXPIRED_TIME
反例:MAX_COUNT / EXPIRED_TIME

枚举成员实际上也是常量,名称需要全大写,单词间用_连接。

2)抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类命名以它要测试的类的名称开始,以 Test 结尾;枚举类名带上 Enum 后缀。

3)接口和实现类的命名有两套规则:

  • 对于 Service 和 DAO 类,基于 SOA 的理念,暴露出来的服务一定是接口,内部的实现类用 Impl 的后缀与接口区别。

    正例:CacheServiceImpl 实现 CacheService 接口。 
    
  • 如果是形容能力的接口名称,取对应的形容词为接口名(通常是 –able 结尾的形容词)。

    正例:AbstractTranslator 实现 Translatable 接口。
    

4)在常量与变量命名时,表示类型的名词放在词尾,以提升辨识度。

正例:startTime / workQueue / nameList / TERMINATED_THREAD_COUNT
反例:startedAt / QueueOfWork / listName / COUNT_TERMINATED_THREAD

5)如果模块、接口、类、方法使用了设计模式,在命名时要体现出具体模式。

正例: 
public class OrderFactory;
public class LoginProxy;
public class ResourceObserver;

说明:将设计模式体现在名字中,有利于阅读者快速理解架构设计思想。

6)各层命名规约:

​ a)Service / DAO 层方法命名规约:

​ ① 获取单个对象的方法用 get 做前缀。

​ ② 获取多个对象的方法用 list 做前缀,复数结尾,如:listObjects

​ ③ 获取统计值的方法用 count 做前缀。

​ ④ 插入的方法用 save / insert 做前缀。

​ ⑤ 删除的方法用 remove / delete 做前缀。

​ ⑥ 修改的方法用 update 做前缀。

​ b)领域模型命名规约:

​ ① 数据对象:xxxDO,xxx 即为数据表名。

​ ② 数据传输对象:xxxDTO,xxx 为业务领域相关的名称。

​ ③ 展示对象:xxxVO,xxx 一般为网页名称。

​ ④ POJO 是 DO / DTO / BO / VO 的统称,禁止命名成 xxxPOJO。

7)POJO 类中定义的布尔类型的变量,不要加 is 前缀,否则部分框架解析会引起序列化错误。

备注:POJO(Plain Ordinary Java Object):普通的 Java 对象。

反例:定义为基本数据类型 Boolean isDeleted 的属性,它的方法也是 isDeleted()。
框架在反向解析时,“误以为”对应的属性名称是 deleted,导致属性获取不到,进而抛出异常。

说明:本文 MySQL 规约中的建表约定第 1 条,表达是与否的变量采用 is_xxx 的命名方式,
所以需要在设置从 is_xxx 到 xxx 的映射关系。

8)包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。

正例:应用工具类包名为 com.alibaba.ei.kunlun.aap.util;类名为 MessageUtils
(此规则参考 Spring 的框架结构)。

9)数组类型应与 [] 紧挨,以免看漏,认为是基本数据类型或 String 类型。

正例:定义整形数组 int[] arrayDemo。
反例:在 main 参数中,使用 String args[] 来定义。

10)避免在子父类的成员变量之间、或者不同代码块的局部变量之间采用完全相同的命名,使可理解性降低。

// 反例
public class ConfusingName { 
    protected int stock; 
    protected String alibaba;
    // 非 setter/getter 的参数名称,不允许与本类成员变量同名
    public void access(String alibaba) {
        if (condition) {
            final int money = 666;
            // ...
        }for (int i = 0; i < 10; i++) {
            // 在同一方法体中,不允许与其它代码块中的 money 命名相同
            final int money = 15978;
            // ...
        } } }
class Son extends ConfusingName {
    // 不允许与父类的成员变量名称相同
    private int stock; 
}

说明:子类、父类成员变量名相同,即使是 public 也是能够通过编译,而局部变量在同一方法内的不同代码块中同名也是合法的,但是要避免使用。对于非 setter / getter 的参数名称也要避免与成员变量名称相同。

关键字

Java 关键字是对 Java 编译器有特殊含义的字符串,是编译器和程序员的一个约定,程序员利用关键字来告诉编译器其声明的变量类型、类、方法特性等信息。

关键字一律用小写字母标识,按其用途划分为如下几组。

1)用于数据类型的关键字有:

boolean、byte、char、 double、 false、float、int、long、new、short、true、void、instanceof。

2)用于语句的关键字有:

break、case、 catch、 continue、 default 、do、else、 for、 if、return、switch、try、 while、finally、 throw、this、 super。

3)用于修饰的关键字有:

abstract、final、native、private、protected、public、static、synchronized、transient、 volatile。

4)用于方法、类、接口、包和异常的关键字有:

class、 extends、 implements、interface、 package、import、throws。

5)保留字:

cat、 future、 generic、inner、 operator、 outer、rest、var、goto、byValue、cast、const 等都是Java尚未使用,但以后可能会作为关键字使用。

另外,Java 还有3个保留字:true、false、null。它们不是关键字,而是文字,包含 Java 定义的值。和关键字一样,它们也不可以作为标识符使用。

2.3 注释

内容导视:

  • 单行注释
  • 多行注释
  • 文档注释
  • IDEA 工具自动快捷键添加注释
  • 使用 javac 命令编译时出现的"错误: 编码 GBK 的不可映射字符"
  • 浅入编码
  • 查看系统编码
  • 使用 API 文档

注释是对代码的解释说明,方便理解代码的含义,提高代码的可读性。
注释不是编程语句,因此被编译器忽略。
如果不写注释,时间久了或代码过长本人也看不懂,所以编写注释是一个良好的习惯。

注释有三种,依次介绍。

2.3.1 单行注释

使用双斜杠 //,// 后的就是注释(仅一行),不会被编译器当成 java 语句。

public class A {
	public static void main(String[] args) {
		// 打印()中的话到控制台上,这个()中的字面量(数据)如果是字符串类型,需要用""包裹起来
		System.out.println("Hello World A");
	}
}

2.3.2 多行注释

对于很多内容,单行放不下,可以使用多行注释,在 /**/ 里内写下内容,星号别省略。

/*
	System 是类,
	通过类名.调用 out 这个静态变量,
	这个静态变量保存的是堆内存中的对象地址,被称为对象引用
	再通过对象引用,调用对象的 println 方法
*/
System.out.println("Hello World A");

2.3.3 文档注释

下面看看就行,以后使用开发工具 IDE 自动生成,没必要手动敲。

文档注释可以被 javadoc 命令解析,生成以网页形式(html)显示的 API 文档。(Application Programming Interface:应用程序编程接口)。

当类又多又杂,一个个找类、看注释很麻烦,于是提取出来生成网页。

用来说明类、成员变量和方法的功能。不用在一个一个 java 文件中查看注释,直接打开 html 查看想要的方法。

javadoc 默认只提取 public、protected 修饰的部分,javadoc -help 查看可加的选项。

文档注释必须写在类、接口、方法、构造器、成员字段前面,写在其他位置无效。

文档注释中可以识别的标签如下:

标签 说明
@version 指定类的版本,用于类上
@author 标注类的作者
@since 从哪个版本起有了这个方法
@param 参数详细信息
@return 说明返回值
@throws 可能抛出的异常
@deprecated 表示不建议使用
@see 另请参阅

文档注释的标签区分大小写,别写错了,也可以看看源码上的注释是怎么写的。(别省略 * 号,注意观察下面的格式)

/**
 * @author 是在座的每一个人
 * @version 2.0.0
 */
public class Hello {

    /**
	 * 这个方法用来求两数之和
	 *
     * @param  num1	第一个参数
	 * @param  num2	第二个参数
     * @return 返回两个数的和
     * @throws 测试用而抛出的异常
     * @since  1.8.2
     */
    public int add(int num1, int num2) throws RuntimeException {
        return num1 + num2;
    }
} 

javadoc 命令只能提取文档注释。让我们试试吧。

javadoc Hello.java -encoding UTF-8 -version -author -private -charset UTF-8 -docencoding GBK

当前目录会生成 index.html 文件,双击此文件,交给浏览器解析(会自动打开浏览器),右键查看页面源代码,API 文档里的信息是读取 Hello.java 文件得来的。

使用此命令还可以追加其他 java 源文件的文档注释,例:javadoc -encoding UTF-8 Hello.java H.java

javadoc 命令中的参数说明


-encoding 是告知 java 源代码所用的字符编码;
-version、-author 是显示版本和作者;
-private 是显示所有类和成员;(包括显示私有,一般显示 protected 以上级别就行,可以不加此选项)

-charset 是告知浏览器此文件采用什么编码方式读取这个文件;
即 html 文件生成 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

-docencoding 是指定生成的 html 文件的字符编码,不写此选项,默认 UTF-8。


由于文件被保存时的编码和读取时采用的编码不一致会出现乱码,所以别掉坑。咳咳,你知道自己的文件编码吗?在哪如何查看?编码是什么?你可以先了解下相关知识,或者你之前已经掉坑了,不知道满屏的 GBK 不可映射是啥意思,后面再讲好吗?

指定文档生成的位置

使用 -d 指定文件在 E:\a\b\c 下生成,很抱歉让你的桌面生了一大堆 html 文件。

javadoc Hello.java -d E:\a\b\c -version -author

代码一改,注释说明也得跟着改;为了避免无用功,代码中给标识符命名,见名知意,最好让所有人看到这段代码就知道它是干什么的,避免冗余无效注释。

下面不用看,我怕你晕:

import java.nio.channels.ReadableByteChannel;
import java.nio.charset.CharsetDecoder;

/**
 * 这是测试如何制作 API 文档的类
 *
 * <p> p 标签包围的文字代表一段,ul 和 li 标签是无序列表</p>
 * <ul>
 * <li>呵呵 {@code test} 呵呵</li>
 * <li>呵呵 <code>test</code> 呵呵</li>
 * <li>被上面 code 标签包裹的内容会更显眼,更细,一般用于标识符</li>
 * <li>see 标签另请参阅,格式:引用类的全类名#方法名(形参类型, 形参类型...)
 *     java.lang 包下的类可以省略包名。如果引用的类在 API 文档上,点击后会自动跳转
 *     这个 H 类我也打包到了此文档</li>
 * </ul>
 *
 * @author  cqh
 * @author  作者甲
 * @version 1.0.0
 * @see     Object#wait(long)
 * @see     Object#toString()
 * @see     StringBuffer
 * @see     H#hh()
 * @since   0.8.0
 */
public class Test {
    /**
     * 介绍属性的作用
     *
     * @see java.util.Scanner#makeReadable(ReadableByteChannel, CharsetDecoder)
     * @since 0.8.1
     */
    public String[] name;

    /**
     * 说明方法的作用
     *
     * @param name 这个name是 {@code String} 类型
     *       	   see参阅本类中其它方法省略类名。link如
     *             {@link #getAge(int, int)}也可以跳转,例
     *             {@link H#hh()},{@link H}
     * @return 返回一个人名
     * @throws ArrayIndexOutOfBoundsException 下标越界抛出此异常
     * @see #getAge(int, int)
     * @see H
     * @since 0.8.1
     */
    public String getName(String name) throws ArrayIndexOutOfBoundsException{
        return name;
    }

    /**
     * 另一种格式,把解释放到下一行 {@link java.lang.Object#notify()} 你好
     *
     * @param age
     *        这是人的年龄
     *
     * @param count
     *        总个数        
     *
     * @throws IndexOutOfBoundsException
     *         如果满足如下几种条件之一就抛出该异常
     *         <ul>
     *           <li> {@code age} 不是整数
     *           <li> {@code age} 没有填入
     *           <li> {@code age+(end-begin)} 超过了 
     *                {@code name.length}
     *         </ul>
     */
    public void getAge(int age, int count) throws IndexOutOfBoundsException{

    }
}

2.3.4 IDEA 工具自动快捷键添加普通注释

以后有了 IDEA 工具再试,现在不用看,直接跳过;放心 IDEA 工具中会更详细地说明。

在 IDEA 中每创建一个类时,自动在类上加注释

左上角 File/Settings/Editor/File and Code Templates,includes/File Header

里面粘贴

/**
 * 现在北京时间:${YEAR}/${MONTH}/${DAY} ${TIME}
 * 本类用于某某某
 *
 * @author  作者
 * @version 版本
 * @see     另请参阅
 * @since   从哪个版本有的
 */

点击 apply 和 OK。

image-20220322171502796

在方法上加注释

左上角 File/Settings/Editor/Live Templates

点击加号 Template Group 自己创建个组后,再选择你刚刚创建的组点击加号 Live Template。

解释:

Abbreviation:**

Description:解释快捷键的描述,自己填写

Options
Expand with Enter

Template text:
**
 *
 * @param   $param$
 * @return  
 * @throws
 */

当输入 Abbreviation 所写内容"**"时,按下 Enter 就把 ** 转成 Template text 中的内容

被 $$ 包围的变量需要点击 Edit vaiables 设置。

选择 Define 勾选 Java,就可以定义此模板只有在编写 java 文件才能使用。

点击 apply 和 OK。

然后我又定义了一个方法模板,缩写词:psvt;设置好后 OK 返回。

image-20220322172330365

在 java 文件输入 psvt 后按下 Tab 键,光标停在 $VAR$ 等我们输入;按下回车,光标到了 $END$ 处。

image-20220322172456942

image-20220322172627159

2.3.5 使用 javac 命令编译时出现的"错误: 编码 GBK 的不可映射字符"

内容如下:

  • 解决 GBK 乱码问题
  • 普及编码格式知识

本节片段提取:

友情提示,先复制文本,转换后直接粘贴。目的是避免转换编码后造成中文乱码,又得一个个改。

有 2 种方式解决:

1)文件/另存为副本,更改编码为 ANSI。(如果使用的是 notepad++,就在上方的工具栏的编码,转成 ANSI 编码)

image-20220322173042667

2)指定使用的编码格式。(编码格式在文本编辑器的右下方)-encoding UTF-8 是指定文件编码格式是 UTF-8。

屏幕截图 2022-03-22 173317

正文如下:

可能编译时由于代码(包括注释里面)中有中文,编译时说什么含有 GBK 的不可映射字符,不让通过。我相信新手的第一道关就卡在这,有人就干脆不写中文了。

为何报错

计算机只认得二进制数,也就是 0 和 1,存储和读取数据时都要使用二进制数表示。

0 和 1 可以有很多的组合,如 011、1001010 等等。可以用它们表示不同的数据,字符编码就是人为定义的一套转换表,规定一系列文字与二进制的映射关系。

(这里未区分字符集与字符编码的概念)

有多种字符编码,比如 ASCII 码,一般是 8 位二进制表示一个字符,如字符 \'a\' 对应 01100001,这个二进制码转为十进制是 96;

学过概率的知道,8 位数,每位是 0 或 1,最多可以表示 2 ^ 8 = 256 个字符,应对 26 个英文字母绰绰有余。这 8 位称为 1 个字节(byte),单个位称为 bit。

2 ^ 8 即 2 的 8 次方,只是为了方便表达。

ASCII 是美国人定义的,没有考虑其它国家。但我们国家用的不是英文,有很多字符是 ASCII 码没有的,1个字节也表示不了那么多的汉字,于是国人粗略规定了 GB2312,使用 2 个字节(16位)表示一个汉字。

如在 GB2312 编码中 "中国" 对应的二进制数 11010110 11010000 10111001 11111010,要是系统采用ASCII 码读取这段二进制,由于它们定义的字符的映射关系都不一样,ASCII 编码也不可能有中文对应的二进制码,所以解码不可能正确,解析不出来就会乱码。

这里二进制数每 8 位隔开,只是方便你们观看,实际使用时还是合在一起。

来,我们使用记事本试试看。此处文件编码为 ANSI,使用 ANSI 编码读取文件,没有乱码,显示 “天下”。

ANSI 代表系统默认编码方式,在中国是 GBK,放心 GBK 兼容 GB2312,使用 GBK 可以解析 GB2312。

举个例子,如果 ASCII 中所有字符对应的二进制码,在 GBK 中,对应关系也同样如此,就说明 GBK 兼容 ASCII 码。说人话就是 01100001 在 ASCII 中表示 \'a\',在 GBK 中也表示 \'a\'。那么使用 GBK 编码读取 ASCII 文件没有问题,反过来则不一定,因为 GBK 还多了 ASCII 中没有的汉字。

屏幕截图 2022-03-22 175428

让我们把文件编码转成 ISO-8859-1,也使用此编码读取文件。

image-20220322181031033

image-20220322181046936

现在再看看,这不就乱码了吗?

所以解码和编码都要使用同一套字符编码规则,notapad++ 可以使用不同的编码方式解析,你测试哪些编码是兼容的,不会乱码。

编码:字符 -> 二进制码

解码:二进制码 -> 字符

底层存储的实际是二进制码。

使用 javac 命令编译时,如果不指定 -encoding 选项,一般默认采用操作系统的字符编码方式,我们是 GBK。

在编写代码时,文本编辑器的右下角会显示当前文件的编码格式。编译时,若与系统当前编码不一致,不是同一套字符编码规则,解析不出来,就会报错;以后讲 char 类型时还会深入,现在讲的很浅显,看不明白很正常,不是你的原因。

两种方式解决

  • 告知此文件的编码方式。
    例:当前文件的编码格式是 UTF-8,文件是 Hello.java,编译时添加 -encoding 参数指定文件编码javac Hello.java -encoding UTF-8

  • 修改文件编码方式为 ANSI,文件另存时可以看到编码。(notepad++在工具栏/编码/转为...记得先全选复制,改编码后再粘贴,否则乱码没法撤回)

  • 所有文件使用统一的编码方式,如 UTF-8,新建环境变量 JAVA_TOOL_OPTIONS,值为 -Dfile.encoding=UTF-8,不建议,以后使用 IDE 工具统一使用 UTF-8 编码,不需要自己在外面配。

  • 我不写中文了,不建议,你是中国人,要不是英文通不过编译,我还真想全部使用中文符号。

2.3.6 查看与修改系统编码

通过 java 代码查看

执行以下代码查看系统默认编码

public class Hello {
    public static void main(String[] args) {
        String encoding = System.getProperty("file.encoding");
		System.out.println(encoding);
    }
}

通过 DOS 窗口查看

打开 DOS 窗口(Windows + R,输入 cmd 回车),点击左上角图标/属性

看到了没有,我没有画圈哦。当前代码页是 936,对应简体中文编码 GBK。

代码页是字符集编码的别名,也称内码表,下面是代码页与编码的对应关系:

代码页       国家(地区)或语言 
437          美国 
708          阿拉伯文(ASMO 708)
720          阿拉伯文(DOS)
850          多语言(拉丁文 I) 
852          中欧(DOS) - 斯拉夫语(拉丁文 II) 
855          西里尔文(俄语) 
857          土耳其语 
860          葡萄牙语 
861          冰岛语 
862          希伯来文(DOS)
863          加拿大 - 法语 
865          日耳曼语 
866          俄语 - 西里尔文(DOS) 
869          现代希腊语
874          泰文(Windows)
932          日文(Shift-JIS)
936          中国 - 简体中文(GB2312)现在是 GBK 了,GBK 是在国家标准 GB2312 基础上扩容后兼容 GB2312 的标准。
949          韩文
950          繁体中文(Big5)
1200         Unicode        
1201         Unicode (Big-Endian)
1250         中欧(Windows)
1251         西里尔文(Windows)
1252         西欧(Windows)
1253         希腊文(Windows)
1254         土耳其文(Windows)
1255         希伯来文(Windows)
1256         阿拉伯文(Windows)
1257         波罗的海文(Windows)
1258         越南文(Windows)
20866        西里尔文(KOI8-R)
21866        西里尔文(KOI8-U)
28592        中欧(ISO)
28593        拉丁文 3 (ISO)
28594        波罗的海文(ISO)
28595        西里尔文(ISO)
28596        阿拉伯文(ISO)
28597        希腊文(ISO)
28598        希伯来文(ISO-Visual)
38598        希伯来文(ISO-Logical)
50000        用户定义的
50001        自动选择
50220        日文(JIS)
50221        日文(JIS-允许一个字节的片假名)
50222        日文(JIS-允许一个字节的片假名 - SO/SI)
50225        韩文(ISO)
50932        日文(自动选择)
50949        韩文(自动选择)
51932        日文(EUC)
51949        韩文(EUC)
52936        简体中文(HZ)
65000        Unicode (UTF-7)
65001        Unicode (UTF-8)

也可通过 DOS 命令查看当前编码:chcp

修改当前 DOS 窗口的编码:chcp 对应编码的代码页,如chcp 936,当控制台不支持中文时,可以试试。(重新打开 DOS 窗口时会失效,恢复原来默认编码)

修改系统编码

如果是 Windows10,打开设置(Windows + i),时间和语言/语言/管理语言设置/更改系统区域设置,

老版本的使用控制面板/时钟和区域/区域/管理/更改系统区域设置。

下面还有 beta 版(即测试版),使用 UTF-8 编码提供全球语言支持;但有些地方莫名其妙的乱码,不建议尝试,还是 GBK 靠谱。

作者:「已注销」,内容:修改 cmd 控制台默认代码页编码的几种方法【GBK、UTF-8】,https://blog.csdn.net/gulang03/article/details/81771343

2.3.7 使用 API 文档

解决了中文乱码后,来看看 rt.jar 包中的类、方法、字段上的文档注释生成的 API 文档。

JDK17 API文档:https://docs.oracle.com/en/java/javase/17/docs/api/index.html

JDK8 API文档:https://docs.oracle.com/javase/8/docs/api/

JDK8 API中文文档:https://www.matools.com/api/java8

就是记不住方法名怎么办,翻阅 API 文档查看方法的作用,你得首先记住哪个类好像有这个方法。

Java 语言提供了大量可供使用的基础类,Oracle 为这些类提供了对应的 API 文档,告诉开发者如何使用此类,以及方法。

通过包名 -> 类名 -> 方法这样的方式寻找。

以 JDK8 为例,哦,对了,将最上面的广告关掉。

如果不知道类在哪个包下,点击最上方的索引(INDEX)

如我要用 Math 类的求绝对值的方法,如果事先知道它在 java.lang 下(第一横线处下翻),找到后点击 java.lang,继续下翻(第二个横线处);找到后点击 Math,再看右边的页面,下翻;点击 abs 方法,就可以看到此方法的详细说明。

image-20220318155351799

打开 rt.jar(jre 的 lib 下) 也可以看到 Math.class。(使如果你没有软件可以打开 zip,win-rar 解压缩软件下载地址在资源地址中)

image-20220318154136523

image-20220318154212941

image-20220318154252881

你说这是字节码文件,肯本看不懂,要看源码上的文档注释。好吧,在 JDK 安装目录下,打开 src.zip\java\lang\Math.java。

image-20220318154851832

image-20220318155512159

以这种方式,的确没有 API 文档访问方便不是吗?(养成在方法上写文档注释的好习惯,这样方便提取出来)

这是谷歌翻译:

返回 {@code float} 值的绝对值。
* 如果参数不是负数,则返回参数。
* 如果参数是否定的,则返回参数的否定。
* 特别案例:
* <ul><li>如果参数是正零或负零,则
* 结果为正零。
* <li>如果参数为无穷大,则结果为正无穷大。
* <li>如果参数为 NaN,则结果为 NaN。</ul>
* 换句话说,结果与表达式的值相同:
* <p>{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
*
* @param a 要确定其绝对值的参数
* @return 参数的绝对值。

总结回顾

编译与运行

先编译成 .class 文件,后运行此类的 main 方法。

运行期类加载器(Class Loader)将 class 文件加载到 JVM 中,JVM 启动解释器对 class 文件解释,生成的机器码在内存中,由操作系统执行。

class 文件是与平台无关的中间代码。下载对应平台的 JVM,由它自带的解释器,将 class 文件翻译成当前操作系统可以执行的机器码,做到一次编写,可以在不同的平台上运行。但 JVM 不跨平台。

程序员可以命名的单词是标识符,如类名、方法名、变量名、接口名、常量名。

命名规则

  • 只能由数字、字母、_、$组成。
  • 不能以数字开头。
  • 不能以关键字作为标识符。

命名规范

  • 类名、接口名首字母大写,之后每个单词首字母大写。
  • 方法名、变量名首字母小写,之后每个单词首字母大写。

注释

合理使用注释,解释代码含义,方便他人阅读。

  • 类和方法上的注释,使用文档注释。
  • 类中、代码块中使用多行或单行注释,对难以理解的地方进行说明。
  • 不同逻辑的代码之间空行隔开。

编码

使用 UTF-8 格式编写源文件更通用。

脑海练习

2.1 为什么 Java 代码可以做到一次编译,到处运行?

2.2 一个源文件可以生成多个 class 文件吗?

2.3 Java 源文件定义的类名必须与文件名一致吗?

第三章 变量

内容导视:

  • 变量
  • 数据类型
  • 类型转换

3.1 变量

内容导视:

  • 字面量
  • 变量

3.1.1 字面量

值(数据)被称为字面量,一眼就能看到值的量。如 3 是整数型字面量,\'a\' 是字符型字面量;有些人把它叫做常量,无可非议。

字面量类型如下:

1)整数类型:如 1、2、3...这些整数。
2)浮点类型:如 22.4、3.2...这些小数。
3)布尔类型:只有两个值,true、false 分别代表真和假。
4)字符类型:\'a\'、\'b\'、\'c\'...用英文单引号括起来的单个字符
5)字符串类型:"abc"、"b"、"北京欢迎你"...用英文双引号括起来的是字符串。

3.1.2 变量

使用如下方式,也不是不可以,但是你不怕一个个复制粘贴不小心漏了吗?

System.out.println(327501510);
System.out.println(327501510 + 6);
System.out.println("我们的花园真漂亮");
System.out.println("我们的花园真漂亮");

为了使字面量得到重复利用,下面使用变量保存这些值。

内容如下:

  • 变量的声明
  • 变量含义
  • 变量按声明位置分类

变量声明

每个变量都需要先声明(定义)自己将要保存的数据的类型,后再给变量赋值。(放心,数据类型之后有讲,现在先看看,别管 int、String 是什么)

例:想要保存整数类型的值,需要先声明整数类型的变量,假如取名为 i:

int i;

再给变量赋一个整数值。

// 使用等号(赋值运算符)把等号右边的字面量赋给左边的变量
i = 327501510;

可以访问这个变量保存的值。

System.out.println(i);// 此时 i 为 327501510

也可以重新给 i 变量赋值,把之前保存的值覆盖。

i = 6;// 把 6 赋给 i
System.out.println(i);// 此时 i 为 6

两者结合,在声明的同时,赋值。

int i = 327501510;

那么就可以把开头的例子转变了:

int num1 = 327501510;
int num2 = 6;
String str = "我们的花园真漂亮";

System.out.println(num1);
System.out.println(num1 + num2);
System.out.println(str);
System.out.println(str);

num1、num2、str 是变量名,作为标识符,我们有权力命名,只要符合命名规则就行。

很明显通过以上例子看到变量有三个要素:

  • 变量的数据类型,如 int
  • 变量名,如 num1
  • 变量值,如 327501510

数据类型 变量名 = 字面量;

如果不考虑类型转换,那么变量的数据类型必须与字面量类型一致。

比如整数型的 int 类型不能保存浮点型的字面量,int i = 3.23; 是错误的写法。由于现在还没有讲数据类型,听着迷惑很正常。

变量含义

变量是内存中存储数据的最基本的单元,任何变量都有数据类型,不同的数据类型在内存中分配的空间大小不同。

int a = 3; 在内存里分配 4 个字节空间,空间存放着 3,a 就代表这个空间。

变量相当于内存中的一小块数据存储空间,通过变量名可以访问到这个区域。可以把 a 理解成你家的门牌号,通过门牌号定位你家。

int 类型会被分配 4 个字节大小的空间,1 个字节(byte)= 8 个比特位(bit)

1 TB = 1024 GB
1 GB = 1024 MB
1 MB = 1024 KB
1 KB = 1024 Byte
1 Byte = 8 Bit
1 Bit = 0 或 1

利用 0 和 1 的不同的组合代表各式各样的数据,等学到进制之间的转换、原码补码就明白了,但你也可以跳过,节省时间。

变量按声明位置分类

分为成员变量与局部变量。之间说过类名 Hello 后跟的 {} 是类体,方法名 main 后跟的 {} 是方法体。

public class Hello {
    // 方法体外、类体中声明的变量是成员变量
    int a = 2;
    
    public static void main(String[] args) {
        // 方法体中声明的变量是局部变量
        int b = 4;
        System.out.println(b);// 4
    }
}

值得注意的地方

1)局部变量必须赋值后才能访问,错误示范:

public static void main(String[] args) {
    int i;
    System.out.println(i);
}

你得先给 i 赋值,比如 int i = 10; 后再访问。

2)同一个域中,局部变量不能重复声明。

域:{} 包起来的范围。

// 错误示范
public static void main(String[] args) {
    int i = 3;
    int i = 6;
}

你得换个名字,以免冲突。比如把后面改成 int j = 6;

3)变量需要先声明,后访问,错误示范:

public static void main(String[] args) {
    System.out.println(i);
    int i = 3;
}

你应该把它俩的顺序换过来,毕竟 java 语句是自上而下逐行执行的。

3.2 数据类型

内容导视:

  • 整数类型
  • 浮点类型
  • 字符类型
  • 布尔类型
  • 基本数据类型转换
  • 基本数据类型与 String 类型的转换

数据类型 变量名 = 字面量;...变量的数据类型必须与字面量类型一致?

字面量讲了,变量名你可以随便取,接下来该说一说数据类型了。

Java 支持的数据类型有两种,基本数据类型引用数据类型

基本数据类型加上引用数据类型中的 String 类,正好与我们之前讲的字面量类型一一对应。

基本数据类型

1)整数类型

  • byte(字节):在内存中分配 1 个字节的空间。(8 位)
  • short(短整型):在内存中分配 2 个字节的空间。(16 位)
  • int(整型):在内存中分配 4 个字节的空间。(32 位)
  • long(长整型):在内存中分配 8 个字节的空间。(64 位)

2)浮点类型

  • float:在内存中分配 4 个字节的空间。
  • double:在内存中分配 8 个字节的空间。(double 精度比 float 更高)

3)布尔类型

  • boolean:在内存中分配 1 个字节(数组中)或 4 个字节的空间(单个定义时)。

4)字符类型

  • char:2 个字节。

引用数据类型

1)类(class)包括枚举

  • JDK 自带类库,如 java.lang.String、集合、包装类...
  • 用户自定义的类型,如我们之前写的 class Hello...
  • 第三方类库

2)接口(interface)包括注解

3)数组(array)

对于基本数据类型,如定义 int 类型的变量,就可以接收整数型的字面量:int i = 4;;定义 char 类型的变量,可以接收字符型的字面量:char c = \'中\';;定义 boolean 类型的变量可以接收 true 或 false:boolean b = true;...

对于引用类型的 String,定义 String 类型的变量,就可以接收字符串型的字面量:String str = "我是什么样";

正常情况下,占用字节空间越大,表示的数越多;如整数类型的 byte 只占一个字节,只能表示 -128 ~ 127 内的整数,所以才需要 int、long,用以存储更大的整数。当然存储的数很小时,没必要使用 long,太浪费空间。

引用类型等面向对象时讲,现在先看基本数据类型:

3.2.1 整数类型

整数类型用来存储整数类型的字面量。

以 1 个字节为例,1 个字节 8 位,每位是 0 或 1,那么就是有 28 种可能,即表示 256 个数。

下面是不同整数类型的取值范围:

类型 占用存储空间 取值范围
byte(字节) 1 个字节 [-128 ~ 127] 即 [-27 ~ 27 - 1]
short(短整型) 2 byte [-32768 ~ 32767] 即 [-215 ~ 215 - 1]
int(整型) 4 byte [-2147483648 ~ 2147483647] 即 [-231 ~ 231 - 1]
long(长整型) 8 byte [-263 ~ 263 - 1]

int i = 3;
byte b = 45;
b = 34;
System.out.println(i);

定义了 int 类型的变量,变量名为 i,保存的值为 3。

定义了 byte 类型的变量,变量名为 b,保存的值为 45。

把 34 赋给 b 变量,原来保存的 45 被修改了。

System.out.println(i);表示把 i 保存的值输出到控制台(目前是 DOS 窗口)上。

由于现在你们可能还不懂二进制,于是使用十进制表示,同时也是为了方便,避免写太多的 0、1。


有人可能会问超过了整数类型的取值范围会怎么样?

byte b = 128;
Hello.java:4: 错误: 不兼容的类型: 从 int 转换到 byte 可能会有损失
    byte b = 128;

这下就更疑惑了,什么叫 int 转成 byte 会有损失?难道这个 128 也就是整数型字面量默认被当作 int 类型处理吗?

让我们试一试:

long num1 = 2147483648;

推测:就算 long 类型可以保存这么大的数,但如果后面的 2147483648 真的被当作 int 类型处理的话,那肯定由于超过 int 的范围,会报错。

Hello.java:4: 错误: 过大的整数: 2147483648
    long num1 = 2147483648;

好的,大概明白了。得出结论:

  • 整数型字面量默认被当作 int 类型处理。
  • 为了方便,当被当作 int 类型处理的字面量的值没超过整数类型的范围时,可以直接赋值。如 byte b = 1;

有人就问了,超出 int 范围的值?那能不能让整数型字面量被当作 long 类型处理?

答:在声明整数型字面量时在其后加 l 或 L。

long num1 = 2147483648L;
long num2 = 2147483648l;

但是你也看见了,由于小写的 l 感觉就像 1,为了避免混淆,统一使用大写表示。

这里插一条概念:

值传递:把变量保存的值重新复制一份,传递给另一个变量;而另一个变量修改自己保存的值,不会影响原来变量保存的值。

int i1 = 100;
// 把 i1 保存的值 100 复制一份,传给 i2,此时 i2 保存的值为 100
int i2 = i1;

// 修改 i2 保存的值,不会对 i1 有影响
i2 = 55;

System.out.println("i1 = " + i1);// i1 = 100
System.out.println("i2 = " + i2);// i2 = 55

好,有了这个概念,让我们试着互换两个变量保存的值。

大家想一想,如果现在有两个杯子 a、b,都装满了水,该如何互换?

无标题

是不是要准备第 3 个杯子 c,先把 a 倒进 c 中,然后把 b 倒进 a 中,最后把 c 倒进 b 中。

int a = 22;
int b = 433;

int c = a;// c = 22
a = b;// a = 433
b = c;// b = 22

可以不借助第三个变量 c 吗?

有聪明的小伙伴想到了:让 a 保存两值之和(a + b),让 b = 两值之和 - b = a;

int a = 22;
int b = 433;

a = a + b;// a = 22 + 433
b = a - b;// b = (22 + 433) - 433 = 22
a = a - b;// a = (22 + 433) - 22 = 433

3.2.2 浮点类型

浮点类型的变量可以接收一个小数,如 6.2、32.2。

由于使用指数的形式表示值,表示的数比相同字节下的整数类型更大,但是精度有限,结果可能有误差,无法精确表示。

现在看看浮点类型的取值范围,的确比整数类型的取值范围大多了:

类型 占用空间 范围
float 4 个字节 [1.4E-45 ~ 3.4028235E38] 即 [2-149 ~ 2128]
double 8 个字节 [4.9E-324 ~ 1.7976931348623157E308] 即 [2-1074 ~ 21024]

这段内容可以不看:


科学计数法

由于数太大了,为了更好表示数值不浪费空间,使用科学计数法表示。这个 E 大写小写都可以。

1.4E-45 = 1.4 * 10-45

3.4028235E38 = 3.4028235 * 1038

有人说为何使用科学计数法表示?以 2 的幂表示,如 2-149 是不是更节省空间?

7777777 保留 2 位有效数字,使用科学计数法表示:7.78 * 106(7.78E6);你此时可能还在算它是 2 的几次方吧?

Java 中,当小数超出 [-9999999,9999999] 范围时,会使用科学计数法表示。

System.out.println(-10000000.0);

控制台上会输出 -1.0E7

有聪明的伙伴可能注意到了两点,题干中的“小数”、字面量后的“.0”,注意啊这两个条件不能丢,否则会被当作 int 类型处理。那么下面这道题就可能做错:

思考控制台输出什么结果?

System.out.println(500e-2);

答:500e-2 = 500 * 10-2 = 500 / 102 = 5.0

别说结果是 5 啊。

下面呢?

System.out.println(-10000000);
System.out.println(500E-7);

第 1 个明显不是小数,还是原样输出。第 2 个你可能会觉得这既然超过上述所说的范围,那使用科学计数法表示,还是原样输出。

我留的坑啊,没有使用这种方式 500E-7 表示的,而是 5.0E-5

举个例子,a * 10n,那么 |a| 是 [1 ~ 10) 之间的数。

-78937935.2 ,一看超过了范围,用科学计数法表示:-7.89379352E77.89379352 大于等于 1,小于 10。你要是这样表示就错了:-78.9379352E6


小数类型的字面量默认被当作什么类型处理?

回过头来,小数类型的字面量又被当作什么类型处理?

做个实验:

float f = 3.14;
Hello.java:8: 错误: 不兼容的类型: 从double转换到float可能会有损失
   float f = 3.14;

看来默认被当作 double 类型处理。同样想要指定字面量被当作 float 处理,需要在字面量后加上 f 或 F。

float f = 3.14F;

同理,指定字面量被当作 double 类型处理。(其实 D、d 去掉也可以,在基本类型的转换中有讲)

double d1 = 5D;
double d2 = 3d;

有时候你会看见这种写法:double d = .12; 不要疑惑,这等同于 double d = 0.12 ,这个 0 可以省略不写,但一般不要这么做,否则其他人可能会疑惑。

精度

浮点数存放形式:浮点数 = 符号位 + 指数位 + 尾数位,尾数部分很可能会丢失,造成精度损失。(小数都是近似值)(有兴趣去扩充知识了解,这里不赘述)

System.out.println(0.11111111111111111111111111111F);
System.out.println(0.11111111111111111111111111111D);
0.11111111
0.1111111111111111

大概可以这么理解:

float 的精度是保留 8 位有效数字。

double 的精度是保留 16 位有效数字。通常使用 double 类型。

有效数字是一个数从左边第一个不为 0 的数字起,直到末尾止的数字称为有效数字,如 0.009210,有效数字 4 位:9、2、1、0。

保留两位有效数字:0.0092。

由于浮点数运算得到的结果可能有误差,所以如下就成了错误做法:

double d1 = 9.9 / 3;
double d2 = 3.3;

if (d1 == d2) {
  System.out.println("它们相等");  
}

上面的意思是:如果 d1 等于 d2,就输出“它们相等”。

但试着运行,控制台什么都没有输出...

此时再试下访问 d1 的值:

System.out.println(d1);// 3.3000000000000003

看到没有?9.9 / 3 不等于 3.3,而是十分接近 3.3 的小数。

当对运算结果是小数的进行相等判断时,应该以两个数的差值的绝对值,在某个精度范围类判断。这个精度由自己决定,如人民币数值比较,人民币最低面额 1 分 = 0.01 元,只要两数差值小于 0.01,就认为它们相等。

现在该改一下了:

double d1 = 9.9 / 3;
double d2 = 3.3;

if (Math.abs(d1 - d2) < 1.0E-2) {
  System.out.println("它们相等");  
}

还记得如何查 API 文档吗?当导入 java.lang 包下的类时,可以不用 import。哦,对了,你们还不懂,这节在面向对象的包机制中。

那我直接说含义,Math.abs(a):求 a 的绝对值。当 d1 - d2 的绝对值小于 0.01 时,我们姑且认为它们相等。

现在收尾。我还是说说怎么找吧:

打开 JDK API 文档,如果知道 Math 在哪个包下,比如 Math 在 java.lang 包下,点击 java.lang;

如果不知道,点击索引找 M 开头的类:

找到后点击 Math,看看 abs 方法的介绍。

3.2.3 字符类型

输出、打印是一个意思。

char 类型的变量可以保存单个字符,占用 2 个字节,取值范围:[0 ~ 65535] 即 [0 ~ 216 - 1]。

char c1 = \'中\';
char c2 = \'a\';

// 字符类型可以直接存放数字,当输出 c2 时,会输出 97 代表的字符,扩充内容中有讲
char c2 = 97;

你们可能会在其他地方遇到如 char c = \'\n\';,这叫转义字符

一般使用 \ 开头,代表着将一个字符转义,本质还是单个字符。


\n:换行
\t:制表符 tab
\r:回车
\u:把十六进制数转成对应的字符


1)\n:

什么叫换行?

System.out.println("你好\n我好\n大家好\n");
char c = \'\n\';
System.out.println(c);
System.out.println(2);

这里不得不提一下 ln:

System.out.print(2);
System.out.print(1);
System.out.println();// 代表换行
System.out.print(7);
21
7

ln 表示当前行结束输出,如果要继续输出,就要到下一行开始。

回过头来,"你好"换行,"我好"换行,"大家好"换行,ln 代表换行。
System.out.println(c);,c 是 \'\n\',代表换行,ln 代表换行。
结果如下:

你好
我好
大家好



2

2)\t:

System.out.println("狗\t猫\t鱼");
狗      猫      鱼

可以看到狗与猫、鱼之间隔了一个制表符的距离。

3)\r:

System.out.println("我是什么\r人呢");

如果回车但不换行,\r 后的"人呢"还在同行首个位置上输出,把"我是"覆盖,最后结果:"人呢什么"。

4)\u:

System.out.println("\u5929");

16 进制的 5929 对应的字符为天,有兴趣请在扩充内容中的字符编码了解。

这个 \ 作用不止如此。

问想要使用 char 类型保存单个字符:英文单引号 \' 怎么做?

char c = \'\'\';这样?

Hello.java:4: 错误: 未结束的字符文字
                char c = \'\'\';

像这类具有特殊含义的字符,需要使用 \ 转成普通的字符,使其不再被认为是代表字符开始的单引号。

char c = \'\\'\';

同理,打印 \、" 等特殊符号,都需要在字符前加上 \:

System.out.println("\"");
System.out.println("\\");
"
\

3.2.4 布尔类型

boolean 类型只有两个值:true 或 false,用于逻辑运算:2 < 3 为 true。

一般放在 if 、for 等语句的条件处,控制程序的流程,现在不用深究。

3.3 类型转换

内容导视:

  • 基本数据类型转换
  • 基本数据类型与 String 类型的转换

3.3.1 基本数据类型转换

缘起

double d = 3; 唉呀,字面量 3 不是被当作 int 类型处理吗?怎么就可以赋给 double 类型的 d?别急,看完以下实验就明白规则了。

boolean 除外,不同类型容量(取值范围)按从小到大排列:

byte -> short -> int -> long -> float -> double
char -> int -> long -> float -> double

基本数据类型的转换规则

前提:基本数据类型

当所赋值的字面量类型与变量的数据类型不一致时,会发生数据类型转换,从一种数据类型转成另一种数据类型。分为自动类型转换强制类型转换。除了 boolean 类型不能参与转换,其他基本数据类型可以互相转换。

小容量赋给大容量,会发生自动类型转型,如 int 类型自动转为 long 类型:

// int 类型自动转换为 long
long l = 3;

// long 类型自动转为 float
float d = 3L;
System.out.println(d);// 3.0

// char 自动转 int
int i = \'中\';
System.out.println(i);// 20013

\'中\'在 Unicode 字库的序号是 4E2D,使用 UTF-16 编码存储的二进制码为 0100111000101101,即 20013。

大容量赋给小容量,自动转换无法进行:

// 错误: 不兼容的类型: 从 double 转换到 int 可能会有损失
int i = 3.13;
// 错误: 不兼容的类型: 从 long 转换到 int 可能会有损失
i = 3L;
// 错误: 不兼容的类型: 从 int 转换到 byte 可能会有损失
byte b = 532;

这时就需要强制转换符(),但可能会有精度损失。

// 强制把 double 类型转成 int
int i = (int)3.13;
System.out.println(i);// i = 3

// 强制把 long 类型转成 int
i = (int)3L;
System.out.println(i);// i = 3

// 强制把 int 类型转成 byte
byte b = (byte)532;
System.out.println(b);// b = 20

补充细节

1)如果字面量的值没有超出 byte、short、char 的取值范围,可以直接赋值给它们。(除了被当作 long 类型处理的字面量)

byte b = 3;
char c = 33;

byte b1 = \'a\';// \'a\' 表示 97
// 超出 byte 的取值范围,从 char 转换到 byte 可能会有损失
byte b2 = \'中\';// \'中\' 表示 20013

需要注意,我指的是以字面量形式赋值,而不是值传递,自己试试报什么错?

int i1 = 3;
int i2 = 33;
char letter = \'a\';

byte b = i1;
char c = i2;

byte b1 = letter;

之前有人问你怎么知道 \'a\' 代表的整数,我又不想了解 ASCII 码,有什么简单的方法吗?这就是第 2 点,请看:

2)byte、short、char 类型的变量混算时,会自动升级到 int 类型。

怎么得出的这个结论?

byte b1 = 2;
byte b2 = 5;
byte b3 = b1 + b2;
Hello.java:6: 错误: 不兼容的类型: 从 int 转换到 byte 可能会有损失
byte b3 = b1 + b2;

是吧,两个 byte 类型的变量相加,竟然升级了。那我可以利用这一点,让 char 类型的变量升级成 int 变量,自然就知道该字符对应的整数了。

char c = \'中\';
short s = 0;

System.out.println(c + s);// 20013
System.out.println(\'1\' - 0);// 49

3)多种类型混算时,先把字面量转成容量大的那种数据类型,再进行计算。

如果你不知道这点,以后计算很容易吃亏。比如 10 / 4,你本来想得到 2.5,但是这参与运算的数,容量最大的也只是 int 类型,而 int 类型只能保存整数,所以 2.5 被削去了小数。

int i = 10 / 4;
System.out.println(i);// i = 2

这时就需要浮点类型的参与,改一下:

double i = 10.0 / 4;
System.out.println(i);// i = 2.5

思考如下语句可以通过编译吗?

byte b = 10;
b = b * 2;

b 保存的 10 对应 byte 类型,2 对应 int 类型,这就是混算;让 10 升级到 int 类型,与 2 相乘,结果还是 int 类型,再赋给 byte 类型的变量,报错:从 int 转换到 byte 可能会有损失

思考输出什么?

double d = 1 / 4 * 4.0;
System.out.println(d);

有人说这不就是 1 吗?有什么难的?当然也有其他人看出来了:1 / 4 是两个 int 类型的字面量参与运算,结果为 0;(你难道忘了 int 类型只能保存整数吗?)接着算,0 * 4.0 = 0.0;

所以结果为 0.0。(忘记带小数,哪怕只是 .0,结果就完全不同)

你的原意可能是这:double d = 1.0 / 4 * 4.0;

3.3.2 基本数据类型与 String 类型的转换

没想到吧,"+" 号除了能计算两数之和外,还能拼接字符串。哦,我好像之前已经用过了。

String str1 = "我";
String str2 = "和";
String str3 = "你";

String str4 = str1 + str2 + str3;
System.out.println(str4);// 我和你

思考输出什么?

System.out.println(4 + 3 * 2 + "2" + 5 * 5);

4 + 6 = 10;10 + "2" = "102";"102" + 25 = "10225";

没看晕吧?从左至右,乘号优先;字符串加谁,谁就被拼接在一起。那么就利用这个 "+",将基本数据类型转成字符串吧。

基本数据类型转成字符串

"" 代表空字符串。输出字符串时,是不会输出双引号的,这你应该早就知道了。

long l = 3L;
int i = 3;
char c = \'中\';
double d = 3.243;

String str1 = l + "";
String str2 = i + "";
String str3 = c + "";
String str4 = d + "";

System.out.println(str1);// 3
System.out.println(str2);// 3
System.out.println(str3);// 中
System.out.println(str4);// 3.243

字符串转成基本数据类型

别看,等到包装类时就懂了。(或者你会查 API 文档,它们在 java.lang 包下)

String str = "123";

byte num1 = Byte.parseByte(str);
short num2 = Short.parseShort(str);
int num3 = Integer.parseInt(str);
long num4 = Long.parseLong(str);
float num5 = Float.parseFloat(str);
double num6 = Double.parseDouble(str);

/*
    取下标为 0 的字符(得到 str 的第一个字符)
	下标是从 0 开始,以 1 递增,并不是从 1 开始哦
*/	
char num7 = str.charAt(0);

// 如果解析不是"true"的字符串,那么返回结果是 false
boolean num8 = Boolean.parseBoolean("true");

System.out.println(num1);// 123
System.out.println(num2);// 123
System.out.println(num3);// 123
System.out.println(num4);// 123
System.out.println(num5);// 123.0
System.out.println(num6);// 123.0
System.out.println(num7);// 1
System.out.println(num8);// true

注意不要想着把字符串 "abc" 转成整数,编译虽然可以通过,但运行时会报 java.lang.NumberFormatException 异常(数字格式化异常),程序会在抛出异常的位置终止执行。(异常中有讲)

编译时只是检查语法,并不会解析 "abc" 是否能够转成整数。

总结回顾

变量

数据类型 变量名 = 值; 先声明后访问。

数据类型

分为基本数据类型(byte、short、int、long、float、double、char、boolean)与引用数据类型(类、接口、数组)。

不能直接以双等号判断两个浮点类型的值。应该让两数相减得到差值,如果差值在设定的精度范围内就认为它们相等。

脑海练习

3.1 下面语句能够通过编译吗?

1)

byte b = 2;
b = b * 2 + 10L;

2)

int i = 3;
float f = i + 2.22;

3)

int i = 21;
long l = 231;
double d = 3.23;

long l2 = i + l + d;

4)

int x = (int)3.14 * 3 + 6.2 * 10;

5)

short s1 = 34;
short s2 = s1 - 3;

6)

int i = 3;
char c = (char)i;

7)

byte b1 = 4 * 3;
byte b2 = b1 + (byte)4;

short s = b1 + b2;

8)

double d = 3;
float f = (float)d + .234F;

9)

long l = 3L;
double d = l + 3.24F;

3.2 下面输出结果?

1)

int x = (int)3.14 * 3 + 6 * 10;
System.out.println(x);

2)

int x = (int)(3.14 * 3 + 6.2 * 10);
System.out.println(x);

3.3 想在控制台上输出 \,怎么写?

3.4 想在控制台上输出如下,怎么写?

参考答案

第一章答案

1.1

JVM(Java Virtual Machine)Java 虚拟机,Java 程序需要运行在虚拟机上,根据不同平台的虚拟机,能够实现跨平台的功能。(编译一次,生成的字节码文件可以在不同平台运行)

JDK(Java Development Kit)Java开发工具包,包含了 JRE 和开发工具(javac.exe、javadoc.exe、javap.exe 等),不仅可以运行 Java 程序,也可以开发 Java 程序。

JRE(Java Runtime Environment)Java运行环境,包括 JVM、核心类库(常用类)等。

JDK 中包含 JRE,如果只想运行 class 文件,JRE 就足够。

JDK > JRE > JVM

1.2

编程:解决某个问题而使用某种编程语言编写程序代码控制电脑得到结果的过程。

使用高级语言编写的源代码需要进行编译或解释,能够让操作系统识别,理解你的意图,接收一系列的指令去一步步操纵硬件工作,最终解决某个问题。

1.3

Swing 包含了构建图形界面(GUI)的各种组件,如按钮、标签、窗口、面板、文本框等组件。你现在看到的 QQ、微信等软件就是一个图形界面,里面是各种类型的组件组成。

1.4

jar 包也称类库。源码编译后生成对应的 .class 字节码文件,为了完成某些功能通常需要多个 .class 文件的配合。jar 包主要对多个 .class 文件打包,类似 zip 压缩格式的文件,但不同的是 jar 多了 META-INF\MANIFEST.MF 文件,里面有 jar 包的创建人、版本等信息;若是可执行的 jar 包(有 main 方法),会包含 Main-Class 属性,表示 main 方法在哪个类中。

1.5

软件可以完成特定的功能,可以理解为应用程序的集合。而应用程序是软件的一个组成部分,它是软件的必要元素。简单来说,软件 = 程序 + 文档 = 数据结构 + 算法 + 文档。

程序指计算机执行某些操作或解决某个问题而编写的一系列有序指令的集合。

1.6

使用计算机语言(一大串二进制数)或汇编语言,一个指令只能对应一个操作中的一个细微的动作,太繁琐,不利于记忆,容易出错,开发效率极低。计算机语言能够被计算机直接识别,执行效率最高。(面向机器)

后来生成了高级语言,方便让人类理解,开发效率高。但是编写的源代码不能被机器识别,需要翻译成机器可以识别的语言,请看下答的平台无关性

1.7

1)面向对象

面向对象虽然执行效率没有面向过程高,但是以类的方式管理大量代码时(一个类中有变量、方法、代码块、内部类),更加方便程序员组织和管理代码,思路更清晰不易出错。

由此才有了对象、继承、封装、多态等概念。

① 对象:使用类为模板指定参数创建的实例,通过实例可以调用类中定义的方法、访问类中的字段,不会混乱。

② 继承:解决多个类中重复出现的代码,只要继承了一个类,自动拥有这个类的全部字段和方法。(私有、构造器、静态、final除外)

③ 封装:为了保护数据,不被错误的修改;在类、字段、方法上添加访问权限修饰符,如 private,只允许在本类中访问,再提供公开的 set 与 get 方法以供别人修改(在方法中可以添加判断逻辑来决定是否赋值)或访问本类的字段。此外还有包机制可以管理大量的类,可以区分两个同名类、将类似功能的类放在同一个包下...

④ 多态:子类继承了父类,但不满意父类的方法实现,可以重写此方法,表面是父类型,但可能底层为子类实例,调用的方法是子类重写后的方法,展现了不同的结果。

① 对象:把自己当作上帝,想要创建一只狗,想一想狗的特征、行为有哪些,在类中定义字段用以保存狗的颜色、大小、品种信息,定义方法体现狗的行为。

public class Dog {
    //private私有化,防止坏人直接修改狗的年龄
    private int age;//定义age变量用以保存年龄
    private String name;//name保存姓名
	
    //方便别人访问狗的年龄,但不允许修改就不提供set方法
    public int getAge() {
        return this.age;
    }
    
    //狗吃饭时的表现
    public void eat() {
        System.out.println(this.name + "开心地摇起了尾巴!");
    }
    //有参构造器略
}

然后使用 new 关键字创建狗,同时指定狗的初始属性值。

new Dog(3, "土狗");

② 继承:想一想子女能够继承父母的财产吧。

③ 封装:父母可不能什么都让你访问,总要有自己私人的东西吧。

④ 多态:你老爸有事不能去了,你可以代替老爸,以他的身份参加这次宴席,你要是不满意老爸继承给你的如何为人处事的方法,可以使用自己的方法应对这些客人。

Father huYingJun = new Father();
huYingJun.call();// 您好啊,真高兴见到你。

Father huTuTu = new Son();
huTuTu.call();// 我会动耳神功,你要看吗?

当然你如果不想使用面向对象,嫌麻烦还要设计字段、方法,也可以把所有变量、方法都塞进一个类中,只是看着乱糟糟的,不好维护。(代码量很少时,没有必要使用面向对象)

2)平台无关性

编写出的代码不可直接被机器识别,需要工具进行转换。

先讲编译器与解释器的区别:

① 编译器将源代码一次性全部翻译,生成一个二进制码文件,这个文件可以直接被机器识别,执行效率高。如果源代码改动需要重新编译生成新的二进制码文件。

② 解释器将源代码逐行解释成特定平台的机器码,解释一行执行一行。每次执行都需要翻译,跨平台性好。

Java 的做法:

③ Java 源代码会被编译成字节码文件,这个字节码文件是与任何平台都无关的中间代码,由 JVM 启动解释器翻译成对应平台上的机器码,所以一份字节码可以在任何平台上运行。前提:不同平台上要安装对应的 JVM,JVM 不跨平台。

之所以这么做,是 Java 既想保持解释语言的跨平台性(可移植性),又想解决解释语言执行效率低的问题。

但效率还是不如编译性语言。为了避免解释型语言带来的执行效率低的问题,Java 设计者制作了 JIT(just in time compilation)实时编译程序,将运行频率很高的字节码直接编译为机器指令执行来提高性能。

① 给一个英语文件,你看不懂,有人直接将英语文件翻译成汉文,将翻译的结果保存在一本书中,给你发过去;这样你每次就直接看这本翻译后的书即可,缺点是原著改了,你又需要请他翻译一下。

② 有人跟在你身边,你看一句,他就说一句这是什么意思;即使你换了一本英语书,他照样解释给你听,只不过效率低。

③ 有的人没有直接翻译成汉文,而是记录了源文件的重要信息、文章主题、中心思想、具体脉络等,再以后看到这份批注,能够迅速理解原文含义,get 到这个点,能够不假思索说给你听。

后来发现也挺麻烦,他干脆挑出你最喜欢、频繁看的部分,将这部分先翻译好了,等你需要看别的地方时,再请教他。

所以不要纠结这个语言究竟是编译执行、还是解释执行,没有多大意义。

3)支持多线程

a)线程与进程

① 进程:每个运行的程序都会开启一个独立的进程,如 QQ、酷狗音乐;操作系统为进程分配内存空间。

② 线程:由线程创建,是线程的最小执行单位,一个进程至少有一个线程,用以完成任务。比如迅雷同时下载多个文件、QQ 打开多个窗口等,多个任务同时执行。

单线程:一个进程同一时刻只有一个线程。

多线程:同一时刻有多个线程用以完成任务。

b)CPU 处理线程的方式

① 并行:同一个时刻,多个任务同时执行(多个 CPU)

② 并发:同一个时刻,多个任务交替执行(单个 CPU),通过 CPU 调度,速度十分快,造成貌似同时执行的错觉。

③ 串行:按先后顺序依次执行任务,一次只做一件事。后面的任务想要执行,必须等前面的任务执行完毕。

① 并行:吃饭时来了电话,你叫老婆接,自己吃饭;接电话与吃饭同时执行。

② 并发:吃饭时来了电话,边吃饭边接电话,感觉像是同时,但是不可能真正在同一个时刻做到吃饭和说话,这样会呛到鼻子去。

③ 串行:吃饭时来了电话,先吃完饭,再打电话。

并发和并行可以同时存在,比如两个 CPU,一个 CPU 在处理 QQ 线程,另一个 CPU 来回切换处理浏览器和音乐播放器。

c)线程之间的关系

① 同步:一个线程需要等待另一个线程执行完毕,返回了消息,才能继续往下运行。

② 异步:一个线程 A 对另一个线程 B 发起请求,可以不用等待 B 返回消息,因为 B 线程执行完后会通知你,你直接去干别的事情了;等到接受通知后,再处理。

d)单个线程的状态

① 阻塞:一个线程在等待的过程啥也不干。

② 非阻塞:没必要一直等待,可以干别的事。

同步阻塞:快递员给你打电话,说楼下有你的快递;当你没拿之前,他就一直在原地等你,不能走开,啥也干不了。

同步非阻塞:快递员给你打电话,说楼下有你的快递;当你没拿之前,他觉得一直在原地等你很无聊,决定跑下步、玩手机、时不时观察你下来了没有、直接上楼...

异步非阻塞:快递员给你发短信,说快递放到菜鸟驿站了;随后没有等你来拿,直接把短信继续发给下一个人。直到你签收后,他那边才接收到消息,然后做相应处理。

异步阻塞:别人拿完快递后,自然会有信息通知你,你完全可以做其他事情,却还在那傻等。

4)安全性

双亲委派机制可以防止恶意加载同名字节码。

5)健壮性

异常处理机制:对可能出现异常的代码实现进行预先处理,防止遇见问题时,程序直接挂掉。

垃圾回收机制:自动清除长时间没使用的对象,防止内存泄漏(内存满了),这也算是简单性吧。

6)简单性

  • 封装、继承、多态很贴近生活。
  • 没有指针这复杂的概念。
  • 只支持类的单继承,多继承可以使用接口实现。
  • 垃圾回收机制,不需要手动释放内存。

1.8

JavaSE 标准版,包含核心类库。主要用来开发桌面应用,允许在桌面、服务器开发和部署 Java 应用程序。

JavaEE 企业版,帮助企业开发和部署可移植、可伸缩且安全的服务端 Java 应用程序,包括 Web 网页后台开发等。

JavaME 微型版,专门为在移动设备和嵌入设备上运行的应用程序提供一个健壮且灵活的环境。

第二章答案

2.1

编译生成的 .class 文件与具体平台、系统无关。

JVM 虚拟机是关键。程序运行时,由 JVM 负责解释执行 .class 文件,将其翻译成不同平台下的机器码并运行。需要注意的是,.class 文件是与操作系统平台无关的中间代码,不能直接运行。

JVM 不跨平台,不同平台需要安装不同的 JVM。

这么做的目的,在可移植的同时兼顾执行效率。此外还加入了 JIT(just in time)编器,把运行频繁的代码直接编译成与本地平台相关的机器码,需要时直接使用,不用再次翻译。

2.2

可以,源文件只要按规则定义了多个类,编译后会生成多个对应的 class 文件。

2.3

不是,只有被 public 修饰的类名必须与源文件名一致。

第三章答案

3.1

1)不能,从 long 转换到 byte 可能会有损失。

2)不能,从 double 转换到 float 可能会有损失。(2.22 默认被当作 double 处理)

3)不能,从 double 转换到 long 可能会有损失。

4)不能,从 double 转换到 int 可能会有损失。(强转符号只针对最近的操作数有效,只是把 3.14 转成了 int 类型,可以使用小括号提升优先级)

5)不能,从 int 转换到 short 可能会有损失。

6)可以。

7)不能,第 2 行报从 int 转换到 byte 可能会有损失;第 4 行报从 int 转换到 short 可能会有损失。

8)可以。

9)可以。

3.2

1)69

2)71(先算小括号里,得出结果再强转成 int)

3.3

System.out.println("\\");

3.4

System.out.println("动漫名称\t编剧\t价格\t销量\n微笑超人\t坂本\t1000\t0001");

资源地址

下面资源全部收集整理于网络并无偿提供,仅可用于个人学习交流;请勿转载、售卖或商用。侵权删!

文章中已经出现的网址可能不再出现,望谅解!

网盘链接

JDK8、11、17下载

天翼云盘链接:(访问码:ugv8)https://cloud.189.cn/web/share?code=iUzmi2VnqqQf

阿里云盘链接:https://www.aliyundrive.com/s/KXvgN16qjUW

奶牛快传传输链接:https://cowtransfer.com/s/6b17ed33caa04b

IDEA下载

阿里云盘链接:(提取码: 05ep)https://www.aliyundrive.com/s/AGtttoykCEA

天翼云盘链接:(访问码:2mqu)https://cloud.189.cn/web/share?code=AZ3quiRnEniq

奶牛快传传输链接:https://cowtransfer.com/s/990e3441f9ef46

Eclipse下载

天翼云盘链接:(访问码:5usd)https://cloud.189.cn/web/share?code=ZrQRVfrQzmEz

奶牛快传传输链接:https://cowtransfer.com/s/2048f7cd25ba4c

自己写的小玩意

天翼云盘链接:(访问码:2qop)https://cloud.189.cn/web/share?code=F3uemyueuAbe

工具网址

可能会使用到的在线工具网址如下

可能会使用到的工具下载链接如下

书中源码地址

参考文献

版权声明:本文版权著作权归以下链接的作者共有,遵循 CC 4.0 BY-SA 版权协议。商业转载请联系原作者获得授权,非商业转载请附上原文出处链接,未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。

参考视频链接

参考视频观点

引用视频观点

参考书籍名称

参考书籍观点

  • 书名:《Think in Java》《Java编程思想》,作者:【美】Bruce Eckel,译者:陈昊鹏、绕若楠,出版社:机械工业出版社,时间:2003

引用书籍观点

  • 书名:《阿里巴巴Java开发手册》,发布者:gujin520https://github.com/alibaba/p3c
  • 书名:《Effective Java 第三版》,作者:【美】Joshua Bloch(约书亚 · 布洛克),译者:俞黎敏,出版社:机械工业出版社,时间:2018

参考文章链接

参考文章观点

引用文章观点

鸣谢名单

以下排名不分先后:

分类:

技术点:

相关文章:

  • 2021-05-26
  • 2022-01-10
  • 2021-11-02
  • 2021-12-28
  • 2021-08-24
  • 2021-04-16
  • 2021-09-07
猜你喜欢
  • 2022-01-17
  • 2021-08-17
  • 2022-01-18
  • 2022-12-23
  • 2021-04-18
  • 2022-01-19
相关资源
相似解决方案