精华内容
下载资源
问答
  • 自学编程的 6 个致命误区

    万次阅读 多人点赞 2020-04-24 09:14:23
    本篇文章来和大家聊聊自学编程中的一些误区——这是我在 B 站上看了羊哥的一期视频后有感而发的文章。因为确实有很多读者也曾私信问过我这些方面的问题,很有代表性,所以我就结合自己的亲身体会来谈一谈,希望对小...

    嗨,小伙伴们大家好,我是沉默王二。本篇文章来和大家聊聊自学编程中的一些误区——这是我在 B 站上看了羊哥的一期视频后有感而发的文章。因为确实有很多读者也曾私信问过我这些方面的问题,很有代表性,所以我就结合自己的亲身体会来谈一谈,希望对小伙伴们有所启发。

    01、追求时髦

    所谓基础不牢,地动山摇啊。可很多小伙伴压根就没注意过这个问题,市面上出什么新鲜的技术就想去尝试,结果把自己学的乱七八糟,心灰意冷。

    别的语言我不懂,就拿 Java 来说吧。时下最火热的技术,有微服务 Spring Boot、有分布式 Spring Cloud,虚拟容器 Docker,流处理框架 Flink 等等等等,但如果你连 JDK、JRE 和 JVM 都搞不清楚的话,那这些技术学起来可想而知有多痛苦。

    我从一开始写作那会就计划着用半年的时间把 Java 基础方面的文章写完,结果呢,写了一年多,发现还有特别多的内容没有覆盖到。

    学习是个漫长的过程,小伙伴们在学习一门语言的初期,一定要从基础开始,不要着急,时髦的东西咱把基础夯实以后再来吃,不然容易撑着哈。

    02、孤军奋战

    透露给大家一个小心得,我有很多知识都是从小伙伴的留言当中学到的。

    我写文章从来不怕自己犯错,因为我有一颗强大的心,经得住批评和嘲讽。金无足赤,人无完人嘛,况且我一直认为自己就是一枚菜鸟,本着这种谦虚谨慎的态度,我想说一句哈,文章中有些知识点写错了,不是我不负责任,是我也在学习,我又不是孔子,传道受业解惑的,纯粹是为了和大家交流而已。

    对吧?如果你没有分享的勇气,只肯自己闷头学习,那么不好意思,你的成长是很有限的。

    这就和打战是一样的道理,要团队配合,不可孤军深入。

    我已经建了 8 个学习交流群了,有些小伙伴进去后一开始嫌人少,不想做元老,想去人多的,可到了人多的群里仍然沉默,一言不发;有的小伙伴呢,不管三七二十一,有问题就是问,这次没人回答,下次还是问。

    这种心态非常值得肯定。为什么这么说呢?群嘛,不可能所有人都在盯着你的问题,也不是所有人都会解答你的问题,问不到答案是很正常的一件事。

    但提问本身是具有重大意义的,因为你会在提问的过程中组织语言,你总得把问题描述清楚啊,不然别人解答也无从下手,对吧,陈述的过程是要花心思的。一旦你的大脑在高速运转,那么答案很可能自己就找到了。

    03、刻意记忆

    有好几个小伙伴曾发私信给我说,“二哥,总感觉学完就忘,可怎么办啊?”

    其实这种困惑真的没有必要,因为人总会忘的,忘是一种常态,我连勾股定理都忘了。还记得张三丰教张无忌太极拳那个桥段吧,忘,忘了,才能学新的。

    我们学习,其实从某种层面上来看,学的是一种学习的能力,而不是死记硬背的知识,对吧?

    在我的概念里,不管你是名校毕业,还是野鸡大学毕业,只要你能在工作中解决问题,那就会受到重视。解决问题就不需要你记忆大量的知识点,记不住了问搜索引擎啊。

    其实,我最讨厌的就是那些炫耀记忆力的,真不如炫耀一下学习力。互联网解决了人类一大难题,就是信息的存储和检索,对吧?

    我上学的年纪,没有手机,没有互联网,查个字只能翻一本厚厚的新华字典,效率极低。甚至为了写作文,背大量的名句典故,虽然现在考生还需要,但我觉得早晚要被取代。

    对于程序员来说,就更没有必要记那么多知识点了,除非——你要面试。说起来这事,我觉得很有必要以后面试的时候,上机联网考试,咱们不扯那些没用的,你要造火箭,咱造就不就完事了。

    多花点心思搞创新,提高学习能力,它不香吗?

    04、怀疑自己

    世界上优秀的人毕竟是少数,大部分都非常平凡。只有意识到这一点,你才能做到不妄自菲薄。

    我时常遇到一些小伙伴,说:“二哥,我学历不好,我出身不好,我在公司好像不受到重视。”针对这些小伙伴,我只能说,心理建设真的非常非常重要。老怀疑自己,你怎么可能变得更强?赶紧把那些自卑扔到垃圾桶,与其卖惨博同情,不如自我超越。

    不是所有人都是学霸,也不是所有人家庭条件都很优渥,作为一个平凡人,我们必须要学会自信,学会扬长避短。

    我就写不了高大上的技术文章,甚至有些文章还会出现一些错误,没关系的,真的,有人爱喷就让人家喷啊,那是人家的自由。

    因为被别人喷就停滞不前,不敢分享,那是弱者的表现,真正的勇士敢于直面别人的口水。我敢说我就很勇敢,有啥好怕的呢?总有人欣赏你的。

    我以前非常喜欢一本书,叫《自卑与超越》,读了很多遍,虽然没有找到超越的秘诀。但不得不说,这本书的书名非常棒,对吧?不要和那些优秀的人比,你需要超越的不是他们,而是从前的自己。我就不信,真的是活一天不如一天?

    可以允许别人超越你,但绝不能允许自己怀疑自己。

    05、收集资源

    好像网络上特别流行一句话,叫做:“收藏从未停止,学习从未开始。”每次看到都觉得特别扎眼,有些人是处于调侃,有些人呢,是真的养成了习惯,见到好的文章,见到长篇大论就赶紧收藏,但从来没有认真从里面学习到一丁点知识。

    哪怕你看 100 字,看 200 字,从中真的学习到一点,然后把它扔到垃圾箱,都比你把它放到收藏夹吃灰,强上一百倍。

    我公众号里不是整理了 500G 的教学视频嘛,然后我就观察啊,有些小伙伴呢,一次性就想把所有的视频全都取走;而有些小伙伴呢,一天过来取一集。我认为,后者要比前者更能学到知识。

    网络上资源真的是已经泛滥了,除了坏的,好的都快。。。。。。你花一辈子都看不完,真的。

    与其收藏,真不如每次看到就学一点,哪怕学一分钟,对吧?

    最近一段时间,我每天到 B 站刷 2 集视频,咱不多刷,然后就地消化,等到真的融会贯通了,再去刷新的。

    这样的好处显而易见,刷一集就吸收一点,长年累月下去,那自然身强体壮啊。

    06、想学最好的编程语言

    每次谈论“谁是最好的编程语言”这个话题,总忍不住把“PHP 是世界上最好的语言”这个梗扔出来。真的,不管是不是梗,“想学最好的编程语言”就是一个伪命题。

    每种语言都有它存在的道理,但也有它的生命周期。我们所能做到的,就是学一门,爱一门,真的把它变成养家糊口的工具。

    对于程序员来说,技术永远都是学不完的,因为时代在进步啊,新鲜的有活力的新语言早晚都要出现。如果你不能从中获利,那么学哪门语言都白搭。

    就目前来说,Java 肯定是就业形势非常好的一门语言。Python、C++、C#、C 等等等等,几乎市面上没有被淘汰的语言都值得去学,不要挑肥拣瘦。

    我记得有一次,有个小伙伴就给我说,“二哥,你这么优秀,能预测一下未来十年里哪门语言最火吗?”

    哎呀,我去,当时我就感觉自己要懵逼。未来十年,计划得可真长远。别说十年,五年内我都预测不了。

    纠结于这个命题的小伙伴,让我想起了“铁饭碗”。偶尔听一些长辈谈论,你家孩子上那个什么什么学校吧,学什么什么专业吧,保准毕业后拿到一份稳定的工作,都什么年代了,还这么向往“铁饭碗”啊。

    语言之间都是相通的,真不假,虽然各自有各自的壁垒,但像我这种对编程没有极致追求的程序员,不也凭借 Java 这门编程语言养活了自己嘛。

    在我这 10 年程序生涯中,我搞过 Ruby,SQL、Flex、ActionScript、JavaScript、PrimeFace,甚至还有一段时间自学过 PHP。无论哪门子编程语言,我敢拍拍胸脯说,我能学会。关键是,挣到了钱,你信不信?

    谈钱多俗,对吧,但你学一门语言不就是为了挣个面包钱吗,只要能帮助我们达到这个目的,就是最好的编程语言。

    COBOL 程序员不是都被抢了吗?

    好了,亲爱的读者朋友,以上就是本文的全部内容了,能看到这里的都是最优秀的程序员,我必须要伸出可爱的大拇指为你点个赞。

    如果觉得文章对你有点帮助,请微信搜索「 沉默王二 」第一时间阅读。本文已收录 GitHub,传送门~ ,里面更有大厂面试完整考点,欢迎 Star。

    我是沉默王二,一枚有颜值却靠才华苟且的程序员。关注即可提升学习效率,别忘了三连啊,点赞、收藏、留言,我不挑,嘻嘻

    展开全文
  • 推荐一个学习群 java《学习》+交流 523401738首先说结论:Java绝对不是最容易学或者最容易上手的语言。我们稍微观察最近几年开始大规模进入大家实现的几门新兴编程语言,包括Python,包括苹果主推的Swift等等,它们在...

    作为一个超过10年以上工作经验的Java开发者,我觉得应该可以来回答一下。

    推荐一个学习群 java《学习》+交流 523401738

    首先说结论:Java绝对不是最容易学或者最容易上手的语言。

    我们稍微观察最近几年开始大规模进入大家实现的几门新兴编程语言,包括Python,包括苹果主推的Swift等等,它们在宣传初期都不约而同的喜欢怼一下Java,并且理由出奇一致:我们只需要一句话就能写出hello world,但是Java需要定义类,定义方法,在方法内写输出,然后创建类的对象,再调用方法,实现输出。所以你看,我们这门语言多么简洁和高效。

    我想这也是很多新人不喜欢Java的原因。 但是我们不妨深究一下Java为什么在最初的时候就被设计成这样,顺便也能回答题主的问题。

    没错,Java最初的理念是脱胎于C++的。C++最大的成功之处是它是一门面向对象的语言。 什么是面向对象?万事万物皆对象。用面向对象的思想能够在最大程度上模拟真实的现实世界。 如果我们把“人”看成一个“类”,那么你我他、小张小李、隔壁练腰的老王都是这个类的独立“对象”。身高肤色腿长就全都是这些“对象”的“属性”,而吃饭睡觉工作等等行为就都是这些“对象”的“方法”——方法用来操控对象的属性,从而使对象做出一定的行为。众多对象的行为相互影响,就能做出更加惊天动地的事情——马爸爸这个“人类”的“对象”,用“说话演讲”这一方法,成功影响了十八罗汉们的“工作”这一方法,并提升了他们的“努力值”属性,最终造就了现在的阿里帝国。

    这就和我们玩升级打怪的游戏一样,对吧。

    而C++又是来源于C语言的。C语言没有面向对象的概念,是一门纯粹的“面向过程”的编程语言。我相信很多新手对“面向过程”这个概念都不甚了解。实际上在早期,编程的世界全部都是面向过程的,人们用程序语言直接去处理业务逻辑。

    你说需要在寄存器里放进去一个变量?好吧,我先看一下寄存器是否还有空间,如果没有的话,要看看哪些不再使用了,可以取出来,腾出空间,再把新变量放进去。这些操作在面向过程的编程思想中,每一次操作都可以只对应一条编程语句或是一小段简单的逻辑块。

    如何把大象放进冰箱?打开冰箱门,把大象放进去,关上冰箱门——这就是面向过程的思维方式,更直接了当。

    C语言是面向过程的语言,C++提出了面向对象的概念,但是仍然保留了面向过程的设计思想,而Java是纯粹的面向对象语言,没有面向过程的踪影了,它封装了它们,程序员不再那么容易看得到了。

    这也是为什么C++和Java在面世之初,被人们称为“高级编程语言”的原因之一。

    而前面所提到的一些新兴编程语言,它们所标榜的高效和简洁,其实就是典型的面向过程的编程思想。这也是新手们更容易接受和喜闻乐见的东西——简洁——别忘了推广语言也是需要宣传的,某些时候这真的只是宣传口径而已。

    但是你会发现一个很有意思的地方,如果你去苹果官方的Swift网站查看,会发现苹果仍然将这门语言称为面向对象的编程语言,事实上确实它也支持面向对象的编程方式——尽管你能在它的很多官方文档里看到大量的面向过程的编程思想。

    想想为什么这些语言一边标榜自己比Java更简洁,又要一边说自己是面向对象语言呢,这不是左右互搏么。

    其实是面向对象的方式虽然看起来冗长复杂,但是它更接近人类的自然思维模式,这一点如果不能深刻理解面向对象概念的话,是很难体会的。但是它确实在软件领域能够解决很多更大规模和复杂的事情——数一数有多少互联网巨头在发展之初都是使用更简洁的编程语言,但最后发展到一定的规模后,都不约而同在底层基础架构层面转向了Java吧,他们应该没有串通好或者被Java收买。

    其实编程只是软件工程工作过程中的一个环节,而语言又只是编程的工具,没有好坏之分,只有合适不合适。

    新人出于本能选择更简单更容易上手的语言是很正常的,但是想要在这一行业内做出成绩来是需要巨大的付出的,但这已经和语言无关了。



    作为一个超过10年以上工作经验的Java开发者,我觉得应该可以来回答一下。

    题主的问题比较大,要回答好需要了解很多编程语言的基本知识和设计理念。

    首先说结论:Java绝对不是最容易学或者最容易上手的语言。

    我们稍微观察最近几年开始大规模进入大家实现的几门新兴编程语言,包括Python,包括苹果主推的Swift等等,它们在宣传初期都不约而同的喜欢怼一下Java,并且理由出奇一致:我们只需要一句话就能写出hello world,但是Java需要定义类,定义方法,在方法内写输出,然后创建类的对象,再调用方法,实现输出。所以你看,我们这门语言多么简洁和高效。

    我想这也是很多新人不喜欢Java的原因。 但是我们不妨深究一下Java为什么在最初的时候就被设计成这样,顺便也能回答题主的问题。

    没错,Java最初的理念是脱胎于C++的。C++最大的成功之处是它是一门面向对象的语言。 什么是面向对象?万事万物皆对象。用面向对象的思想能够在最大程度上模拟真实的现实世界。 如果我们把“人”看成一个“类”,那么你我他、小张小李、隔壁练腰的老王都是这个类的独立“对象”。身高肤色腿长就全都是这些“对象”的“属性”,而吃饭睡觉工作等等行为就都是这些“对象”的“方法”——方法用来操控对象的属性,从而使对象做出一定的行为。众多对象的行为相互影响,就能做出更加惊天动地的事情——马爸爸这个“人类”的“对象”,用“说话演讲”这一方法,成功影响了十八罗汉们的“工作”这一方法,并提升了他们的“努力值”属性,最终造就了现在的阿里帝国。

    这就和我们玩升级打怪的游戏一样,对吧。

    而C++又是来源于C语言的。C语言没有面向对象的概念,是一门纯粹的“面向过程”的编程语言。我相信很多新手对“面向过程”这个概念都不甚了解。实际上在早期,编程的世界全部都是面向过程的,人们用程序语言直接去处理业务逻辑。

    你说需要在寄存器里放进去一个变量?好吧,我先看一下寄存器是否还有空间,如果没有的话,要看看哪些不再使用了,可以取出来,腾出空间,再把新变量放进去。这些操作在面向过程的编程思想中,每一次操作都可以只对应一条编程语句或是一小段简单的逻辑块。

    如何把大象放进冰箱?打开冰箱门,把大象放进去,关上冰箱门——这就是面向过程的思维方式,更直接了当。

    C语言是面向过程的语言,C++提出了面向对象的概念,但是仍然保留了面向过程的设计思想,而Java是纯粹的面向对象语言,没有面向过程的踪影了,它封装了它们,程序员不再那么容易看得到了。

    这也是为什么C++和Java在面世之初,被人们称为“高级编程语言”的原因之一。

    而前面所提到的一些新兴编程语言,它们所标榜的高效和简洁,其实就是典型的面向过程的编程思想。这也是新手们更容易接受和喜闻乐见的东西——简洁——别忘了推广语言也是需要宣传的,某些时候这真的只是宣传口径而已。

    但是你会发现一个很有意思的地方,如果你去苹果官方的Swift网站查看,会发现苹果仍然将这门语言称为面向对象的编程语言,事实上确实它也支持面向对象的编程方式——尽管你能在它的很多官方文档里看到大量的面向过程的编程思想。

    想想为什么这些语言一边标榜自己比Java更简洁,又要一边说自己是面向对象语言呢,这不是左右互搏么。

    其实是面向对象的方式虽然看起来冗长复杂,但是它更接近人类的自然思维模式,这一点如果不能深刻理解面向对象概念的话,是很难体会的。但是它确实在软件领域能够解决很多更大规模和复杂的事情——数一数有多少互联网巨头在发展之初都是使用更简洁的编程语言,但最后发展到一定的规模后,都不约而同在底层基础架构层面转向了Java吧,他们应该没有串通好或者被Java收买。

    其实编程只是软件工程工作过程中的一个环节,而语言又只是编程的工具,没有好坏之分,只有合适不合适。

    新人出于本能选择更简单更容易上手的语言是很正常的,但是想要在这一行业内做出成绩来是需要巨大的付出的,但这已经和语言无关了。

    说了那么多,最后把问题抛还给题主,你自己现在怎么思考的呢。


    展开全文
  • (二)java面向对象编程知识模块较完整)

    千次阅读 多人点赞 2018-08-07 15:01:35
    这一篇文章讲的内容不太容易理解,但是同时也是java最为重要的一块理论知识,需要大家好好琢磨清楚。 1.编程语言的发展(这儿大致了解就行):发展是朝着人类更内容理解的方向。 机器语言:直接由计算机的指令组成...

    这一篇文章内容不太容易理解,但是同时也是java最为重要的一块理论知识,需要大家好好琢磨清楚。

    1.编程语言的发展(这儿大致了解就行):发展是朝着人类更内容理解的方向。

    机器语言:直接由计算机的指令组成,指令、数据、地址都以“0”和“1”的符合串组成;可以被计算机直接执行。

    汇编语言:用容易理解和记忆的符号表示指令、数据以及寄存器等,抽象层次很低,程序员需要考虑大量的机器细节。

    高级语言:屏蔽了机器细节,提高了语言的抽象层次接近人的自然语言,60年代出现的结构化编程语言提出了结构化数据和语句,数据和过程抽象等概念。

    面向对象的语言:与以往的各种语言的根本不同是,它的设计出发点就是为了更能直接的描述问题域中客观存在的事物。

    2.面向过程的设计思想和面向对象的设计思想

    面向过程就是分析出解决问题需要的步骤,然后用函数把这些步骤一个个实现,使用的时候依次调用,面向过程的核心是过程。

    面向对象就是把构成问题的事物分解成一个个对象,建立对象不是为了实现一个步骤,而是为了描述某个事物在解决问题中的行为,面向对象的核心是对象。

    3.java面向对象的基本概念

    (1)对象和类的概念(有了类再去找对象)

    对象用计算机语言对问题域中事物的描述,对象通过“属性attribute”和“方法method”来分别对应事物所具有的静态属性和动态属性。

    类是用于描述同一类型的对象的一个抽象的概念,类中定义了这一类对象所因具有静态和动态属性。

    类可以看成一类对象(object)的模版,对象可以看成该类的一个具体实例(instance)。

    举例:如瓶子(一类事物的抽象)类比于类(类中包括成员变量(静态属性,也叫属性),方法(动态属性));这个啤酒瓶就是瓶子的一个实例,也就是我们常说的实例化后的对象。

    (2)类(对象)之间的关系

    1)关联关系(最弱):类与类之间的连接,它使得一个类知道另外一个类的属性和方法。

    2)继承关系(能用“XX是一种XX”,这种形式来描述),理论上一个类可继承多个父类(但ava不允许多继承,只能继承一个父类,但是可以实现多个接口)

    3)聚合关系(整体和部分)

    聚集:松耦合(并不是说离了哪个不行)

    组合:密不可分

    组合与聚合几乎完全相同,唯一区别就是对于组合,“部分”不同脱离“整体”单独存在,其生命周期应该是一致的。

    4)实现关系:实现是指一个class实现interface接口(一个或者多个),表示类具备了某种能力,实现是类与接口中最常见的关系,在Java中通过implements关键字来表示。

     

    (3)java与面向对象

    对象是java程序的核心,在java程序中“万事万物皆对象”。

    对象可以看成是静态属性(成员变量)和动态属性(方法)的封装体。

    类是用来创建同一类型的对象的“模版”,在一个类中定义了该类对象所应具有的成员变量以及方法。

    jdk提供了很多类供程序员使用,编程人员也可以定义自己的类。

    (6)成员变量

    Java类定义

    public class Person {
        //成员变量的定义
        private int id;
        private int age=20;
        private String sex;
    //    方法定义
        public int getId() {
            return id;
        }
        
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }

    成员变量:成员变量可以是java语言中任何一种数据类型(包括基本类型和引用类型)。

    在定义成员变量时可以对其初始化,如果不对其初始化,java使用其类型默认的初始化值(局部变量必须自己对其初始化,java不会默认对其初始化)。

    成员变量类型 初始化默认取值
    byte 0
    short 0
    int 0
    long

    0L

    char '\u0000'
    float 0.0F
    double 0.0D
    boolean false
    所有引用类型 null

    成员变量的作用范围为整个类体。

    (7)引用(提到引用二字,脑海中要想到它在内存中是一小块区域指向一大块区域,这对分析一个程序的内存变化有好处)

    java语言中除了八种基本类型之外的变量类型都称之为引用类型(引用类型在内存中占两块)。

    java中的对象是通过引用对其操作的。

            /*
              声明了一个String类型是的引用变量,
              但并没有使它指向一个对象
            */
            String str;
            /*
              使用new语句创建了一个String类型的对象并用str指向它
              以后听过str完成对其的操作
             */
            str = new String("hello world");

    过程内存分配图:

    如何在内存中区分类和对象?

    1)类是一个静态的概念,它是放在代码区里面的。

    2)对象是new出来的,位于堆内存(用于在运行期间动态分配内存,堆的内存区比较大,如果分配的内存不用了,则会被GC回收)

    3)类的每个成员变量在不同的对象中都有不同的值(除了静态变量),而方法只有一份,执行的时候才占用内存。

    4.对象的创建和使用

    1)必须用new关键字来创建对象。

    2)使用对象(引用).成员变量来引用对象的成员变量。

    3)使用对象(引用).方法(参数列表)来调用对象的方法。

    4)同一类的每个对象有不同的成员变量存储空间(new一个新对象就产生一块新内存)。

    5)同一类的每个对象共享该类的方法。

          非静态方法是针对每个对象进行调用。

    6)成员变量(成员变量在new的时候才会在堆内分配)分配在堆内存局部变量分配在在栈(stack)内存。

    (8个原生数据类型的局部变量储存在栈中,成员变量储存在堆中。)

    以下程序的内存分析:

    public class C {
        int i;
        int j;
        public static void main(String[] args) {
            C c1=new C();
            C c2=new C();
        }
    }

    内存分配分析图(重要:建议好好琢磨清楚这张图):

    5.构造方法

    1)使用new+构造方法 创建一个新对象。

    2)构造方法是定义在java类中的一个用来初始化对象的方法。

    3)构造方法与类同名且没有返回值(注意,连void都没有)。

    4)当没有指定构造函数时,编译器为类自动添加无参构造方法,形如:ClassName(){}的构造函数。

    无参构造方法的例子:

    /**
     * 说明:无参构造方法举例
     *
     * @author huayu
     * @date 2018/8/2 下午9:17
     */
    public class Student {
        /*下面注释掉的在这个代码中可有可无,没有的话编译器会默认加一个无参构造方法
        (换句话说,类中若有参构造和无参构造都不写,后期编译器会默认给加一个无参构造方法)
         public Student(){}。所以若不定义有参构造方法,无参构造可写可不写(不写后期默认也会加上)。
         反之,一旦自己定义了构造方法,系统就不会给默认添加任何构造方法了。
        */
    
        /*public Student() {
        }*/
    
        private  int id;
        private  int age;
        public static void main(String[] args) {
          /*调用无参构造时,可不传参数。调用下列语句(无参构造)时,id,age会被默认初始化为0。(不传 
            参数时,各个类型默认值以前讲过啦,忘了的可以翻一下博客文章看一下)
          */
           Student tom=new Student(); 
        }
    }

    本例内存分配分析图:

    有参构造方法例子:

    /**
     * 说明:有参构造方法举例
     *
     * @author huayu
     * @date 2018/8/2 下午9:17
     */
    public class Student {
        private  int id;
        private  int age;
        //构造方法
        public Student(int _id, int _age) {
            this.id = _id;
            this.age = _age;
        }
    
        public static void main(String[] args) {
            Student tom =new Student(1,25);
        }
    }

    本例内存分配分析图:

    6.内存分析详解(这个太重要了,一定要好好学)

    代码:

    package oop;
    
    /**
     * 说明:实体类
     *
     * @author huayu
     * @date 2018/8/3 
     */
    public class Birthday {
        private int day;
        private int month;
        private int year;
        //有参构造方法
        public Birthday(int day, int month, int year) {
            this.day = day;
            this.month = month;
            this.year = year;
        }
    
        public int getDay() {
            return day;
        }
    
        public void setDay(int day) {
            this.day = day;
        }
    
        public int getMonth() {
            return month;
        }
    
        public void setMonth(int month) {
            this.month = month;
        }
    
        public int getYear() {
            return year;
        }
    
        public void setYear(int year) {
            this.year = year;
        }
    
        @Override
        public String toString() {
            return "Birthday{" +
                    "day=" + day +
                    ", month=" + month +
                    ", year=" + year +
                    '}';
        }
    }
    
    
    
    
    
    
    
    
    import oop.Birthday;
    
    /**
     * 说明:测试类
     *
     * @author huayu
     * @date 2018/8/3 
     */
    public class TestBirthday {
        public static void main(String[] args) {
              //new TestBirthday();相当于调用了TestBirthday类的无参构造方法(编译器默认加的)
    1.        TestBirthday test=new TestBirthday();
              //调到这句在栈内存分配一块名为date,值为9的内存
    2.        int date=9;
              //new Birthday(7,7,1970);相当于调用了Birthday类中的有参构造方法
    3.        Birthday d1=new Birthday(7,7,1970);
    4.        Birthday d2=new Birthday(1,1,2000);
    5.        test.change1(date);
    6.        test.change2(d1);
    7.        test.change3(d2);
    8.        System.out.println("date="+date);
    9.        d1.toString();
    10.       d2.toString();
    
        }
        public void change1(int i){
    11.        i=1234;
        }
        public void change2(Birthday b){
    12.        b=new Birthday(22,2,2004);
        }
        public void change3(Birthday b){
    13.        b.setDay(22);
        }
    }
    

    内存过程分析:

    在做分析以前我们应该预备的知识有:

    1)栈内存储的是局部变量,基础类型的局部变量也分配在栈中,而且它只占一块内存:如下图栈中的局部变量date,一个int类型变量分配了一块int类型空间,四个字节,里面装了个值9,名字叫做date。

    2)引用类型在内存中占两大块(栈中跟堆中),一块在栈中存的是指向对象的引用(对象在堆中的地址),一块在堆中存的是new出来的对象。(凡是new出东西来,则在堆内存中做分配):如下图栈中的局部变量test,一个引用类型分配了一块内存用于存test的引用(即对象在堆中的存储地址,后期利用这个存储地址去找到并操作堆中new出来这个引用的对象),它指向了在堆中new出来的对象的一块内存(即图中那块未存东西的空位置)。

    3)方法中的形参与局部变量等同

    4)方法调用的时候是值传递

    5)方法执行完毕后,在栈中为这个方法分配的局部变量的空间全部消失。若方法调用有基本类型返回值,则栈中会为其提供一块暂存值的空间,返回值暂存在栈中,同样,当方法调用完毕后内存也会一同被收回。

    6)在堆中new出来的对象若栈中没有了它的引用(也就是不用它了),后期会被GC清理掉那部分堆中的内存,而GC回收的具体时间不可控。

    上面代码中当执行到TestBirthday中main方法第四句时,内存里面的布局是这个样子的(下图1中所示堆中的d1对象显示的好像是3块,其实就是一个块,也就是堆中就一个d1对象,我为了看起来清楚才这么画的自己知道就可以了,d2同理也是就一个对象)。

    (1)执行change1(int i)方法

    接下来我们开始执行第五句chage1(int i)方法,而里面有个形参i,当我们调用这个方法的时候,首先应该在栈里面为形参(与局部变量等同)分配一块空间,如下分配了一个空间名字叫i,值的话是实参传了多少就是多少,在这实参是date且值为9,所以形参i的值是9(方法调用的时候是值传递,相当于把date的值9复制给了i),此时的内存布局为图2:

    执行到第11句,i=1234;到这时i的值由9变为了1234,但是date值不会遍,因为i当时的值9是date复制了一份给它的,所以i的改变对date无影响。此时的内存布局为图3:

    当执行完change1方法后,形参i在栈中分配的空间被收回(注意这时date依然不受影响哈),此时的内存布局为图4

    (2)执行change2(Birthday b)方法

    首先,形参要求传一个Birthday  b的引用类型,所以我们将d1传进来。Birthday  b是一个局部变量,二话不说在栈内存空间内分配一个变量b,b中装的是实参中传的内容(即d1中的内容),当执行了这个方法之后,它会把d1中的值复制给b。此时b中的地址跟d1是一样的,他们指向的是同一个对象(堆中的d1对象)。此时的内存布局为图5:

    当执行第12句b=new Birthday(22,2,2004);这一句时,堆中这是又会new出一个新的对象(凡是new出东西来,则在堆内存中做分配),此时栈中的引用地址指向新new出来的b的对象(注意到栈中b的引用地址也变化了)。此时的内存布局为图6:

    当方法change2执行完毕后,为其在栈中分布的局部变量空间也随之消失。注意,此时栈中为方法执行分布的局部变量被收回了,但是它在堆上new出来的对象b不一定消失,它会等待GC来回收它,具体回收时间不可控,所以我们也不确定它什么时候能消失,但是弱栈中没有了指向它的引用,这个b对象迟早会被GC清理掉,早晚会消失。此时的内存布局为图7:

    (3)执行change3(Birthday b)方法

    首先,形参要求传一个Birthday  b的引用类型,所以我们将d2传进来。Birthday  b是一个局部变量,二话不说在栈内存空间内分配一个变量b,b中装的是实参中传的内容(即d2中的内容),当执行了这个方法之后,它会把d2中的值复制给b。此时b中的地址跟d2是一样的,他们指向的是同一个对象(堆中的d2对象)。此时的内存布局为图8:

    当执行到第13句b.setDay(22);(是Birthday类中的public void setDay(int day) {this.day = day;}这个方法),它会利用b这个引用去操作d2对象,当传入实参22给int day后它会把值传给this.day,则day的值真正被改变了(注意,此时的栈中b引用跟d2引用的值都没变,还是指向同一个对象)。此时的内存布局为图9:

    当方法change3执行完毕后,为其在栈中分布的局部变量空间也随之消失。注意,虽然此时栈中b引用虽然消失了,但它指向的对象d2还有栈中的d2引用在,所以堆中对象d2不会消失。此时的内存布局为图10:

    change1,change2方法调用完后,或早或晚的栈内存,堆内存中分配的空间的都会被回收,没起任何实质性作用,相当与白调了。而change3方法调用了实体类Birthday中的具体方法,确实并对堆内存中仍然被栈空间的引用d2所引用的堆内对象做了修改产生了实质性作用。

    7.方法的重载:重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载。

    注:1)参数列表不同包括两种:参数类型,参数个数有一个不同就可以。

           2)重载对返回类型没有特殊的要求。

          3)方法重载的本质是在重载方法被调用时,会根据不同的参数表选择对应的方法,只要能区分开来不会混淆则他们两个方法        就是重载。

          4)调用时,会根据不同的参数选择对应的方法,实现的是编译时的多态性。

          5)构造方法也可以被重载,但不可以被重写,因为构造方法不能被继承。

    举例:

    /**
     * 说明:方法重载举例
     *
     * @author huayu
     * @date 2018/8/3 
     */
    public class Overload {
        public void max(int a){
            System.out.println(a);
        }
        public int max(int a,int b){
            System.out.println(a>b?a:b);
            return a>b?a:b;
        }
        public void max(int a,int b){
            System.out.println(a>b?a:b);
        }
        public void max(short a,short b){
            System.out.println(a>b?a:b);
        }
        public void max(float a,float b){
            System.out.println(a>b?a:b);
        }
    }
    
    
    
    /**
     * 说明:构造方法重载举例
     *
     * @author huayu
     * @date 2018/8/3 
     */
    public class Overload {
        private int a;
        private int b;
    
        public Overload() {
        }
    
        public Overload(int a) {
            this.a = a;
        }
    
        public Overload(int a, int b) {
            this.a = a;
            this.b = b;
        }
    }
    

    8.this关键字

    1)在类的方法定义中使用this关键字代表代表使用该方法的对象的引用

    2)当必须指出当前使用方法的对象是谁时要用this。

    3)有时使用this可以处理方法中成员变量和参数重名的情况。

    4)this可以看作是一个变量,它的值是当前对象的引用。

    强调:this一般出现在方法里面,当这个方法还没调用的时候,this指的是谁并不知道,但是实际当中你如果new一个对象出来的话,this指的就是当前这个对象。你对那个方法调这个对象,那么this指的就是谁。

    /**
     * 说明:this用法举例
     *
     * @author huayu
     * @date 2018/8/3 下午5:39
     */
    public class Leaf {
        int i=0;
    
        public Leaf(int i) {
    1.        this.i = i;
        }
        public Leaf increament(){
    2.        i++;
    3.        return  this;
        }
        void print(){
    4.        System.out.println("i="+i);
        }
    
        public static void main(String[] args) {
    5.        Leaf leaf=new Leaf(100);
    6.        leaf.increament().increament().print();
        }
    }
    

    上面代码内存分析:

    第一步:通过执行main方法第5句,调到了Leaf类的构造方法Leaf(int i),这时栈空间为形参i开辟了一块内存,实参传入的值为100,又将栈内存中形参i的值赋值给了堆内存成员变量i,所以this.i=100。

    第二步:构造方法完成,为它分配的局部变量形参i消失。

    第三步:执行第6句leaf.increament().increament().print();  leaf.increament()执行leaf对象的increament()方法,执行i++;

    第四步:执行第3句return this;return会在栈空间分配一块临时的内存,这块空间是this的内容,而this指向它自身,所以这块临时内存也指向了对象leaf。leaf.increament()执行完成之后内存分布如下图:

    第五步:对leaf.increament()结果再调用increament()方法,即还是对原来的对象调用,执行完i++;后,成员变量i值变为102。

    第六步:再执行return this;return又会在栈空间分配一块临时的内存,这块空间是this的内容,而this指向它自身,所以这块临时内存也指向了对象leaf。

    第7步,调用完print()方法,整个方法执行完成后,栈中局部变量的内存空间回收

    9.static关键字

    1)在类中,用static声明的成员变量为静态成员变量,它为该类的公用变量。在第一次使用时候被初始化,对于该类的所有对象来说,static成员变量只有一份。

    2)用static声明的方法为静态方法,在调用该方法时,不会将对象的引用传递给它,所以在static方法中不可访问非static的成员。(静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,在调用静态方法时可能对象并没有被初始化)。

    3)可以通过对象引用或类名(不需要实例化)访问静态成员。

    4)static静态变量存在在data seg数据区,就算是不new它,它也会在data seg部分保留一份。静态变量是属于整个类的,它不属于某一个对象。  

    知识链接:字符串常量在内存中分配也是在data segment部分。

    /**
     * 说明:静态变量内存分析举例
     * 
     * @author huayu
     * @date 2018/8/3 
     */
    public class Cat {
        //静态成员变量,就算不new对象它也会在data seg里面保存一份,它属于整个类
        //不属于某个对象。int静态变量可以用来计数。
        //对静态值访问:1.任何一个对象通过对象的引用都可以访问这个静态对象,访问的时候都是同一块内存
        //2.即便是没有对象,也可以通过 类名. 来访问 如:System.out  out是个静态变量
    1.    private static  int sid=0;
        //非静态成员变量 new对象的时候在堆内存对象中保存,每new一个对象产生一块
    2.    private  String name;
        //非静态成员变量 new对象的时候在堆内存对象中保存,每new一个对象产生一块
    3.    private int id;
    
        public Cat(String name) {
    4.        this.name = name;
    5.        id=sid++;
        }
    
        public void info(){
    6.        System.out.println("My name is "+name+" No."+id);
        }
    
        public static void main(String[] args) {
            //静态变量sid属于整个Cat类,不属于某个对象,可以用类名.来访问,所以这儿没有new任何对 
            //象,直接用类名.(Cat.sid)来访问的。
    7.        Cat.sid=100;
            //字符串常量分配在data seg
    8.        Cat mimi=new Cat("mimi");
    9.        Cat pipi=new Cat("pipi");
    10.       mimi.info();
    11.       pipi.info();
    
        }
    }
    
    打印结果:
    My name is mimi No.id=100 sid= 102
    My name is pipi No.id=101 sid= 102
    

    执行完7Cat.sid时,静态变量sid值为100。内存分布状态如下:

    (1)执行第7句构造方法

    第一步:执行第7句Cat mimi=new Cat("mimi");字符串常量“mimi”分布在data segment部分,内存分布如下(这儿看不懂的再回去看以前我的java程序内存分析的博客):

    第二步:调到上面后就该到Cat的构造方法了,执行第4句this.name = name;这时根据传入构造方法的name形参,栈中就会为其开辟一块名为name的空间,实参“mimi”传了进来,这时候栈中name的引用指向了data segment中的字符串常量“mimi”,因为this.name = name,所以自身成员变量的this.name也指向了data segment中的字符串常量“mimi”。

    第三步:执行id=sid++;mimi对象的成员变量i值为原来sid的值100,接下来sid++,将sid的值改为101,内存状态如下图:

    第四步:构造方法执行完成后,为执行这个方法在栈中分配的形参变量的内存空间收回,name在栈中的空间消失(当然,为执行方法而在栈中分配的局部变量空间,方法执行完毕后都应该被收回了)

    (2)执行Cat pipi=new Cat("pipi"); 方法跟执行上面那个构造方法原理是一样的(当然,为执行方法而在栈中分配的局部变量空间,方法执行完毕后都应该被收回了),大家自己画一下,我这边把最后的内存分布状态给一下大家:

    从以上sid(static id)的变化不难看出,int的静态变量可以用作计数用。

    (3)将以上程序的static静态变量static int sid;再改为非静态变量 int sid;后做内存分析对比

    代码:

    /**
     * 说明:将上面代码静态变量改为非静态的再做内存分析
     *
     * @author huayu
     * @date 2018/8/3 下午6:32
     */
    public class Cat1 {
        //成员变量在new的时候才会在堆内分配
        private  int sid=0;
        private  String name;
        private int id;
    
        public Cat1(String name) {
            this.name = name;
            id=sid++;
        }
    
        public void info(){
            System.out.println("My name is "+name+" No.id="+id+" sid= "+sid);
        }
    
        public static void main(String[] args) {
    //        Cat1.sid=100;
            Cat1 mimi=new Cat1("mimi");
            Cat1 pipi=new Cat1("pipi");
            mimi.info();
            pipi.info();
    
        }
    }
    输出结果:
    My name is mimi No.id=0 sid= 1
    My name is pipi No.id=0 sid= 1

    对以上程序进行内存分析:这儿上面以前详细的讲过,大家亲自动手去画一画,感受了解一下静态变量跟非静态变量的区别,下面我给贴个最终状态的图(记得,为执行方法而在栈中分配的局部变量空间,最终方法执行完毕后都应该被收回了):

    从以上过程不难看出当静态变量static int sid;改为非静态变量int sid;后,每new一个对象,sid不再发生变化,故用它来计数是不可能了。

    10.package和import语句

    (1)package (包)例如:package  com.jd;

    1)为了便于管理大型软件系统中数目众多的类,解决类的命名冲突问题,java引入包(package)机制,提供类的多重类命名空  间。

    2)约定俗称的包起名方式:把公司的域名倒过来。如:package  com.jd;这个包包了两层(建包可不是只能建两层哈,别误会,只是这个例子中有两层),公司域名不是一样的,这样起名避免类名产生重复。

    3)package语句作为java源文件的第一条语句,指明该文件中定义的类所在的包。(若缺省该语句,则指定为无名包)。

    它的格式为package pkg1[.pkg2[.pkg3....]];

    4)java编译器把包对应于文件系统的目录管理,package语句中,用“.“来指明包(目录)的层次,例如package  com.jd;则该文件中所有的类位于.\com\jd 目录下

    5)class文件的最上层包的父目录应位于classpath下(在公司不同的项目一般设置不同的classpath)。

    6)要想执行一个类必须写全包名。如:java com.jd.TestPackage

    (2)import(引入):用于引入非同包类,同胞类不需要引入,直接用就可以。

         例:import oop.Birthday;  //引入oop包下的Birthday类

    11.j2sdk中主要的包介绍

    java.lang-包含一些java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。这里面的类不需要引入就直接能用,除了他之外其它包在用的时候必须要先引入。

    java.awt-包含了构成抽象窗口工具类(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界  面(GUI)。

    java.applet-包含applet运行所需的一些类。

    java.net-包含执行与网络相关的操作的类。

    java.io-包含能提供多种输入/输出功能的类。

    java.util-包含一些实用工具类,如定义系统特性、使用与日期日历相关的函数。

    知识补充:将自己写的类打成jar包备用。打jar包命令:jar -cvf

    192:java huayu$ jar
    用法: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
    选项包括: 
        -c  创建新的归档文件
        -t  列出归档目录
        -x  从档案中提取指定的 (或所有) 文件
        -u  更新现有的归档文件
        -v  在标准输出中生成详细输出
        -f  指定归档文件名
        -m  包含指定清单文件中的清单信息
        -e  为捆绑到可执行 jar 文件的独立应用程序
            指定应用程序入口点
        -0  仅存储; 不使用情况任何 ZIP 压缩
        -M  不创建条目的清单文件
        -i  为指定的 jar 文件生成索引信息
        -C  更改为指定的目录并包含其中的文件
    如果有任何目录文件, 则对其进行递归处理。
    清单文件名, 归档文件名和入口点名称的指定顺序
    与 'm', 'f' 和 'e' 标记的指定顺序相同。
    
    示例 1: 将两个类文件归档到一个名为 classes.jar 的归档文件中: 
           jar cvf classes.jar Foo.class Bar.class 
    示例 2: 使用现有的清单文件 'mymanifest' 并
               将 foo/ 目录中的所有文件归档到 'classes.jar' 中: 
           jar cvfm classes.jar mymanifest -C foo/ .

    用法举例:jar -cvf  Test.jar *.*

    192:java huayu$ jar -cvf Test.jar *.*
    已添加清单
    正在添加: HelloWord.class(输入 = 409) (输出 = 280)(压缩了 31%)
    正在添加: HelloWord.java(输入 = 124) (输出 = 106)(压缩了 14%)
    正在添加: Test.class(输入 = 187) (输出 = 160)(压缩了 14%)
    192:java huayu$ ls
    HelloWord.class	Test.class
    HelloWord.java	Test.jar//这就是那个打包完后的jar包

    12.访问控制

    java权限修饰符public protected private置于类的成员定义前,用来限定其他对象对该类对象成员的访问权限。

    修饰符 类内部 同一个包 子类 任何地方
    private yes(可以访问)      
    default yes(可以访问) yes(可以访问)    
    protected yes(可以访问) yes(可以访问) yes(可以访问)  
    public yes(可以访问) yes(可以访问) yes(可以访问) yes(可以访问)

    注意:1)对于class的权限修饰只可以用public和default。

              2)类的成员(包括内部类)的修饰符可以是以上四种。

              3)类的成员不写访问修饰时默认为 default,默认对于同一个包中的其他类相当于公开 (public),对于不是同一个包中的其                 他类相当于私有(private)。

              4)受保护(protected)对子类 相当于公开,对不是同一包中的没有父子关系的类相当于私有。

    13.类的继承与权限控制(继承关系:能说通XX是XX就可以看作继承关系,比如,狗是动物)

    继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、 基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续 性,同时继承也是封装程序中可变因素的重要手段。

    1)java中使用extends关键字实现类的继承机制,其语法规则为:<modifier>class<name>[extends<superclass>]{... ...}

    2)通过继承,子类自动拥有了父类(基类superclass)的所有成员(成员变量和方法)。

    3)java只支持单继承,不允许多继承(一个子类只能有一个基类,一个基类可以派生出多个子类)。

      代码举例:

    package oop;
    
    /**
     * 说明:
     *
     * @author huayu
     * @date 2018/8/5 1:03 PM
     */
    public class Person {
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    
    /**
     * 说明:
     *
     * @author huayu
     * @date 2018/8/5 1:05 PM
     */
    public class Student extends Person{
        private String school;
    
        public String getSchool() {
            return school;
        }
    
        public void setSchool(String school) {
            this.school = school;
        }
    }
    
    
    import oop.Student;
    
    /**
     * 说明:
     *
     * @author huayu
     * @date 2018/8/5 1:06 PM
     */
    public class TestStudent {
        public static void main(String[] args) {
    1.        Student student=new Student();
    2.        student.setName("yuhua");
    3.        student.setAge(18);
    4.        student.setSchool("BJTU");
    5.        System.out.println("name: "+student.getName()+" age:"+student.getAge()+" School:"+student.getSchool());
        }
    }
    

    以上程序的内存分析过程:

    第一步:执行第1句 Student student=new Student();这句后的内存状态:

    执行完main方法后,最终内存分布图(当然,为执行方法而在栈中分配的局部变量空间,方法执行完毕后都应该被收回了),这儿我给个贴图,过程不难自己分析,如果再不会就再好好看一下以前讲的内存分析的那部分知识:

    14.方法的重写(overwrite)

    1)在子类中可以根据对从基类中继承来的方法进行重写。

    2)重写方法必须和被重写方法具有相同的方法名称、参数列表和返回类型。

    3)重写方法不能使用比被重写方法更严格的访问权限(子类的权限不能小于基类,要大于等于才行)。

    4)变量的重写看引用,方法的重写看对象。

    /**
     * 说明:重写代码举例,基类
     *
     * @author huayu
     * @date 2018/8/5 1:03 PM
     */
    public class Person {
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    
    /**
     * 说明:重写代码举例,子类
     *
     * @author huayu
     * @date 2018/8/5 1:05 PM
     */
    public class Student extends Person{
        private String school;
    
        public String getSchool() {
            return school;
        }
    
        public void setSchool(String school) {
            this.school = school;
        }
    
        @Override
        public String toString() {
            return "Student{" + "name='" + getName() + '\'' +
                    " age='" + getAge()+'\''+
                    " school='" + school + '\'' +
                    '}';
        }
    }
    
    
    
    /**
     * 说明:测试类
     *
     * @author huayu
     * @date 2018/8/5 1:06 PM
     */
    public class TestStudent {
        public static void main(String[] args) {
            Student student=new Student();
            Person person=new Person();
            person.setName("john");
            person.setAge(19);
            student.setName("yuhua");
            student.setAge(18);
            student.setSchool("BJTU");
            System.out.println(person.toString());
            System.out.println(student.toString());
        }
    }
    
    测试类输出结果:
    Person{name='john', age=19}
    Student{name='yuhua' age='18' school='BJTU'}
    
    
    重写与重载的区别:
    方法的重写和重载都是实现多态的方式。区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求。
    
    

    15.super关键字

    在java类中使用super来引用基类的成分;

    /**
     * 说明:super关键字引用父类成员演示,基类
     *
     * @author huayu
     * @date 2018/8/5 2:57 PM
     */
    public class Foo {
        public int value;
        public void f(){
            value=100;
            System.out.println("Foo.value="+value);
        }
    }
    
    /**
     * 说明:super关键字引用父类成员演示,子类
     *
     * @author huayu
     * @date 2018/8/5 2:58 PM
     */
    public class Coo extends Foo{
        public int value;
        public void fcoo(){
            //引用父类的f(0)方法
            super.f();
            value=200;
            System.out.println("Coo.value="+value);
            System.out.println(value);
            System.out.println(super.value);
        }
    }
    
    import oop.Coo;
    
    /**
     * 说明:测试方法继承
     *
     * @author huayu
     * @date 2018/8/5 3:05 PM
     */
    public class TestInherit {
        public static void main(String[] args) {
            Coo coo = new Coo();
            coo.fcoo();
        }
    }
    
    
    测试结果:
    Foo.value=100
    Coo.value=200
    200
    100
    

    内存分析图:

    把这个子类继承父类程序并子类调用父类成员的内存分配过程,这儿常出面试题:子类是怎么对父类的成员进行调用的。因为以前教过内存分析的具体过程,这儿我就只给了个最后的内存分布图,大家自己好好分析一遍。(当然,方法调用完,栈内为其分配的空间应被收回)。

    16.继承中的构造方法

    1)子类的构造的过程中必须调用其基类的构造方法(也就是在子类的构造方法中应首先调用父类的构造方法)。

    2)子类可以在自己的构造方法中使用super(argument_list参数列表)调用基类的构造方法。(1.使用this(argument_list)调用本类的另外的构造方法  2.如果调用了super,必须写在子类构造方法的第一行“先父后子”)。

    3)如果子类的构造方法中没有显示调用基类构造方法,则系统默认调用基类无参数的构造方法。

    4)如果子类构造方法中既没有显示调用基类构造方法,而基类中又没有无参构造方法,则编译出错。

    /**
     * 说明:继承中的构造方法测试用例,基类
     *
     * @author huayu
     * @date 2018/8/5 3:42 PM
     */
    public class SuperClass {
        private int n;
        //验证第一条的时候,SuperClass()构造方法注释掉
        //验证第四条的时候,SuperClass()构造方法注释掉
        public SuperClass() {
            System.out.println("SuperClass()");
        }
    
        public SuperClass(int n) {
            System.out.println("SuperClass("+n+")");
            this.n = n;
        }
    }
    
    /**
     * 说明:继承中的构造方法测试用例,子类
     *
     * @author huayu
     * @date 2018/8/5 3:44 PM
     */
    public class SubClass extends SuperClass{
        private int n;
    
        public SubClass(int n) {
            //验证第三条的时候,相当于加了一个在这super();语句。
            System.out.println("SubClass("+n+")");
            this.n = n;
        }
    
        public SubClass() {
            //验证第一条的时候,super(300);这条注释掉
            //验证第二条的时候,将super(300);与 System.out.println("SubClass)");调换个位置
            super(300);
            System.out.println("SubClass)");
        }
    }
    
    
    import oop.SubClass;
    
    /**
     * 说明:继承中的构造方法测试用例,测试类
     *
     * @author huayu
     * @date 2018/8/5 3:48 PM
     */
    public class TestSuperSub {
        public static void main(String[] args) {
            //验证三、四条的时候注释掉 subClass这句
            SubClass subClass=new SubClass();
            //验证一、二条的时候注释掉 subClass1这句
            SubClass subClass1=new SubClass(400);
        }
    }
    验证结果:
    1.验证第一条:如果在编译期,它会报找不到SuperClass的错误(如果你用的是ide编辑的,其实在你注释掉代码的时候,代码就报错了)。将注释打开后输出结果:
    SuperClass(300)
    SubClass()
    2.验证第二条:如果在编译期,它会报对super的调用必须是构造函数的第一个语句(如果你用的是ide编辑的,其实在你注释掉代码的时候,代码就报错了)。
    3.验证第三条:打印结果
    SuperClass()
    SubClass(400)
    4.验证第四条:如果在编译期,它会报找不到SuperClass的错误(如果你用的是ide编辑的,其实在你注释掉代码的时候,代码就报错了)。
    

    17.Object类

    1)Object类是所有Java类的根基类(源码在jdk  rt.jar java的lang包里面,没事了可以看一看)

    2)如果在类的声明中未使用extends关键字指明其基类,则默认基类为Object类

    public class Person {
     //代码...
    }
    等价于:
    public class Person extends Object{
     //代码...
    }
    

    3)Object类里常用的方法(学会看api文档,能看懂英文版更好)

    api在线文档地址https://blog.fondme.cn/apidoc/jdk-1.8-baidu/

    ~1.toString方法

    Object类中定义有public String toString()方法,其返回值是String类型,描述当前对象的有关信息。

    在进行String与其它类型数据的连接操作时(如:System.out.println("info"+person)),将自动调用该对象类的toString()方法。

    可以根据需要在用户自定义类型中重写toString()方法。

    ~2.equals方法

    1)public boolean equals(Object obj) { return (this == obj); }提供定义对象是否“相等”的逻辑。

    2)Object的equals方法定义为:x.equals(y)当x和y是同一个对象的应用时返回true否则返回false

    3)J2SDK提供的一些类,如String,Date等,重写了Object的equals方法,调用这些类的equals方法,x.equals(y),当x和y所引用的对象是同一类对象且属性内容相等时(并不一定是相同对象),返回true否则返回false。

    4)可以根据需要在用户自定义类型中重写equals方法。

    知识链接:"=="和 equals 方法究竟有什么区别

    ==:运算符,适合于基本数据类型和引用数据类型。如果是基本数据类型,比较两个变量的值是否相等。 如果是引用数据类型变量,判断两个变量是否指向内存中的同一个对象(引用,内容都一样)。
    equals():是 Object 类中定义过的一个方法。只适用于对象来调用。如果各个对象所在的类没有重写 Object 中的 equals(),则与==使用相同。如果所在的类重写了 equals(),一般重写的规则是判断两个对象中包含的所有属性的值是否相等。

    /**
     * 说明:未重写equals方法时候
     * 如果各个对象所在的类没有重写 Object 中的 equals(),则与==使用相同。判断的是引用跟值都得相同
     * @author huayu
     * @date 2018/8/5 7:39 PM
     */
    public class Dog {
        int color;
        int height,weight;
    
        public Dog(int color, int height, int weight) {
            this.color = color;
            this.height = height;
            this.weight = weight;
        }
    }
    
    /**
     * 说明:equals方法的测试类
     *
     * @author huayu
     * @date 2018/8/5 7:41 PM
     */
    public class TestEquals {
        public static void main(String[] args) {
            Dog dog=new Dog(1,2,3);
            Dog dog1=new Dog(1,2,3);
            System.out.println(dog==dog1);
            System.out.println(dog.equals(dog1));
        }
    }
    
    结果:
    false
    false
    /**
     * 说明:重写equals方法时候
     * 如果所在的类重写了 equals(),一般重写的规则是判断两个对象中包含的所有属性的值是否相等。
     * @author huayu
     * @date 2018/8/5 7:39 PM
     */
    public class Dog {
        int color;
        int height, weight;
    
        public Dog(int color, int height, int weight) {
            this.color = color;
            this.height = height;
            this.weight = weight;
        }
    
        @Override
        public boolean equals(Object o) {
            if (o == null || getClass() != o.getClass()) {
                return false;
            } else {
                if (o instanceof Dog) {
                    Dog dog = (Dog) o;
                    if (dog.color == this.color && dog.height == this.height && dog.weight == this.weight) {
                        return true;
                    }
                }
            }
    
            return false;
        }
    }
    
    
    /**
     * 说明:equals方法的测试类
     *
     * @author huayu
     * @date 2018/8/5 7:41 PM
     */
    public class TestEquals {
        public static void main(String[] args) {
            Dog dog=new Dog(1,2,3);
            Dog dog1=new Dog(1,2,3);
            System.out.println(dog==dog1);
            System.out.println(dog.equals(dog1));
    
            //下面验证第三条String类是否真的重写了equals方法
            String string1=new String("hello");
            String string2=new String("hello");
            System.out.println("String判==结果:  "+(string1==string2));
            System.out.println("String判equals结果  "+(string1.equals(string2)));
        }
    }
    
    结果:
    false
    true
    String判==结果:  false
    String判equals结果:  true
    

    18.对象转型(casting):可以增强程序的可扩展性,比定义好多个方法要好一些。

    1)一个基类的引用类型变量可以“指向”其子类的对象。

    2)一个基类的引用不可以访问其子类对象新增的成员(属性和方法)。

    3)可以使用 引用 变量instanceof类名 来判断该引用型变量所“指向”的对象是否属于该类或该类的子类。

    4)子类的对象可以当作基类的对象来使用称作向上转型(upcasting),反之称为向下转型(downcasting)。

    (1)释例一:演示对象转型

    /**
     * 说明:
     *
     * @author huayu
     * @date 2018/8/6 1:00 PM
     */
    public class Animal {
        public String name;
    
        public Animal(String name) {
            this.name = name;
        }
    }
    
    
    /**
     * 说明:用于演示对象转型,pig类
     *
     * @author huayu
     * @date 2018/8/6 1:01 PM
     */
    public class Pig extends Animal{
        public String eyesColor;
    
        public Pig(String name,String eyeColor) {
            super(name);
            this.eyesColor = eyeColor;
        }
    }
    package oop;
    
    /**
     * 说明:用于演示对象转型,tiger类
     *
     * @author huayu
     * @date 2018/8/6 1:03 PM
     */
    public class Tiger extends Animal{
        public String furColor;
    
        public Tiger(String name ,String furColor) {
            super(name);
            this.furColor = furColor;
        }
    }
    
    import oop.Animal;
    import oop.Pig;
    import oop.Tiger;
    
    /**
     * 说明:用于演示对象转型,测试类
     *
     * @author huayu
     * @date 2018/8/6 1:08 PM
     */
    public class TestCasting {
        public static void main(String[] args) {
            Animal animal=new Animal("");
            Pig pig=new Pig("xiaozhu","black");
            Tiger tiger=new Tiger("xiaohu","yellow");
            System.out.println(animal instanceof Animal);
            /*pig instanceof Animal 这句话用到的instanceof关键字,表达的意思是pig是不是 
            Animal的一个实例
            */
            System.out.println(pig instanceof Animal);
            System.out.println(tiger instanceof Animal);
            System.out.println(animal instanceof Pig);
            //向下造型,父类引用指向子类对象,自动转
            animal=new Tiger("tigername","white");
            System.out.println(animal.name);
            //父类拿不到访问子类自己成员的权限,故无法访问子类特有的成员furColor,这儿会报错
    //1.    System.out.println(animal.furColor); //!error
            System.out.println(animal instanceof Animal);
            System.out.println(animal instanceof Tiger);
            //向上造型,子类引用指向父类对象,需强转
    2.      Tiger tiger1=(Tiger) animal;
            //通过上面句2强转后,就可以访问它的特有成员furColor了
            System.out.println(tiger1.furColor);
    
        }
    }
    测试类输出结果:
    true
    true
    true
    false
    tigername
    true
    true
    white
    
    

    为了能让大家更好的理解 1.System.out.println(animal.furColor); //!error  这一句,我对animal=new Tiger("tigername","white");这一句做了一个内存分析图,希望可以有助于大家的理解:

    执行句2Tiger tiger1=(Tiger) animal;后的内存分布图:

    (2)释例二:用于演示对象转型对程序可扩展性的有利影响

    import oop.Animal;
    import oop.Pig;
    import oop.Tiger;
    
    /**
     * 说明:用于演示对象转型扩展性,测试类
     * 以上Animal,Pig,Tiger的类依然沿用释例一部分的
     * @author huayu
     * @date 2018/8/6 1:08 PM
     */
    public class TestCasting {
        public static void main(String[] args) {
            TestCasting testCasting=new TestCasting();
            Animal animal=new Animal("name");
            Pig pig=new Pig("xiaozhu","black");
            Tiger tiger=new Tiger("laohu","yellow");
            testCasting.f(animal);
            testCasting.f(pig);
            testCasting.f(tiger);
            /*有了通过对象造型对程序的扩展性提供了很大的帮助,比如这个程序内除了上面两种...
              其它的也照样可以测,比如再加什么苍蝇蚊子等等,只需要写方法调用方法就可以了。
            */
        }
        public void f(Animal animal){
            System.out.println("name: "+animal.name);
            if(animal instanceof Pig){
                Pig pig=(Pig) animal;
                System.out.println(" "+pig.eyesColor);
            }else if(animal instanceof Tiger){
                Tiger tiger= (Tiger) animal;
                System.out.println(" "+tiger.furColor+" fur");
            }
        }
    }

    19.多态polymorphism(动态绑定dynamoc binding,池绑定late binding):动态绑定是指“在执行期间(而非编译期间)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。”, 

    多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样 的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当 A 系 统访问 B 系统提供的服务时,B 系统有多种提供服务的方式,但一切对 A 系统来说都是透明的 (就像电动剃须刀是A系统,它的供电系统是B系统,B系统可以使用电池供电或者用交流电, 甚至还有可能是太阳能,A 系统只会通过 B 类对象调用供电的方法,但并不知道供电系统的底 层实现是什么,究竟通过何种方式获得了动力)。

    方法重载(overload)实现的是编译时的多态 性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。

    运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:1). 方法重写(子类继承父类 并重写父类中已有的或抽象的方法);2). 对象造型(用父类型引用引用子类型对象,这样同样 的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。

    多态(动态绑定,池绑定)使扩展性达到最好。

    释例

    package oop;
    
    /**
     * 说明:用于演示多态,动物类
     *
     * @author huayu
     * @date 2018/8/6 1:00 PM
     */
    public class Animal {
        public String name;
    
        public Animal(String name) {
            this.name = name;
        }
        public void enjoy(){
            System.out.println("叫声...");
        }
    }
     
    package oop;
    
    /**
     * 说明:用于演示多态,pig类
     *
     * @author huayu
     * @date 2018/8/6 1:01 PM
     */
    public class Pig extends Animal{
        public String eyesColor;
    
        public Pig(String name,String eyeColor) {
            super(name);
            this.eyesColor = eyeColor;
        }
    
        @Override
        public void enjoy(){
            System.out.println("猪叫声...");
        }
    }
    
    package oop;
    
    /**
     * 说明:用于演示多态,tiger类
     *
     * @author huayu
     * @date 2018/8/6 1:03 PM
     */
    public class Tiger extends Animal{
        public String furColor;
    
        public Tiger(String name ,String furColor) {
            super(name);
            this.furColor = furColor;
        }
        @Override
        public void enjoy(){
            System.out.println("老虎叫声...");
        }
    }
    
    package oop;
    
    /**
     * 说明:用于演示多态,GF类
     *
     * @author huayu
     * @date 2018/8/6 3:11 PM
     */
    public class GF {
        private String name;
        //定义成父类引用是为了更灵活
        private Animal pet;
    
        public GF(String name, Animal pet) {
            this.name = name;
            this.pet = pet;
        }
        public void myPetEnjoy(){
            pet.enjoy();
        }
    }
    
    import oop.GF;
    import oop.Pig;
    import oop.Tiger;
    
    /**
     * 说明:用于演示多态,测试类
     *
     * @author huayu
     * @date 2018/8/6 3:14 PM
     */
    public class TestPolymoph {
        public static void main(String[] args) {
            Pig pig=new Pig("xiaozhu","black");
            Tiger tiger=new Tiger("laohu","yellow");
            GF gf=new GF("xiaohong",pig);
            GF gf1=new GF("xiaolv",tiger);
            gf.myPetEnjoy();
            gf1.myPetEnjoy();
        }
    }
    
    结果:
    猪叫声...
    老虎叫声...

    内存分析(以new Pig为例):

    多态的存在三个必要条件:

    1)要有继承;

    2)要有重写;

    3)父类引用指向子类对象。new的是哪个对象则就会动态绑定它里面重写的方法。

    20.抽象类

    1)用abstract关键字来修饰一个类时,这个类叫做抽象类;用abstract来修饰一个方法时,该方法叫做抽象方法。

    2)含有抽象方法的类必须被声明为抽象类,抽象类必须被继承,抽象方法必须被重写(继承他的子类去重写)。

    3)抽象类不能被实例化(new不出来)。

    4)抽象方法只需声明,而不需实现。明知道父类的一个方法肯定要被子类实现,所以它没有必要实现它的方法,只声明就可以。

    5)抽象类中可以含有非抽象的方法,但是类中必有抽象的方法在里面。

    释例:

    package oop;
    
    /**
     * 说明:用于演示抽象类,动物类
     * 抽象类:残缺不全的类,被继承后,子类需要重写它所有的抽象方法
     * @author huayu
     * @date 2018/8/6 1:00 PM
     */
    public abstract class Animal {
        public String name;
    
        public Animal(String name) {
            this.name = name;
        }
        //以下enjoy方法,若子类继承这个类,这个方法将会被重写,所以它没必要实现它的方法
        /*public void enjoy(){
            System.out.println("叫声...");
        }*/
        //注释掉上面的方法把它改进为public abstract void enjoy();相当于C++的虚函数
        //注意public void enjoy(){};这叫空的实现,但这个要被重写,也每必要写它。
        //所以有了以下的这种抽象方法,只有定义,没有任何实现。而这个方法加了abstract这个类也需 
        //要被声明为抽象类。在类名前加abstract关键字。
        public abstract void enjoy();
    }
     
    package oop;
    
    /**
     * 说明:用于演示抽象类,pig类
     *
     * @author huayu
     * @date 2018/8/6 1:01 PM
     */
    public class Pig extends Animal{
        public String eyesColor;
    
        public Pig(String name,String eyeColor) {
            super(name);
            this.eyesColor = eyeColor;
        }
    
        @Override
        public void enjoy(){
            System.out.println("猪叫声...");
        }
    }
    
    package oop;
    
    /**
     * 说明:用于演示抽象类,tiger类
     *
     * @author huayu
     * @date 2018/8/6 1:03 PM
     */
    public class Tiger extends Animal{
        public String furColor;
    
        public Tiger(String name ,String furColor) {
            super(name);
            this.furColor = furColor;
        }
        @Override
        public void enjoy(){
            System.out.println("老虎叫声...");
        }
    }
    
    package oop;
    
    /**
     * 说明:用于演示抽象类,GF类
     *
     * @author huayu
     * @date 2018/8/6 3:11 PM
     */
    public class GF {
        private String name;
        //定义成父类引用是为了更灵活
        private Animal pet;
    
        public GF(String name, Animal pet) {
            this.name = name;
            this.pet = pet;
        }
        public void myPetEnjoy(){
            pet.enjoy();
        }
    }
    
    import oop.GF;
    import oop.Pig;
    import oop.Tiger;
    
    /**
     * 说明:用于演示抽象类,测试类
     *
     * @author huayu
     * @date 2018/8/6 3:14 PM
     */
    public class TestPolymoph {
        public static void main(String[] args) {
            Pig pig=new Pig("xiaozhu","black");
            Tiger tiger=new Tiger("laohu","yellow");
            GF gf=new GF("xiaohong",pig);
            GF gf1=new GF("xiaolv",tiger);
            gf.myPetEnjoy();
            gf1.myPetEnjoy();
        }
    }
    
    结果:
    猪叫声...
    老虎叫声...

    知识拓展:

    1)抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。 抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

    2)抽象类(abstract class)和接口(interface)有什么异同?

    3)抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用。一个类如果继承了 某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被 声明为抽象类。接口比抽象类更加抽象,因为抽象类中可以定义构造器,可以有抽象方法和具 体方法,而接口中不能定义构造器而且其中的方法全部都是抽象方法。抽象类中的成员可以是 private、默认、protected、public 的,而接口中的成员全都是 public 的。抽象类中可以定义成员 变量,而接口中定义的成员变量实际上都是常量。有抽象方法的类必须被声明为抽象类,而抽 象类未必要有抽象方法。

    4)抽象的(abstract)方法不能同时分别被static,native,synchronized修饰?

    抽象的(abstract)方法不能同时是静态的(static),因为抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。

    抽象的(abstract)方法不能同时是本地方法(native),因为本地方法是由本地代码(如 C 代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。  

    抽象的(abstract)方法不能同时被 synchronized 修饰, 因为synchronized 和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的

    21.final关键字

    final:最终的 可以用来修饰类、变量、方法
     

    1)final的变量的值不能够被改变(final的成员变量,final的局部变量(形参))

         final 修饰变量:此变量就"退化"为一个常量。比如:Math 类的 PI。

         可以如下三个位置对 final 的变量初始化:显式的初始化/代码块中初始化/构造器中初始化

    /**
     * 说明:测试final的值不能被改变
     *
     * @author huayu
     * @date 2018/8/6 8:15 PM
     */
    public class FinalDemo {
        final  int i=1;
    }
    
    import oop.FinalDemo;
    
    /**
     * 说明:测试final的值不能被改变
     *
     * @author huayu
     * @date 2018/8/6 8:14 PM
     */
    public class TestFinal {
        public static void main(String[] args) {
            FinalDemo finalDemo=new FinalDemo();
            //试图修改final变量i,如果进了编译期,编译期报这个值不能被改变,若用ide多数代码还           
            //没敲完就会报错了
            finalDemo.i=1;
        }
    }
    

    2)final 修饰方法:表明此方法不可以被重写.比如:Object 类的 getClass();

    package oop;
    
    /**
     * 说明:测试方法不能被重写
     *
     * @author huayu
     * @date 2018/8/6 8:15 PM
     */
    public class FinalDemo {
        public  int i=1;
        public final void m(){
    
        }
    }
    
    /**
     * 说明:测试方法不能被重写
     *
     * @author huayu
     * @date 2018/8/6 8:24 PM
     */
    public class TT extends FinalDemo{
       //如果进入了编译器,编译器会报无法重写m方法的错误,若使用ide多数一般代码刚写完就已经报错了
       public void m(){
           
       }
    }

    3)final 修饰类:表明此类不可以被继承.比如:String 类、StringBuffer 类

    /**
     * 说明:测试类不能被重写
     *
     * @author huayu
     * @date 2018/8/6 8:15 PM
     */
    public final class FinalDemo {
        public  int i=1;
        public  void m(){
    
        }
    }
    
    /**
     * 说明:测试类不能被重写
     *
     * @author huayu
     * @date 2018/8/6 8:24 PM
     */
    //如果进入了编译期,编译器会报无法继承FinalDemo类的错误,若使用ide多数一般代码刚写完就已经
    //报错了
    public class TT extends FinalDemo{
    
    }

    知识拓展:

    1)内部类访问外部属性为什么加 final?

    局部内部类能访问方法中的所有的局部变量,其生命周期与局部内部类的对象的生命周期是不一致的。如何才能实 现访问呢?当变量是 final 时,通过将 final 局部变量"复制"一份,复制品直接作为局部内部中的数据成员。这样,当局 部内部类访问局部变量时,其实真正访问的是这个局部变量的"复制品”。那么使用 final 修饰,表示其复制品与原始的量是一样。

    2)final, finally,finalize()的区别

    -final:修饰符(关键字)有三种用法:如果一个类被声明为 final,意味着它不能再派生出新的 子类,即不能被继承,因此它和 abstract 是反义词。将变量声明为 final,可以保证它们在使用中 不被改变,被声明为 final 的变量必须在声明时给定初值,而在以后的引用中只能读取不可修改。 被声明为 final 的方法也同样只能使用,不能在子类中被重写。

    - finally:通常放在 try...catch...的后面构造总是执行代码块,这就意味着程序无论正常执行还是 发生异常,这里的代码只要 JVM 不关闭都能执行,可以将释放外部资源的代码写在 finally 块中。

    - finalize:Object 类中定义的方法,Java 中允许使用 finalize()方法在垃圾收集器将对象从内存中 清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize()方法可以整理系统资源或者执行其他清理工作。

    22.接口(interface):是抽象方法和常量值的定义的集合。从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。

    接口的特性:

    1)接口可以多重实现。

    2)接口中声明的属性默认为public static final的,也只能是public static final的

    3)接口中只能定义抽象方法,而且这些方法默认为public的,也只能是public的

    4)接口可以继承其它接口,并添加新的属性和抽象方法。

    5)多个无关的类可以实现同一个接口,接口中抽象方法必须全被重写。

    6)一个类可以实现多个无关的接口,接口与接口之间用“,"隔开,接口中抽象方法必须全被重写。

    7)与继承关系类似,接口与实现类之间存在着多态性。

    8)定义java类的语法格式:

    <modifier> class <name> [extends <superclass> ]

    [implements <interface> [,<interface>*] {

    <declarartions>*

    }

    释例一

    /**
     * 在这段代码中我们模拟写一个跳远的运动员的接口
     */
    public interface InterfaceDemo {
        /*为了修正C++多继承多个父类之间相同成员变量引用特麻烦跟运行易出错的问题,
          java在接口中将成员变量定义为static final的
         */
        public static final int count = 1;
        /*
        其实接口中成员变量也可以不写static final因为它默认就是static final的
         */
        int id = 1;
    
        //接口中的方法不用写abstract它也全都是abstract的
         public void start();
        //接口中的方法也可以不加public,因为它默认就是public的
         void jump();
    
         void stop();
    }

    释例二:

    package oop;
    
    /**
     * 在这段代码中我们模拟写一个运动员的接口
     */
    public interface InterfaceDemo {
        /*为了修正C++多继承多个父类之间相同成员变量引用特麻烦跟运行易出错的问题,
          java在接口中将成员变量定义为static final的
         */
        public static final int count = 1;
        /*
        其实接口中成员变量也可以不写static final因为它默认就是static final的
         */
        int id = 1;
    
        //接口中的方法不用写abstract它也全都是abstract的
         public void start();
        //接口中的方法也可以不加public,因为它默认就是public的
         void jump();
    
         void stop();
    }
    
    package oop;
    
    /**
     * 说明:定义了一个跳远运动员的类,实现运动员接口
     *
     * @author huayu
     * @date 2018/8/7 1:31 PM
     */
    public class Jumper implements InterfaceDemo {
        private String name;
    
        public Jumper(String name) {
            this.name = name;
        }
    
        public void start() {
            System.out.println("起跳的动作准备");
        }
    
        public void jump() {
            System.out.println("起跳过程中的身形变化控制");
        }
    
        public void stop() {
            System.out.println("快结束时入坑姿势调整");
        }
    }
    

    知识拓展:

    接口是否可继承(extends)接口?抽象类是否可实现(implements) 接口?抽象类是否可继承具体类(concrete class)?

    接口可以继承接口,而且支持多重继承。抽象类可以实现(implements)接口,抽象类可继承 具体类也可以继承抽象类。

     

     

     

     

    展开全文
  • 计算机从业者在工作学习中会遇见一个非常常见的问题,那就是学习的东西太多太多了 ,又特别容易忘记,这该怎么办呢?几年的学习经验的博主小小的规划总结了一下,并且把这些好的方法呈现出来给大家,希望能帮大家...


    在这里插入图片描述

    写在前面

    计算机从业者在工作学习中会遇见一个非常常见的问题,那就是学习的东西太多太多了 ,又特别容易忘记,这该怎么办呢?几年的学习经验的博主小小的规划总结了一下,并且把这些好的方法呈现出来给大家,希望能帮大家解决这个疑难问题

    这张图是艾宾浩斯遗忘曲线,我们可以清晰的看到,当我们学习一个东西的时候,短期内它就会被急速遗忘,然后时间久了感觉记住的已经不多了。有时候我们感觉学习了一个新事物后,过了 10 天或者 20 天都忘记了一些,似乎忘记的分量好像没什么差别,但是有个特点就是,如果你去学了那么它的 y 轴总会有一个值,如果你不学,y 轴永远是 0,并且如果我们反复的学,这个 y 轴可以持续维持较高的水准。

    我这里总结了如下的方法来使我们尽可能少的遗忘

    • 学会总结
      • 博文总结
      • github 模板
    • 回顾应用
      • 返回回顾
      • 尝试应用

    学会总结

    博文总结

    以文字的方式来做总结

    我们知道学完一个东西,我们不去做总结梳理就会像知识没有网络,像一盘散沙一样,一盘散沙的知识点最容易忘记,因为他们之间没有关联,无法通过强大的联想回忆来避免遗忘

    所以我建议使用博客总结的方式,当我们学到一个阶段时候,对某个知识点做个总结,可以用各种总结模板,方便我们以后回忆查看

    • csdn
    • cnblog
    • 有道云
    • 印象笔记

    github 模板

    以代码的方式来做总结

    当我们学习了一些知识点,我建议可以通过实际应用的方式来做一些小的项目,这些小的项目实际上就是在应用和回顾,并且把这些项目我们可以放到一些地方,方便我们以后回忆查看

    • github
    • gitlab
    • gitee
    • bitbucket
    • gitcafe
    • 自己的硬盘或 U 盘

    回顾应用

    反复回顾

    以文字的方式来做回顾

    当我们学习了很多知识之后,我们需要时常回顾,只有不断去回顾,才能记忆的更深,其实这跟做项目很像,当我们做一个项目,假如做了一个月,实际上就是在这个月内不断的在脑中回顾这个项目的知识点,这也就是为什么对于做过项目的知识点能很好的掌握,而且当我们回顾的次数越来越多,这个知识点我们就越来越难忘记了!

    有哪些策略却回顾呢,我提供了几种方法

    • 时不时的回顾,偶然性的回顾
    • 联想的回顾,当我们学到类似的东西,或者引发了之前学的东西的回忆,这个时候就可以快速的把之前学的东西在脑中想一遍,可以是看博客的方式
    • 有计划的回顾,比如每天抽出半小时看之前的哪个知识点

    这几种回顾方式都很好 ,因为我比较懒,所以我只是用第一种和第二种

    尝试应用

    以代码的方式来做回顾

    其实还有一种回顾方式,或者准确来讲不叫回顾,应该叫去应用,当我们去应用这个知识点本质就是在不断回忆这个知识点,所以它也可以算回顾的一种

    当我们学会了一些知识点,我们需要在以后的项目中大胆尝试去应用它,这个也很重要

    写在后面的话

    其实这些方法如果都做到且做的比较好,我们想遗忘都很难!

    其实还有一点就是,当我们学了非常多的东西之后,虽然以后学的东西也会遗忘,但是因为随着我们掌握了不那么快遗忘的方法,和学习的东西很多内容是相通的,也就是遗忘性没有以前那么高了,因为可以通过联想来回忆,并且因为学的东西多了,我们也会学的更快了,所以实际上有个特点就是,随着我们后来学的东西越来越多,我们会发现我们的遗忘性越来越低,并且还会学的越来越快!

    为什么你总是能看到有的人能在一个比较复杂的知识点上非常的了解,有两个可能:

    1. 人家的经验很多,历经了项目到“折磨”,相当于将此篇博文中的“学会总结”和“回顾应用”都做过了很多遍了,自然他懂的很深入,而且也一定很广
    2. 人家是一名新人,经验不多,但是他目前正好做到了这个项目,用到了这个功能点,依据遗忘曲线,极短时间内记忆很难消失

    我们应该要从这两者身上学到东西:

    1. practise makes perfect!
    2. 大胆去应用于项目,写项目兼备了“回顾”,“总结”的两个好处,加深印象

    最后有一点不得不提到,学习的过程拒绝完美主义,因为有完美主义的人往往不喜欢琐碎的复习,他们喜欢完整的复习,但是完整的复习必然会花费大量的时间,于是之后复习这个任务就不了了之,所以我推荐大家琐碎的复习回顾!

    展开全文
  • 它伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。自诞生至今,还产生了无数和Java相关的产品、技术和标准。下面简要回顾一下Java的技术体系和发展轨迹、历史变迁 一、为什么 Java 要叫 Java(咖啡)?...
  • 学习编程中那些很容易犯的错误前言常犯的错误纠正方法结语 前言 回顾一下,距离去年三月份开始学习编程到现在马上快有一年的时间了,在这个期间中走了很多弯路,犯过很多错误,在这里我将结合自己学习的这段过程总结...
  • 更多精彩内容,请微信搜索“FPGAer俱乐部”关注我们我知道,我对与电子有关的所有事情都很着迷,但不论从哪个角度看,今天的现场可编程门阵列(FPGA),都显得“鹤立鸡群”,真是非常棒的器件。如果在这个智能时代,在...
  • 论学习编程

    2021-06-14 20:06:52
    本人是本科的一名非计算机专业的大四的学生,大学四年基本在玩,对本专业的知识不感兴趣,倒是国二考了个C语言程序设计,但也快的差不多了,对编程是有兴趣的,在备考C语言考试的时候倒也积累了不少的 ...
  • Python黑帽编程2.8 套接字编程

    千次阅读 2016-08-16 18:05:02
    接字编程在本系列教程中地位并不是很突出,但是我们观察网络应用,绝大多数都是基于Socket来做的,哪怕是绝大多数的木马程序也是如此。官方关于socket编程的文档地址为...
  • C# DX 编程

    千次阅读 2010-06-11 22:54:00
    要:C#进行游戏编程一直受到一些C++程序员的怀疑和...作者对.NET、C#、DirectX及游戏制作的相关知识都作了介绍和讲解,然后,一步步的制作“文字对战游戏”,相信读完本文,你一定会受益非浅。 关键词:C#
  • 编程技术面试的五大要点

    万次阅读 多人点赞 2011-11-16 15:19:40
    (写在前面的话:本文最初发表于《程序员》杂志2011年10月刊,并收录到《剑指Offer——名企面试官精讲典型编程题》一书中。) 近年来找工作一直是一个很热门的话题。我们要想找到心仪的工作,难免需要经过很多轮...
  • linux操作系统下c语言编程入门

    千次阅读 2012-09-13 21:29:48
    linux操作系统下c语言编程入门  整理编写:007xiong  原文:Hoyt等  (一)目录介绍  1)Linux程序设计入门--基础知识  2)Linux程序设计入门--进程介绍  3)Linux程序设计入门--文件操作  4)Linux程序...
  • 并发编程并不是一门相对独立的学科,而是一个综合学科。并发编程相关的概念和技术看上非常零散,相关度也很低,总给你一种这样的感觉:我已经学习很多相关技术了,可还是搞不定并发编程。那如何才能学习好并发编程呢...
  • 带妹入坑,她该怎样提高自己的编程能力?

    千次阅读 多人点赞 2020-12-10 10:24:20
    不是有那句俗话嘛,“当局者迷旁观者清”,如果你站在读的角度,就会很容易自欺欺人;但如果自己亲自实操的话,就完全不一样了,不仅印象深刻,还为以后的复盘做好了备份。在敲的过程中,最好把自己认为经典的案例...
  • 作者 |杨成立(篱) 阿里巴巴高级技术专家 导读:从问题本身出发,不局限于 Go 语言,探讨服务器中常常遇到的问题,最后回到 Go 如何解决这些问题,为大家提供 Go 开发的关键技术指南。我们将以系列文章的形式...
  • 编程新手导论

    万次阅读 2012-06-07 20:00:31
    第二部分 导论,这一部分主要是关于编程的导论, (要懂得一点思想具备一点常识)《设计,编码,,与软工》(编程与思想)这一章解释了三种思想,原语,抽象,组合,,和软件开发的二个重要过程,,软件工程的相关...
  • Linux编程之进程和线程编程

    千次阅读 2008-01-24 10:57:00
    进程和线程编程 目 录1. 进程和线程编程 1. 原始管道 1. pipe() 2. dup() 3. dup2() 4. popen()和pclo
  • 编程中,有哪些好的习惯一开始就值得坚持?

    千次阅读 多人点赞 2020-04-28 07:29:17
    今天这个话题我觉得还是值得和大家探讨的,因为好的编程习惯对程序员的职业生涯真的非常重要。 记得我在学驾照的时候,遇到一哥们,之前开过车,属于无证驾驶的那种。但是,这哥们科目二竟然挂了四次,第五次有没有...
  • 编程高手箴言

    千次阅读 2011-02-15 09:43:00
    编程高手箴言 书名: 编程高手箴言 作者: 梁肇新 来源: 电子工业出版社 ISBN: 7-5053-9141-0 页数: 416 开本: 16开 出版时间: 2003年11月 定价: 50元 内容简介: 本书是作者十余年编程生涯中的技术和经验的...
  • 编程路上,对于迷失者的一些小小建议

    万次阅读 多人点赞 2017-07-30 19:49:10
    前几天,在半梦半醒中写了一篇《编程路上,送给处于迷茫中的你和自己》,没想到还挺受欢迎,同时收到了一些朋友的留言和感谢,意外之余也挺开心。大多人都会经历的迷茫其实这也都难免的,现在计算机技术更新那么快,...
  • 编程高手箴言

    千次阅读 2012-01-30 14:43:08
    本书是作者十余年编程生涯中的技术和经验的总结。内容涵盖了从认识CPU、Windows运行机理、 编程语言的运行机理,到代码的规范和风格、分析方法、调试方法和内核优化,内有作者对许多问题 的认知过程和透彻的分析...
  • 什么才算是真正的编程能力?

    千次阅读 2015-06-08 22:53:59
    问题:什么才算是真正的编程能力? 还在读书,也在实验室帮忙做了些东西,自己也搭过几个网站。在周围人看来似乎好像我很厉害,做了那么多东西,但是我发现这些东西虽然是我做的,但是实际上我手把手自己写的...
  • Qt on Android 核心编程

    千次阅读 2014-11-21 15:10:01
    Qt on Android 核心编程(最好看的Qt编程书!CSDN博主foruok倾力奉献!) 安晓辉 著  ISBN 978-7-121-24457-5 2015年1月出版 定价:65.00元 444页 16开 编辑推荐 当Qt跨界牵手Android,移动开发会有什么...
  • [转]给SSD(固态硬盘)编程

    万次阅读 2016-05-27 21:15:06
    程序员如何更好的使用SSD硬盘以及在上面编程开发的系统知识
  • 一、什么是防御性编程 详细请见:http://www.uml.org.cn/codeNorms/201007165.asp 防御性编程是一种细致、谨慎的编程方法。为了开发可靠的软件,我们要设计系统中的每个组件,以使其尽可能地“保护”自己。我们...
  • 来自Unix/Linux的编程启示录

    千次阅读 多人点赞 2017-02-08 04:46:00
    现在我们来看看Unix/Linux中那些隐藏的编程哲学,需要说明的是Unix/Linux中的编程哲学非常通俗易懂,他们大多是你已知的,更多的时候是我们不曾注意到. 无论你现在负责的系统多么复杂,这总有可以帮助你的地方.(要说...
  • windows黑客编程

    千次阅读 2005-07-24 17:29:00
    要想在安全知识方面有更多的建树,那么编程就是你必须得懂的技能。前几天在网上看了《WIN下编程须知》一文,觉得写出一篇适合初学者们看的入门级文章的确很重要,可惜此文只介绍了线程、消息、句柄等几个基本概念。...
  • 程序员编程艺术:第八章、从头至尾漫谈虚函数

    万次阅读 热门讨论 2011-05-26 01:03:00
    程序员编程艺术:第八章、从头至尾漫谈虚函数作者:July。出处:http://blog.csdn.net/v_JULY_v 。 前奏 有关虚函数的问题层出不穷,有关虚函数的文章千篇一律,那为何还要写这一篇有关虚函数的文章呢?看完本文后...
  • 读《Unix编程艺术》笔记

    千次阅读 2009-11-21 15:08:00
    http://blog.sina.com.cn/s/blog_4c451e0e0100d5be.html 读《Unix编程艺术》笔记 (一) 1)行为的最终逻辑被尽可能推后到使用端; 2)最终用户永远比操作系统设计人员更清楚他们究竟需要什么; 3)用错误的方式...
  • Java编程思想(十三) —— 字符串(2)

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 28,933
精华内容 11,573
关键字:

编程知识容易忘