费曼学习法和写代码1


java关键字



下面重点记忆






在刚才,是不是给大家讲解了什么是咱们的注释啊? 那现在,咱们要学习一个东西,叫做标识符。 学标识符的话,我们也会聊几个东西,叫做关键字啊。 这是什么东西?咱们再慢慢看。 首先,咱们每个人从出生开始,是不是就会有一个名字啊? 咱们生活中的所有事物都有名字,这个名字是谁规定的呢?是不是造物主啊? 比如说,我们自己的名字,就是我爸妈给我取的,对不对? 那些科学家他们造出来的东西,是不是就他们命的名字啊? 每个东西都有自己的名字啊。 所以说,在程序里面也是不例外的。 我们作为写程序的人,是不是程序员啊?是这个“员”啊,不要写错了。 程序员是这个“员”。 OK,咱们作为“造物主”,要给所有东西也要取个名字。 比如说,咱们刚才写的那个Hello World程序,来回到这个HelloWorld,打开看一下这个Hello World程序啊。 当然现在,是不是被注释搞得太乱了?咱们把这个注释提到外边来,这样的话就会清楚一点。 OK,咱们来看这个HelloWorld的代码,只有这几行,它有自己的名字啊,这个名字是不是叫Hello World呀? 这个Hello World,就是咱们的类的名字,它是一个class,是一个类吗? 然后也是我们的文件名字,看到了没?把它放大来看,是不是这个地方有个public、class这种高亮的东西? 在这里面就是一些关键词啊,是咱们系统定义的,是搞Java的人给它定义出来的,我们拿过来是不是直接使用就好了? 它们有一些特殊的作用啊,而且这下面的每一行代码,包括这边的东西是不是都变色了? 你们可以发现,它都有自己的一些意思啊,都有自己的名字,这些东西就是用来做区分的,它是干嘛的?它是干嘛的? 就跟咱们的名字一样,是被拿来称呼的,程序是不是一切都是源自于生活的? 咱们在学程序的时候啊,一定要把它跟生活中的一切联系起来,你会发现这一切东西都是息息相关的啊。 OK,咱们来看一下Java,除了这个我们见到的public、class,还有这些什么public、static、void这种变色的,还有这个out等等,是吧? 像这种一些东西是关键词,就是系统定义好的。 除了我们写的这几个简单的,总共有哪些呢? 我告诉你们,就是咱们整个Java学完,你们也就只能遇到这么多,看起来非常多,是吧? 在咱们学完Java基础阶段的话,就认识一大半了;在学到咱们的面向对象的时候,几乎就认识完了,除了几个特别的,咱们几乎都能用得到,而且这个地方是常用的,咱们很快,我保证你们都会学完,对不对? 哎,不要觉得看到这么多英语单词就有压力了啊,这是千万不要的。 咱们都是一个一个学的,比如说就这个public、class,咱们来找找,在这里面看能不能找到,我来看一下。 我的眼神可能不太好啊。 来,咱们来看这个地方是不是有个class啊?咱们是不是已经用到了?虽然说你不知道干嘛的,但是随着学习深入,你每天都在写,很快就会了。 这个地方是不是有个public呀?然后除了这个地方,咱们还有一个叫做static的东西,来看,找一找static是不是在这个地方啊? 像这些东西大家都已经见过了,还有一个void,对不对?来找一个void,咱们的void,看一下,在这。 OK,这四个咱们还没写就遇到过了,剩下的东西写着写着也就全认识了。 我们是一个一个去慢慢随着深入学习的,每一个关键词,它在不同的领域啊。 所以说,大家不要觉得我们会一天让你们把这个背完啊,跟小学英语一样啊,肯定不会的。 我们随着学习,可能一天就多接触一个或者两个这样的东西,而且要把它用到熟练。 所以说,大家不会有觉得特别难的这种感觉。 所以说,秦老师在这个地方是不是给大家打了心理预防针啊?千万不要怕。 哎,咱们这些关键词就是你们现在能看到的,你们可以把它截个图,这些东西啊,你们以后在Java里面就不能用这些东西去取名字了。 比如说,你写了一个类名字叫做public class class,它就会报错啊。 比如说咱们来试一下,你看都是小写的class,你在这个地方再来一个class,你看直接就报错了。 首先不说文件名不同吧,这个地方就过不去,它已经高亮了。 OK,这些关键词啊,就是说在关键字这些东西是第一个规范,就是写咱们写Java的一些标识符的时候,不能把它们写上,就是你起名字,不能用它们来起名字。 OK,看下面这句话:Java所有的组成部分都需要名字,无论是咱们的类名还是变量名以及方法名,都会被称为标识符。 那咱们来看一下,什么叫类名、变量名和方法名啊? 来对应着这个Hello,来看这个就是外边的class描述的,它就是一个类,这个就是类的名字。 然后这里面的一个public、void,这就是一个方法,这个方法的名字叫main,但是我们这地方还没有变量,我们等会可以去定义一个。 比如说我现在来定一个吧,这叫String,来一个teacher(老师的意思啊)。 他的老师名字叫什么呢?比如说我这样叫做秦江,对不对? OK,这就是咱们最明显的一个定义变量,这个变量的名字就是咱们的teacher。 你看这个地方可以自己随便写,每个东西都需要名字啊,不然的话我们是拿不到这个值的。 不用不用管我写的什么,现在大家如果不认识的话,跟着我敲就对了,咱们到后面学习下去,很容易就理解了。 OK,咱们来继续往下看啊。 我们平时在写这个标识符的话,它会有一些简单的注意点。 比如说,所有的标识符都是以字母(大写A到Z或者小写a到z)、或者美元符($)、或者下划线(_)开始的,只能以这些开始啊。 我们来试一下,我们以其他东西来开始试一下。 比如说,我来写第二个程序吧,比如说叫做Demo01吧,就像做Demo01,就往下写嘛。 OK,咱们来试一下定义变量吗?我们还是要写一个main方法,这是咱们的代码架子,对不对?现在学的。 OK,他说所有的标识符都应该以字母命名,那咱们来试一下,比如说跟着我写,我们都用String来定义,你还不知道这是干嘛的,就写上,跟我一样。 写上,看这是不是也有一个,写到这个地方。 然后咱们来,比如说他说可以A开头,A_hello,是可以的。 我们后面都用名字来吧,都叫秦江,来随便写。 就拼一把,来看我们写了这些变量,它说可以A开头,是吧?也可以小写开头,没问题,也可以以$符号开头(就是Shift加上大写键盘上的4),这个也没问题。 还能以下划线开头,下划线开头也没有问题。 然后我们再来试试其他的符号,你说我想玩,我能不能以数字开头呢?哎,发现直接报错了,不得行。 然后把这个注释掉,现在认识这个注释了吧? 除了这个的话,我们再试一试,能不能以井号(#)开头呢?你们说反正想玩嘛。 井号开头,哎,是不是也不行啊?又报错了,所以说这个也不行。 那除了这个之外,你们说能不能以什么其他东西开头呢?再来一个,比如说以星号(*)开头吧,来把这个注释去掉。 OK,是不是也报错啊? 它就只能以这些开头啊:大写字母、小写字母、美元符号($)跟下划线(_)。 OK,第二个规则:首字母之后,可以是任意字母、数字、$、_的任何组合。 来看啊,他说的是首字母之后,咱们第一个字母有限定了,咱们后面怎么写呢? 来看,他说后面可以用数字,咱们也来试一下吧。 比如说,String,这两个重名了,所以说不让他重名,我们就把它后面改掉。 他说后面是可以任意组合,我们来写个a1_1,没有问题,对不对? $符号和下划线,怎么说?可以是任何字符的组合,你看a1_$bc都是可以的。 那还有问题,你写个a1#,看是不是报错了? 像井号这些特殊符号啊,你就不能随便写在咱们的变量命名当中啊,一定要符合规范,正常的话英文字母就够用了。 那咱们再继续接着往下看啊。 第三个规则:不能使用关键字作为变量名或者方法名。 诶,刚才是不是在大量给大家说啊,就这里面的东西咱们不能去直接再定义了。 比如说你们想试的话,就来试一下嘛:String class;,你看直接给你报错。 像这种被定义的东西你不能用,因为Java给它了一些意义,你给它随便用的话就是不行的。 比如说咱们中国的话,一些伟人的名字,你们是不是也不能随便叫、随便取啊? OK,除了这个之外,咱们还要往下看标识符合法的一些举例,给大家看一下。 比如说像这样的:小写字母开头(name)、$符号开头($name)、_开头(__1v6),后面随便组合,没有问题。 然后非法的:数字开头的(123abc)就不行,减号开头的(-name)更不行啊,井号(#)也是不行的,都给大家看了。 这句话非常非常的重要,把它圈起来:标识符是大小写敏感的。 什么意思呢? 这句话,比如说,咱们往下把这个往下推,我们现在来写变量啊,这个东西,来我们来首先给大家写一个:String Main = "秦腔";,对不对? String main = "秦腔";,这个Main跟这个main是完全不一样的东西啊。 它所以说大小写十分敏感,这个一定要注意,大小写十分敏感。 因为咱们Java它是一种强类型语言啊,只会给大家讲讲,它对这个东西要求是非常高的,你必须按照自己的规范去写,不要瞎写。 OK,咱们还可以有一句话:可以使用中文命名,但一般不建议这样去使用,也不建议使用拼音,很low。 很多人初学者啊,在国内的,他都喜欢用拼音去命名字啊。 比如说这个地方呢,本来看String的话,它是不是应该取个name啊(英文,名字的意思),然后他们用中文怎么取呢?String 名字 = "秦江";,哎,这个东西说实话看不懂,我自己都看不懂,对不对?不要这样去写啊。 除此之外的话,像这种变量的名字啊,标识符的名字,我们还可以以中文来命名。 比如说,来一个String 王者荣耀 = "百星王者";,就那个例子,王者荣耀,对不对? 这是咱们的一个名字,荣耀,OK,王者荣耀,他可以给他赋一个值啊,我们来给它赋一个值。 比如说大家什么段位啊?我估计大家都什么段位,是不是百星王者呀?百星王者。 OK,我是什么段位呢?我叫做倔强青铜啊,对,倔强青铜,这就是差距。 对不对?你们都是王者,我是个青铜。 OK,我们可以用中文命名啊,把这个注释掉,因为这两个名字一样了,它是不能重名的,在Java里面。 所以把它注释掉,然后咱们可以输出来看一下,我们来输出一下这个王者荣耀。 输出一下,你看这个语句是输出,咱们都见过,之前我们是不是输出了一个具体的字符串啊? 它现在的话,可以输出一个这样的变量啊,先跟你说,这就叫变量,它可以给后面赋任何的值。 你看我们现在把它叫王者荣耀,我们来输出一下,输出看下他最后的一个结果,你们可以跟着我写,看他是不是出了百星王者啊? 我也可以把它叫做倔强青铜,来看,他就输出青铜了。 但是我输出的东西,它是不是就是一个固定的呀?你看到没? 所以说这个就是变量,它的值可以进行变化。 OK,咱们除了这个地方用中文名字,咱们这个类名也能用中文名字啊,但是不建议大家去使用了,对不对? 非常非常的不规范啊。 我们在平时编写代码的时候,一定要养成良好的习惯,保证这些东西合乎规范,都对,也不要去瞎写,尽量见名知意,用咱们的英文单词去表示。 最好你用中文的话,说实话,你这个程序发不出去了,以后没有人能看得懂,对吧? 养成一个良好的规范,是不是再一次强调啊? OK,这就是关于咱们标识符的一些东西啊。 咱们随着学习的深入,每天都会用,所以说慢慢的就会越来越了解它到底是什么样子的了。 咱们等会儿来看一下,咱们什么是数据类型啊?这个东西是比较复杂的,先给你们说一下,有个提前的预知,是吧?当然也非常简单,因为都是我讲的,是吧? OK,那咱们这一块就到这个地方。 一定要下去把这些规范记住啊,只能去遵守规范就行了,因为理论的话还是比较多,对不对? 但是记住这样一句话:每一个理论它都会有具体的应用。 咱们这边学的理论,是不是我都用代码这样的方式给你们一个一个在应用啊? 你们平时学东西也得保证这个思路啊。


char只能放一个字或一个字母!




BigDecimal 是 Java 中的一个类名,由两部分组成:
Big:意为 “大的”
Decimal:意为 “十进制的、小数的”




高转低,强转;低转高,自动转。






有long转long无long转int


^相同为0,不同为1
波浪线是取反运算符














奇数和偶数



由于要先解决如何做题,书中读十几遍其义不能自现,直接跳到这个视频开始看,看后比ai讲的更通俗易懂一点


由于视频没有字幕,自己听着来写,因为语言不能断章取义,所以尽量把听到的都写上方便以后自己忘了方法这方面知识的话回头去看去学起来更方便,日后看这个下面写的就能回忆起这个视频讲的内容了。
Java的方法,
我们先来理解一下这个词啊,什么东西叫做方法?
我们一般是不是在我们的日常生活中,我们的方法就可以理解为我们要去做某件事情而采取的一些解决办法呀?诶比如说我们今天来这个地方学习,你们就要面临着一些事情,比如说诶,你们该通过什么方法来到学校对不对?这个问题你们要怎么解决呢?你们是公交车呢,还是打车呢?对不对,还是坐地铁,诶那么这些解决问题的一些东西,我们得把它称之为什么,是不是方法,这就是生活中的一些方法,那在咱们的Java里面就是方法,它是来完成某些事情的,比如说我们写一个添加的方法I的,对不对,也可以写一个加法,就I的代号1+2,它就把这个1+2算出来,它会返回一个3,诶,这就是一个加法的方法,那是不是还有减法,乘法,除法诶等等你们学过的那些输出的方法,Print print line, 这些都叫做方法,那咱们来看一下这章要讲哪些内容,首先分为这几个点啊,第一个你们要。
搞清楚哎,到底什么是方法,第二个学会方法的定义以及调用,诶,第三个了解什么东西叫做方法的重载,诶这个也非常非常重要。第4个给大家扩展的对不对,可以把它当做一个课外扩展点,就是命令行传参,就咱们那个黑窗口啊,你们之前学的Java c Java到此那些命令它为什么可以用呢?我们今天也可以用啊,就自己写的Java程序,通过命令行传参。第5个HGDK5的新特性叫什么可变参数,这个东西大家可能还不理解,到时候写了再来说。最后最后会给大家讲解什么是递归,递归的话是一个比较重要的点啊,在面试笔试里面经常经常的出现它,然后在学习的过程中啊,依旧会给大家穿插一些练习题,让大家加深的去理解,那咱们来看一下第一个到底什么是方法对不对,咱们前面都学过一个叫system outp println, 它是什么东西啊,哎,大家都知道,它可能就是一个输出语句是吧,也仅此而已,知道你们就知道它是一个输出的,但是他并不知道。
为什么输出,然后它的每一个结构是什么,可能大家现在都不是很清楚,对不对?那我来带你们分析一下,诶,这个CS team啊,它是一个系统的类,它是一个类,就跟咱们呢,你们写的一个hello word DEMO一一样,它就是一个类,而这个out它是一个对象,就是systemteam下的一个输出对象,然后这个后面这个带括号结尾的print line, 诶,它就是一个方法,那回想一下咱们在上一章学的那些方法,比如说咱们的scanner的一堆next next line, 它们是不是都是点儿出来的,然后一串方法名字啊,加一个括号呀,等等你们见到的这样一些的东西啊,它都是咱们加法程序里面的一些方法,那这句话到底该怎么去理解呢?意思就是调用咱们系统类里面的标准输出对象out中的方法叫做print line方法,哎,就是这样来的,它是类,然后对象方法对不对?那咱们来看一下到底什么是方法啊,这句话,记住方法是语句的集合,他们在一块儿可以执行。
你一个功能,哎,比如说啊,我们要让一个公能,我们经常是用到A+B这样的东西啊,诶你发现大量的在使用的话,你就觉得东西太重复了,非常麻烦,你就可以把它这种公共的东西干嘛抽取出来,提取一个方法,咱们等会儿来写一些比较简单的方法,那我们还是通过代码驱动,最后再回到咱们的PPT啊回顾一下这个问题,方法的命名规则是什么?大家还记得吗?是不是我说的首字母小写后面是驼峰命名规则呀?
拖蜂命运规则还记得吗?来,咱们去代码里面实现一下,OK, 咱们回到代码里面,我们来建一个包吧,给它叫做method,哎呀,怎么右键点不出来啊,等会儿卡了,来一个method的方法,M meth OD, 这是咱们方法的意思啊,Method我们还是先来定义一个类啊,比如说这个地方叫做DEMO萌01可以吧,反正就挨着走呆萌01,咱们来看一下到底什么是方法啊,我们每次写一个程序PSVM,你们说下这句话的时候,是不是就出现了一个东西叫做main方法呀,当时我跟你们说的这个地方是不是咱们的main方法,名字叫main
方法,OK, 这就是一个方法,但是这个方法啊,是交给咱们程序管的,不是我们自己去写的啊,那咱们要写的方法一般都会写在它的外边,比如说咱们来写一个刚才的加法运算,比如说加法,加法这个方法怎么写呢?首先看着我的操作啊,先跟着我抄远,Public是它的一个修饰符,你可以不要对不对,然后还有一个int,这是它的一个返回值类型,看这边的返回值类型是不是Y的呀。
啊,咱们的慢方法,我们知道这个public和static,我在前面说了,这个东西都是修饰符,然后后面这个是咱们的方法的一个返回值,这个返回值外就代表它不返回东西啊,咱们论方法执行完是不是就结束了,但是咱们加法它就会返回一个值,你说1+1是不是要等于2啊,它有个等于的值吧,所以就是这来的,然后方法的话,你需要给它起一个名字,那咱们这个地方就起了一个名字叫做I的,然后你也可以给它加一些参数,我们加法运算一般是不是至少需要两个数啊,我们就给它设置两个数,你看设置一个in特A,设置一个B,诶,当然这两个数只是形式上的,我等会儿要用它的时候再给它传实际的,那咱们这个地方就return,就是给它返回一个A+B,诶大家现在是不是第一次尝试这种方法,并不理解到底是干嘛的,先跟着我写一遍,然后咱们再回到PPT去看对不对,那这边写完了上面是不是要用啊,你们发现没有直接调用I的调不了对不对?那么回忆一下我在之前说的怎么调啊,是不是我们给这个方法也加一个static就可以了。
让它成为内变量,我们就可以直接使用这个I的方法,你看I的是可以直接用的,然后我们给它传个一逗号2,这时候你们看一下,我们给它生成一个变量,是不是返回一个值,我们这个值的名字是不是就随便写了呀,然后输出一下咱们的,比如说这个叫做3,它的一个和来输出一下,这个和你跑一下啊。
看一下它是怎么走的,什么东西叫做方法,然后我们去看看它怎么走,你看是不是输出了一个3啊,诶这个三门确实对于这个A+B怎么来的,咱们来打一个断点调试一下,还记得我的debug吗?来选中这个红点,然后干嘛?点击这个debug模式,就是调试模式,你看到现在走到这个地方,咱们现在进main方法,main方法的参数你看它写的是空的,这个地方是可以传的,那不管它,咱们走下一步,诶下一步你看我们到了这个I的方法,它直接跳到了这个位置执行对不对,它走了一个A=1 B=2,这是不是你给它上面传递两个参数就到这来了,然后到这个地方,它就会把这两个值进行一些运算,你可以看到啊,Return的A+B这地方有A=1 B=2,那你再往下走一步呢,你可以看到它是不是就回来了,回来的时候诶这个summer它就有值了,然后你再往下一步,它就可以发现它这个summer是不是就对应3啊,它相当于调用了一个方法去执行的,OK, 听不懂没关系啊,咱们理解一下,跟着我走1。
变,那咱们回到PPT来看一下,这个地方能理解吗?方法它是用来解决一类问题,有序步骤的组合,我们这个地方的步骤是不是就是返回A+B呀,这是一个非常非常简单的方法,咱们也可以返回一些麻烦的方法,等会儿再来给大家慢慢深入。那第二个方法包含于类或者对象中,把PPT放大一点啊,第三个咱们的方法在程序中被创建,在其他地方被调用你们东西,比如说咱们这个client对象不是你们自己写的吧,但是它是不是咱们Java程序里面就有的,你们只用去用它就好了,它就是用来被调用和引用的,我们可以把自己写的一些功能干嘛都抽取成一个一个的方法,诶,我们到时候要用它,直接就用就好了,就像我们的前辈们,他们是不是总结了很多生活中的方法跟经验,然后我们去学习使用就可以了,那这个也是一样的,包括这个什么输出类,咱们学到hello word里面是不是我也是教大家如何去使用,但是大家还没有去写过这个方法,OK, 那咱们来看一下它。
它有一个设计方法的一个原则,就是这句话,直接看红色的啊,一个方法只完成一个功能,就是你的方法里面不要做太多事情,比如说加法,它就是加法,你不可能写一个计算器方法,用它来做加减乘除吧,你最好加法加法乘法乘法对不对?除法,除法这个东西叫做原子性,它的官方名就原子性啊,说白了就是干嘛一个方法只做一个功能,诶这样的话是比较好的,为了大家更好的理解啊,再给大家举两个例子,比如说我们之前在这里面写了一些方法,诶随便去找一下有没有长一点的运算符之类的,那咱们来看一下这个找负循环的吧,你看这是不是一个非常烦的方法呀,咱们要输出这么多整数,怎么输出呢?它现在是在咱们的main方法里面没有问题,咱们把它给干嘛啊,提取出来,这是不是就是一个功能啊,这一段代码的功能就是输出一堆数字,那咱们把这个方法提出来,比如说你看着还是提public,由于刚才那个方法都是输出一堆数字是吧,它就不像这个A+B,它需要返回一个值了啊。
它就返回一个空,而这个vide的就代表空的意思,那咱们这个地方的方法名就直接叫做test吧,给你们说测试这个名字是不是随意的取啊,然后这个夸括号就代表它的一个方法的样子,这个就是一个固定的写法,咱们等会儿再聊,你看OK,你把你这段代码给它放进来,它是不是就被提成一个方法了,现在你要使用这个方法干嘛?调用它就可以了,为了方便调用干嘛?加上咱们的static,在咱们没学对象之前啊,就先用这个static OK, 把上面这两句话干嘛先注一下,注完之后咱们来调用一下这个方法,你看怎么调用方法呢?
直接去使用它就可以了,拍死它,OK, 执行它,他就可以直接跑起来了,你们来看一下,跟我们想的一不一样,诶,你看他是不是依旧把1~1000输出出来了,但是我们现在没有像刚开始那样子放到焖方法里面,我们的焖方法啊,要时刻保持简洁干净,尽量把一些公共模块干嘛都提取到外面,通过方法调用的形式来,哎,这样子咱们之后在学习GVM的时候,大家就更清楚了,因为这个地方是不是要涉及到一些底层的东西啊,M方法是在咱们占的最底层,所以说它这样调用的话,你可以看到非常的非常的清楚,诶这句话大家听不懂诶,没有关系,重点先理解一下,诶什么是方法,有一个概念就好了,对不对?
其中红色部分是下面内容:



总结:方法是可以被调用的,而且主要是被调用的,比如上图的test()

我做题思路,先写出public class A58 {,再按照题目要求定义一个名为printWelcome 的方法public static void printWelcome()
然后方法功能是打印打印 欢迎学习Java方法!;,
然后再写主要内容public static void main(String[] args) {
然后直接就可以在里面写 printWelcome();直接调用上面的方法了,最终如下

第二课内容:

由于视频没有字幕,自己听着来写,因为语言不能断章取义,所以尽量把听到的都写上方便以后自己忘了方法定义(多了个定义)这方面知识的话回头去看去学起来更方便,日后看这个下面写的就能回忆起这个视频讲的内容了。
那我们继续来看啊,到底方法它定义是个什么玩意儿,对不对?我们上面已经写了一些简单的方法了,还是这句话,看一下方法,Java里面的就类似于其他语言的函数,诶你们以后在C语言听到函数,或者在javascript里面听到函数,哎,这个东西就跟咱们的方法是差不多的,你看是不是类似啊,他们都是用了同一个作用,用一些代码片段,就是咱们的一个方法来完成一些特定的功能,比如说我们上节课说的加减乘除这样的简单东西,对不对?一般情况下定义一个方法只需要包含一些方法的基本内容就可以了,其实咱们上一节课已经写了,咱们来重点看这一块儿,你看它首先需要有修饰符,咱们说了修饰符是不是可以有多个啊?回想一下咱们学了哪些修饰符啊,是不是至少看到过一个public啊,我给你们讲过一个static啊,讲过一个final等等这样的值啊,它都是咱们的一修饰符这个地方说了,它是不是可以选择的呀,所以说你可以选,可以不写,没有关系,第二个方法的返回值。
我们上一节课是不是给大家写了一个int类型,然后还写了一个Y的呀,就是加法加减乘除,它会返回一个数字啊,如果你只是输出一句话,它就什么都不会返回,就会有一个Y的啊,如果没有返回去的情况下,一般是不是都是用Y的啊,Y的就代表空的意思,那第三个咱们这个地方是什么呢?方法的名字,我们说了加法里面所有东西在第一节课里面是不是就说了都需要有个名字,就好像咱们人一样,你要叫别人怎么叫,这边是一样的,方法名就是方法实际的名字啊,名字是不是可以随便取啊,但是要遵守什么啊,命名规范,驼峰命名是不是啊?开头小写,后面首字母大写,那后面参数的话可以加类型。
在刚才的代码里面,咱们去看一下,是不是也用了咱们加法那个代码,你看就后面丢了两个参数,这个东西要参数啊,就是我们可以给他传递一些具体的值,让他进行一些运算啊,操作啊等等,然后后面这个是不是test里面我们就没有传递参数啊,它也可以直接调用,也是可以选择的,这就是咱们的一个参数类型,它更像是一个占位符啊,这个地方写了理解这个占位符的概念,咱们等会儿多写一点,你们就懂了,这个参数啊,它是可以选择的,看到了吗?方法也可以不含任何参数,这个地方咱们都理解,咱们的main方法是不是就有一个默认的参数啊,一个string括号X这样一个东西,大家现在还不理解没关系,下一章学数组就理解了,那也是一个数组参数,咱们等会儿也会用到,然后咱们来看一下这个方法里面有两个东西,一个叫做实参,一个叫做行参,什么意思呢?实参就是我们调用这个方法实际传递给他的参数,行参就是咱们去定义这个方法的时候随便编的一些参数。那咱们来看一下什么叫。
三根13理解一下咱们这个地方是不是定义了一个简单的加法呀,加法它需要接收两个值,就是我们要给它传递这样两个数量,两个变量,它是不是才能进行计算呀,那这个东西就是咱们的形式参数啊,就是我们用来定义作用的,你们可以这样理解,形式参数用来定义作用的,那什么是咱们的实际参数呢?咱们来看一下上面这个使用的1+2这个例子,咱们把它给干嘛取消注释,那咱们把这下面这个test出了来,看我们这个地方是不是在真正的去调用这个I的方法,你看我一点这个是不是下面就亮了,它通过这一种语句来调这个方法,把这个1跟2传递进去,然后最后返回了一个sum,相当于把这个1复制给了下面这个A,把这个2复制给了下面这个B,对不对,这个就是实际调用给他传递的参数就叫实际参数啊,诶这样讲一下是不是大家就明白了,哎,PPT上写没有用,还是要看代码,咱们要以代码为主啊,学习的时候多敲代码,多去写注释,自己给自己增加一些理解的渠道,对不对,实际。
这参数就是我用给的嘛,我给他传的嘛,那新的参数是不是就是我定义这个方法,这个方法又没被我用,我先给他两个占位符,我这个地方随便写任何,比如说我这边写AAA,你看都可以写BBB,不影响它只是个形式参数啊,然后最后它调用给他传递的是不是叫实际参数啊,理解这样一个简单的概念干嘛就可以了,不用管它,你看方法也可以随随便便的写,那咱们还是来继续往下看,中间的话是不是就还有一个方法体呀,这个方法体就是咱们方法里面包含的任何语句,它定义一些方法的功能,比如说我们加法的是不是就返回一个A+B啊等等,包括等会儿我们再去写一个比大小的方法吧,等会儿来写,然后最后有个地方我没在PPT上面写出来,看这个位置啊。
叫做return,如果咱们方法存在返回值的情况下,一定要把返回值通过return这个关键词返回出去,如果是Y的,哎,那就不用return了,理解就是return就是返回一个值,那咱们要返回值的类型是不是要跟上面这个对应啊,就是一对一的感觉,那咱们还是来写一个方法,再多写一写,咱们来一个,咱们来一个DEMOMON02吧,在这个地方DEMO02。
不给大家混到一块儿啊,M0啊,那咱们来看一下,首先什么都不干,论问方法是不是先写上啊,咱们来写一个比大小的方法来比大小,比大小怎么去理解呢?首先根据我的调要求啊,第一个是不是得要一个修饰符啊,Public代表公共的,我们所有人都可以用它,之后还会有几个当面相对换的时候再给大家学啊,然后第二个咱们再来加个修饰符,Static, 这个修饰符是不是就相当于告诉大家诶,我要直接调用它,它可以是一个类,属于类的一个类变量啊,咱们之前说的,然后咱们回到这儿来看是不是修饰符我们就搞定了。第二个方法返回值类型,那咱们这个地方方法返回值类型比大小,它肯定会返回一个数,是不是我们可以写一个int没有问题,然后这是咱们的一个返回值类型就好了,那方法是不是还需要一个名字呢?那咱们一个名字来一个叫做max,就是比大小,OK, 这是咱们的方法,OK, 把这个括号是不是写完啊,这是一个具体的东西啦,然后你看现在是不是报了个宏,他说你必须要返回一个值,但是我们现在还没有做所。
所以说先不返回,那咱们来看比大小肯定要有两个数来比,所以说我需要给它丢两个形式参数是吧?比如说这个地方叫做NUMBER1,然后再来一个NUMBER2,咱们说啊,这个名字你们是不是可以随便取,它只是一个形式参数,我们在这个方法里面会用这个参数去给它传递而已,那咱们来看一下这两个数到底该如何去比较大小呢?是不是我们可以这样判断,如果哎,NUMBER1就是咱们的第一个数大于咱们的NUMBER2就说明什么,是不是第一个数大呀,所以说我们应该让它返回咱们的NUMBER1,那怎么返回呢?你直接老师说,诶,我刚才说看了return是返回值啊,那我return一个NUMBER1可不可以?诶,当然可以,但是这样你看是不是还报错呀,咱们的return要提取到最外边来,咱们一般把return啊写到最下边,能不能理解。
那写到最下边怎么样子把这个NUMBER1反回出来呢?我们一般可以采取一种方式定义一个变量就可以了,比如说我来一个结果叫做result OK, 那咱们把这个NUMBER1复制给result是不是就可以了,就是如果它大,它就把它复制给result,最后咱们return一个咱们的result,这个结果就可以了,就是把这个结果干嘛返回出去,诶大家能理解吗?然后咱们来看一下这个地方是不是报了条红线啊,然后他说了一个话,看是不是咱们前面说的基础啊,他说这个变量result呀,它需要干嘛被初始化,你可以给他一个初始化的值,比如说初始化的值叫做负一,可不可以你随便写叫0也可以,叫100也可以,是不是都可以叫啊,反正它最后都会被下面这个东西干嘛给它覆盖掉,哎,咱们这个地方是这样的,那是不是还要加一个判断啊,如果你不是NUMBER1大呢,如果是NUMBER2大于咱们的NUMBER1,这个就说明谁大呀,是不是说明咱们的NUMBER2大呀,那就把咱们的result是不是给。
他把NUMBER2的值复制给他就可以了,诶这样一个结果,但是这样的代码大家一看啊,是不是很不舒服啊,那怎么这样可以做到它舒服一点呢?我们可以可以可不可以这样做if,它elses,你看加了一个elses,把这个result拿过去,如果NUMBER1>NUMBER2,说明NUMBER1大没问题,如果咱们的NUMBER1<NUMBER2,那咱们的。
NUMBER2是不是就大呀,但是我之前给大家说过,是不是咱们的程序要严谨啊,所以说这样一个方法还不够,你肯定要去判断它,万一这个人输出的东西相等怎么办,那你是不是要输出啊,如果NUMBER1等等于NUMBER2,诶这种情况就表示他们两个相等,相等怎么办呢?我们就直接在这个地方输出一句话就好了,输出一个什么话呢?咱们叫做NUMBER1等等于NUMBER2,然后输出完看我的操作,我直接在这个地方加了一个return return, 咱们随便写一个RETURN0,看这句话啊,Return除了返回结果的意思,它还有另外一个意思,叫做终止方法啊,来终止方法就是咱们的程序啊,一旦碰到这个return在方法里面,这个方法就结束了,比如说他进到这个地方,他走了,这个方法之后,RETURN0以后这个方法就结束了,我们一般可以通过return来结束一些方法,在某些特殊的情况下,这也是OK的,能理解吗?然后咱们可以去。
做一下这个事情,比如说咱们这样去写一个ma克X比大小来ma克X比一大大小,比如说比一下10跟20,咱们肯定傻子都知道是不是20大呀,那咱们来输出一下这个max,你看咱们现在调用这个方法是不是直接调用它就可以了,那咱们来看的方法调用什么鬼啊来方法的调用有两种方式,第一种如果方法有返回值的时候,一般方法调用会被当做一个值来处理,比如说咱们刚才写的这个方法对不对,Max它会返回一个更大的值,如果方法为空,那么方法调用一定是一条语句,比如说咱们的system outp print line这个方法对不对,它直接用就可以了,这就是咱们方法调用的一些东西啊,然后具体还有一个对象名,点方法名,这个诶等会儿再来给大家说,不着急,咱们先把这个东西搞定,能理解咱们现在这个地方max是不是给它传的实际参数是10跟20,它的形式参数在这儿啊,他把这个值传给他之后,他们就进行一些运算,最后把咱们的result返回给来,返回过来是不是就max这个它是有。
所参数的结果把它赋给这个值啊,方法调用完它是一个具体的值,那这个方法呢,输出方法它是不是就没有返回值啊,咱们可以点开看啊,摁住它,摁CTRL,然后点进去就能看到它的源码了,这个源码大家不用看得懂,但是你知道这个public是修饰词,Wide是它的返回值,是一个空,对不对,Print, 然后你可以给他传递一个参数,让它输出出来,OK, 那咱们去跑一下,看一下这个程序啊。
咱们让它跑起来。
这就是两个方法调用完全不一样的概念,你看是不是输出了20啊,因为咱们20是比较大的,那咱们现在来再做一件事情,比如说咱们来一个10跟10,这两个是不是一样了,它会返回一个0,你看着。
你看这个地方是不是输出了NUMBER1=NUMBER2,我们在程序里面做了这种方法,最后他返回了一个0啊,因为他们两个比较不出来谁大,当然这是一种解决办法,比较low是不是啊,但是是一种思路,重点是告诉你们什么程序需要严谨,你方法需要给自己的方法负责,对不对?很多人进公司,你要去给别人修改方法的话,诶,你要经过别人同意的,你给别人修改出问题了啊,一一个业务崩了,是不是所有的东西就崩了,这样的话就是不行的,你看我们通过这个比大小的例子,希望大家能够干嘛再深刻理解啊,到底什么是方法,那我们等会儿再来看方法它的一些重载是干嘛的,顺便给大家是不是把这个对象名点方法名啊,也给大家说一下,其实啊,之前已经说过了,只是大家可能印象不深,就是我们需要去拗一个对象来操作,对不对,那样是比较麻烦的,在咱们目前学习基础阶段的话,大家还没学到对象那个方法,大家现在用起来的话,可能也只是抄一抄,还不理解意思啊,那咱们来看一下这个东西。
课后拓展了解,这是一道家庭题,我到时候会把文章在群里发给你们啊,就是什么是直传递,什么是引用传递,为什么网上很多人都说Java是直传递,诶,这句话肯定没有错,你们也可以先记住Java它是直传递,那到底什么是直传递,今天晚上给你们发那篇文章,里面会认真认真的给大家什么详细的说明,因为这两个概念啊,干嘛经常在咱们的笔试中遇得到,就是他问你这个东西是直传递还是有用传递,但是你们记住Java都是直传递,OK, 就是咱们现在这个写的类里面啊,它是不是有两个方法,一个是咱们的main方法,一个是这个max方法,而咱们的main方法它是被咱们Java虚拟机调用的,除此之外,这个main方法跟正常的普通方法没有任何区别,Java中只有值传递,对不对?把10传递下来,然后他去走它的值传递,它会有一个拷贝的概念,现在给大家讲多了,大家不理解,所以说不着急,学到GVM的时候,诶,然后你们。
跟自己现在在自己的电脑上花10分钟把这两个方法理解一下,自己定义一些方法,然后去调用一下,顺便输出一下,理解一下咱们这个方法它到底是个什么作用,对不对?很多人说肯定有人就会说,老师不要这个方法也行,不要也可以,假如你的代码非常多,成千上万哈,你如果不拆分的代码,你那个main方法里面还能看得下去不,还能见人不对不对,而且方法它可以实现共用,我这个方法写好了,我在另外一个程序里面要用,我是不是直接把这个代码拷过去就可以了呀,这就是一个非常方便的作用啊,甚至不用考我们后面学的对象,我们可以通过这个类去调到它,诶就十分十分的方便了,直接可以在其他类里面用方法的好处啊,会随着咱们学习的深入干嘛,逐渐逐渐的越来越理解学习任何一个东西。
java是都是值传递。
开始看下面一课程方法重载:

方法重载可以让名字相同,方法名字可以相同,但是参数类型不同,比如int和double类型

由于视频没有字幕,自己听着来写,因为语言不能断章取义,所以尽量把听到的都写上方便以后自己忘了重载这方面知识的话回头去看去学起来更方便,日后看这个下面写的就能回忆起这个视频讲的内容了。
刚才的练习大家都练完了吧,哎,其实写一遍是不是就知道哎到底什么是方法了,那咱们来看一下到底什么是啊,方法的重载这个概念的话也是非常非常重要的,认真认真的听,你看,先理解它的概念,重载就是在一个类中,它有相同的函数名称,但是参数不同,什么意思呢?咱们来看一下这边啊,咱们现在这个地方是不是有个max方法啊,这个max方法它的参数只能是int,假设我现在给他传了一个double类型,你看我传了个十点十,他是不是就加不了了,他就比不了大小了,但是我们想让他这样也能比,怎么办呢?哎,没有办法了,你有可能老师说再简单呀,我们是不是再定义一个方法就好了,比如说怎么定义,你看着我再定义一个一模一样的方法,我把这个地方的类型改成什么啊double,哎,改成一个double就可以了,最后返回值是不是也变成double啊,这样的话,它就会去比较咱们的两个double类型的数了,对不对,它会返回一个double类型的值,OK, 老师你说这样就做到了。
不确实干嘛,没有任何毛病,这时候你们就已经突破了,从咱们一个普通的方法变成重载方法了,你们看现在我10.0 10.0的掉,你看我跑起来走啊,你看他是不是都能算出来结果你看诶确实没问题,是不是等我们来一个20.0,这样他可以比出一个大小嘛,来让他们比出大小,你看是不是20.0出来了,那咱们现在再把它改成10跟20,你们说他会走谁啊,猜一下肯定还是会走,咱们的double,就是咱们后面这个比较大小啊,理解一下为什么你看你的返回值是不是double啊,那咱们现在把返回值变成int OK, 你再跑,你看一下它会输出20.0还是20,你看看结果,诶,它是不是走了20啊,这个就是方法的重载,这两个方法名字一模一样,对不对,它的参数类型不同,诶有时候我们就通过这种方式干嘛来解决一些咱们常见的问题,在这个里面啊,你是不是调用max的方法,它是int类型,它就会调用下面这个int类型的。
啊,返回值方法,你如果调用咱们的double类型的方法,它是不是调用double类型的方法,但是我们发现名字都用的同一个,这就是方法重载,不难理解吧,各位,那说白了是不是就是一个类里面有两个方法,并且用相同的名字啊,只是他们的参数干嘛要不同,如果这两个参数一一样,那就崩了,你看着啊,我现在把这个参数放上去,这两个参数一模一样了,咱们分不清你调动谁了,如果通过参数类型不同,这样是可以做到的,GVM, 就咱们的Java那个编译器啊,它会根据方法的这个样子,方法的参数类型去判断,诶你这个到底执行了哪个,所以说名字可以相同,能不能理解方法重载这个机制啊,可以让咱们的程序干嘛更加清晰易读啊,它可以执行一些跟这个名字相关的参数,比如说现在这两个不够是吧,你再来一个,你还可以来一个什么三个数比大小行不行,只要你能够把这里面的逻辑是不是实现就可以了,比如说这个地方你再来一个1跟2跟3比较,比较出来后。
返回一个结果是不是这都是可以的,然后你现在再来一个三角形,你比如说来个30,你看它是不是去调用这第三个方法了,方法可以有无限多重名的,但是要确保什么参数类型不同,这就是咱们方法的重载,诶都能理解这个概念对不对?那咱们回到咱们PPT来看啊,它有一这样的规则,大家牢牢的记住就好了,诶在一些咱们的笔试题里面会遇到啊,你看第一个方法名称比喻相同,咱们刚才是不是说了,比如说我们刚才都叫max啊,如果你换了个名字,那个就不叫重载了,那完全就不一样的方法。第二个有一个必须不同的地方,参数列表必须不同,它的个数可以不相同,或者类型不同,或者咱们参数的排列顺序不相同等等,这都是OK的,一定要保证这些条件,这是一个必须要满足的条件,还有这上面两个,后面这两句话就不做要求,你看方法的返回值类型可以相同也可以不相同,这个就没有任何区别了,我们两个都返回in特也OK啊。
比如说咱们去试,你两个都返回int,只是你要传的不一样而已,你看我现在这个地方上面是不是返回了double啊,我也给他返回int没任何问题,把这里面改一改就可以了吗?然后这个地方他说NUMBER1是咱们的,我们给它强转为int,哎不就可以了,咱们都学过这个类型是不是可以转换呀,你看现在的话,两个方法是不是max都返回的int呀,三个都返回的int没有任何毛病,只是通过参数类型不同,它就可以去区分,到底我应该程序走起来要调用哪个方法对不对,这个是Java虚拟机去帮我们自己判断的,通过方法参数类型的不同来做的,这个地方有一句话叫做方法名称相同的时候,咱们的Java的编译器啊,它会根据调用方法的参数个数,参数类型的逐个去匹配对不对,然后来判断到底我要去用哪一个方法,如果匹配失败,则编译器报错,什么意思呢?那我现在再来一个S40,你看它没有这一个方法,咱们这个程序是不是就红了这个地方,他说找不到这个方法。
析不了它就会报错,就是这样的,所以说我们只要按照要求去做,没有任何问题,方法重载不难吧,它是一个概念,在咱们的代码里面,还有之后我们分析源码的时候,你们会经常性的,经常性的干嘛见到它基础阶段是不是还是要把这些概念先掌握啊,到了后期咱们的所有理论你们都可以发现,在Java里面都有,干嘛相应的实现,你们可以通过后期我们一些源码的分析,干嘛加深自己的印象去学习,能理解了解一下,那给你们5分钟的练习时间,给你们出道题,你们去把我们之前写的这个爱的方法给他写一些重载方法,其实我也可以带你们写啊,你看比如说可以两个数相加,对不对,也可以干嘛,也可以三个数相加,Int一个C是不是在后面添加一个int一个C就可以了,这样是不是就有三个数相加了,还可以有4个数相加,5个数相加等等等等,把它给实现好不好?多写一些方法,然后去调用一下,你就能理解到底什么叫做方法重载了,然后把我这一个概念是不是自己在纸上默默的写一遍。




习题,把下面的add方法写出一个重载方法

我觉得直接在再写一个蓝色部分,然后改动部分变成下面这个就行了,因为重载方法名一样,类型改动就行了。
public static int add(int aaaa,int bbbb,int c){return aaaa+bbbb;
public
1

OK,我们已经把方法都回顾完了,对不对?还给大家留了一个悬念 —— 值传递,对不对?那咱们现在来看一下类跟对象的关系,也从这个地方咱们切入 “创建对象” 的知识点。
那回顾一下,咱们就开始给大家聊了一下面向对象哎,中间是不是两节?大家不要忘记了,回过头来看一看。
那咱们来看一下类:我们当时说了,它是一种抽象的数据类型呀!它可以将一类事物的共同特性抽象出来,它并不代表一个具体的事物。比如说我们日常生活中的动物、植物、手机、电脑诶,这个地方都是抽象的概念啊。比如说动物里面有猫、狗、猪;植物里面有树、花、草,对不对?手机里面有苹果、安卓等等;电脑是不是有很多啊?Linux、Windows 的操作系统,这是咱们在真实生活中的样子。
那放到咱们类里面也是啊,比如说我们的 Person 类,它代表一个人,人是不是可以有很多啊?Pet 代表宠物类,是不是我们也会有很多宠物啊?Car 代表车,我们是不是也会有很多车啊?等等这些类啊,都是用来描述一系列物体的共同特征,把它抽象出来的感觉。
而对象是什么样子呢?对象是不是这个抽象类的具体实例啊?比如说张三就是一个人的实例,因为张三属于一个人嘛,对不对?张三是一个人,而张三家里的旺财呢,就是一只狗的具体实例。狗是不是也是一个抽象的概念?它有很多很多的狗,那什么是具体的狗呢?你们到时候可以自己去把它列出来,就知道了。
它具体的对象能够体现出一些具体的特性,展现出来的是具体的实例,而不是一个抽象的概念。所以说咱们回到之前来看一下,我们是不是说了这样的话:对象,它是一个具体的事物;类是抽象的,对不对?而类是对对象的一个模板。
诶,大家现在听可能有点懵了,我们赶紧去写一下代码来理解一下。首先写之前呢,我们要明白几个东西:如何去创建一个对象?来,我们这个地方刚才已经见过了,是吗?使用 new 关键字是不是来创建对象啊?
使用 new 关键字创建的时候呢,它会给我们的对象分配一些默认的值和一些空间。那咱们先不去管这个,我们先把 “创建对象” 搞定。
我们现在来到咱们的 Demo02,Demo01 是不是回顾咱们的方法?嗯,我们来一个最简单的吧,就来一个 Student。又来 Student 了,Student 呢,大家知道它是一个什么?是不是一个学生类呀?学生类。
然后大家现在跟我养成一个好习惯:我们不要在每一个类里面都去加上一个 main 方法了,这样子是不好的。因为这个类里面不应该有 main 方法啊,它就是一个单纯的类;而咱们一个程序只有一个主启动类,所以说我们在这个地方可以定义一个大的启动类或者测试类。比如说我把它叫做 Application(A-P-P-L-I-C-A-T-I-O-N),就是咱们应用的意思啊,来定义。
一个项目要规范:一个项目应该只存在一个 main 方法,一个 main 方法就够了,不要写那么多了。我们就放在这个 Application 里面,这是我们的总的测试类。来,psvm(快速生成 main 方法),OK,这是我们唯一的一个入口啊。
那咱们把它列到一边,为了方便咱们随时可以测试,这是我给大家讲课、代课养成的好习惯。那咱们来看一下,现在学生类在这个地方,我们都会测试,就去这边写,能明白我的分工了吧?
那咱们来写一下最简单的学生类。类,好,定义类里面只有两个东西:一个叫做属性,也就是咱们的一个一个的字段,大家可以把它理解为字段。比如说,嗯,给大家写一下:String name 诶,这就是一个字段,对不对?然后 int age 哎,这是咱们的姓名跟年龄哎,咱们就有属性了。
然后属性完了,还有方法。方法,一个类里面只可能存在这两个东西,就是无论再厉害的类、再厉害的人,他写一个类,里面只有属性跟方法,他没有其他东西,就是属性、方法,你们记住就好了。
那比如说我们写:public void study ()(S-T-U-D-Y),嗯,这是一个方法,对不对?我们输出一个:“学生在学习”。学生,学生在学习。那这个学生可能是变化的,是不是根据这个 name 来的?所以说我们这个 “学生” 也可以指代一下 “谁在学习呢”?我们可以把 this 用上 ——this,this,this 代表当前这个类,this.name 就是自己的这个名字。
你看它是不是指向上去了?你点它就跳上去了,可以点的,你看一点就跳上去了。这个 this 代表当前这个类,就相当于 “这个学生在学习”,我们等会可以给它赋值啊。
OK,一个简单的类,咱们就定义出来了,就跟 Hello World 一样,我们先把这个写出来啊。这是咱们最简单的一个类:一个类里面有属性和方法。
那我们现在要去把这个类干嘛?把它实例化出来,变成一个对象。来,这是一个类,我们说了类是抽象的,来理解这句话:抽象的,抽象的,它需要干嘛?需要实例化。
什么意思呢?我们需要把这个抽象的类给它具体地实例化出来。来看一下:类是抽象的,我们这个类,对不对?对象是实例化的。那我们来看一下该怎么去实例化呢?我们通过一个关键词叫做 new——new Student ()。
你看我们 new Student () 之后,诶,这个对象干嘛?它就被实例化了,就这么简单。实例化之后它会产生一个返回结果,说句话啊:类实例化后会返回一个自己的对象。
什么意思呢?我们常常说了,类是抽象的,而对象是一个具体的实例,对不对?所以说这个地方的对象,就是所谓的这个 Student 变量,是咱们的对象的名字嘛。这个对象就是 Student 类的具体实例。
大家是不是听着有点懵啊?没关系,理解啊。比如说这个地方 Student 是不是一个总的类?是个学生吧?学生可不可能是小明?同志们现在理解吧?是不是小明是一个具体的人啊?诶,那我是不是可能还有小红啊?你看这都是 Student 类的对象,但是我是不是产生了两个不一样的对象?有一个叫小明,有一个叫小红,能不能理解了?
同一个类,它下面可以产生不同的对象,但是这些对象都有共同的特征:他们两个肯定都会有 name、age 以及 study () 方法,我们可以试一下。
比如说我们什么都不干的时候,我们先输出一下这个小明点 name—— 来,比如说我们写:小明.name,你看看能不能输出出来东西啊?我们现在是不是这个 name 没赋任何值啊?它在这个地方是空的,我们这边也没赋值哎,所以说它是 null。
回看我 PPT 的话,咱们在使用 new 关键字创建对象的时候呢,除了分配一个内存空间(咱们在基础课就学了),那还会干嘛?给创建好的对象进行默认的初始化,以及对类中的构造器进行调用。
后面这句话听不懂,但是第一个是不是能听懂啊?进行默认的初始化。比如说咱们这个地方的 name 默认是 null,就是我们没有赋值之前,它就是 null,null 是空的;然后这个 age 默认肯定是 0,我们也可以把这个 0 打印一下:小明.age,来看一下是不是 0。
它会有一个默认值,就是你什么都不用赋值,在这个属性里面,因为它是个模板嘛,这个模板肯定没有具体的值。如果你在这个地方写成 name = "小明",你在这个地方写哎,那它还是一个模板吗?同志们!学生的名字不应该被写死吧?那样所有人都叫小明了,肯定是不行的,它是一个抽象的概念,再理解一下。
那咱们来看一下,这边现在定义了两个学生,我给他们赋值了,开始了。比如说小明:先来个小明.name = "小明" 哎,现在我是不是把 “小明” 这个值赋给他了?你看小明现在就有值了,来我们输出一下它的 name,你看下它是不是就是 “小明” 了?哎,跟我们正常的赋值是一模一样的,把 “小明” 赋值给咱们这个对象,对不对?
那小明有名字了,那小明可能也有 age,比如说小明今年多少岁了?三岁了,可以吧?那小明有了,那你看一下,这是小明这个对象吧?小红这个对象有值吗?那咱们来输出一下,我们把这个小红输出一下,写 xh 吧,不然的话感觉太像了:xh.name、xh.age。
你们看一下我们现在是不是只给小明赋值了?小红依旧是 Student 类的对象,它依旧是空的,因为我们的小红没赋任何值,但是小明已经成功被附上值了。那你要给小红赋值也一样,直接把这个拿过来就好了:来,比如说咱们这个地方是小红.name = "小红",然后下面的 age 也设为 3,嗯,这个地方来个小红,他们两个都三岁,是一对好朋友,对不对?
那咱们来看一下,现在小明跟小红是不是都被赋值了?可以理解,对不对?你现在能不能理解了?再回过头来看一下:这个类是不是一个抽象的模板啊?而我们通过这个类,通过 new 关键词可以创建不一样的、具体的实例。
你看虽然后面都是 new 了一个 Student,但是 new 完之后它是不是就变成一个具体的实例了?相当于咱们这个世界,如果你们要把这个世界想象成一个程序的话,那所有人都应该是 “人” 的模板,能不能理解?都是一个 Person(P-E-R-S-O-N),比如说都是人类,或者叫 Person,Person 更像 “人”,对不对?都是这样,Person。
一个 Person 类,它是不是包含了人的所有共性啊?比如说每个人都会有自己的身高、体重、年龄嘛,对不对?身高,来思考一下,体重、年龄,对不对?这些东西大家可能都会存在。
那么其实全世界的人,你要把它抽象起来,是不是都可以叫 Person 啊?然后你要给它具体的属性,比如说我这个情况,他可能还会有更多的属性啊,比如说咱们的国家、国籍,对不对?然后他的祖籍啊,然后乱七八糟的属性,然后通过这一系列的属性来确定 “唯一的你” 这一个人,然后就能理解了。
所以说有一句话:为什么说学程序好呢?我们来思考一下,学程序好,学程序好啊!来,学程序好的一个原因就是:很多人为什么说学编程好啊?它并不是说能挣更多的钱,我认为它是可以对世界进行更好的建模 —— 就是你可以让这个世界变得模块化、抽象化,以至于你能去理解这个世界,而不是过很俗世的生活,对不对?
但是这样也可能造成大家宅,是不是?就是写代码还是尽量不要宅哎,老师就不是一个很宅的人啊,我们也会经常出去玩玩,去大学做做讲座,对不对?这就是我们的生活啊。
所以说希望大家在学习之外啊,有一些其他爱好哎,多弹弹吉他,对不对?学习音乐哎,对不对?陶冶下情操;旅游,是不是放松一下视野?等等;是不是还可以学学英语,出国啊?这样都是比较好的。
OK,关于类跟对象的创建,我就说到这。在这一节课学完,一定要把 “类” 跟 “new 关键词创建出来的对象” 给我搞清楚!然后回到咱们之前说过的一句话:面向对象编程的本质就是 “以类的方式组织代码,以对象的形式封装数据”,对不对?
类是不是用来组织代码的?而每一个具体的对象是不是封装每一个具体的数据诶?就是这么回事啊!认真地理解,理解不透,就把这些视频多看几遍,然后多去思考,思考透了再往下看,可以吧?然后把这个地方给停一下。


我们刚才已经学会了如何使用 new 关键字创建对象,对不对?然后也说了一句话:使用 new 关键字创建对象的时候,除了分配空间以外,还会给它进行默认的初始化。
那么到现在为止,这句话大家是理解了,但是后面是不是还跟了个 “以及” 啊?那咱们来看一下 —— 以及对类中的构造器进行调用。构造器是不是大家不认识了?然后看下面这段红字,我说的是:构造器必须要掌握,可以想想它的重要性啊!
构造器也叫构造方法,创建对象时是必须要调用的。那咱们来看一下,嗯,当然我先把这一段代码移到当前这个项目的最下面,哎,这样的话大家以后回看这些代码就非常方便了,就是每一个类的测试代码都在它的最下面。OK,把它粘过来就可以了。
那咱们来看,现在依旧保留一个 main 方法,咱们去写一些其他的属性。嗯,我们来写一下:在咱们的包下面,Demo02,我们来写一个最简单的构造器。比如说咱们来一个 Person 类,我们现在写了一个人的类,对不对?
那咱们还是把代码分开写。然后我们要 new 这个 Person 对象的时候,你看它会调用一个方法。现在虽然说我们这个类里面什么都没写,对不对?但是它依旧能 new 出来对象,这说明存在一个这样的方法,大家能理解吗?就是存在一个空的 Person 构造方法。
写到这里的话,大概就是这个样子:public Person (),长这个样子的一个东西,你看对不对?就是一个空的构造器。但是我们虽然没写,它也能被调用出来,这是为什么?所以说肯定这里面有一些默认的东西啊。
那咱们什么都不管,我们来把它输出一下。来,我们运行这个项目,跟着我看!我们这个类目前是什么都没有的,但是你看这边是不是依旧可以用啊?我们把这个注释写上:哎呦,这个地方叫做 “实例化一个对象”,哎,只用 new 关键词,实例化了一个对象。
那你要知道这个对象是怎么来的,对不对?那为什么它能凭空 new 出来呢?我们去看一下它生成的 class 文件啊。我们现在这个地方是 java 文件,它编译之后会生成 class 文件,来,我们去打开这个 class 文件看一下。
我们用 IDEA 打开,嗯,肯定很多人问 IDEA 怎么看?是不是我之前的基础课已经教过了?那咱们来看一下:我们打开这个项目结构,然后在 Models 下面,选择加上一个根目录,把咱们的 out 目录加回来,点击 OK、Apply。
那咱们现在可以看到,基础语法模块里是不是有 out 目录啊?这个 out 目录就是咱们的输出目录,它会生成对应的 class 文件。你看,跟我们源码的目录结构是一模一样的,只是里面的文件变成了 class 文件。
那咱们找到刚才写的这个 Person 类,大家来看一下是不是有区别?这是咱们的 java 文件,来对比一下 —— 它是不是默认帮我们加了一个方法呀?发现了没有?而且这个方法没有返回值,这是第一个要点;第二个要点,它这个方法的名字是不是跟类名相同啊?
其实这就是构造器!然后可以得出第一个结论:哎,一个类即使什么都不写,它也会存在一个构造器,对不对?它也会存在一个方法,就是长这个样子的方法,这个方法就是构造方法。
那咱们来看一下构造方法的定义:首先构造方法有两个特点,第一个必须和类的名字相同,第二个必须没有返回值(连 void 都不能写)。那是不是就像刚才那样子?它其实非常简单。
那咱们来手动写一下:刚才是默认生成的,咱们可以显式地定义一个构造器,按照要求来 —— 是不是首先得有一个 public 的方法,其次这个方法的名字必须跟类名相同,然后 OK,这样就是一个构造方法,它没有返回值。
看,非常简单!一个与类名相同、并且没有返回值的 public 方法,对不对?这就是构造器,无参构造(没有参数的构造器),大家可以理解一下。
那肯定有很多小伙伴问:这个无参构造器能干什么?对不对?比如说,最简单的,它可以给我们初始化一些信息。咱们知道 Person 的 name 初始化值应该是什么?我们可以来输出一下:你看,比如 person.name,然后我们把它输出一下。
你看一下这个 person.name,大家现在都知道它应该是什么?它是不是 null 啊?就是因为我们没有给它赋任何值。来,这是一个 null 值。然后我们给 Person 写了构造器之后,你看它默认是空构造器,第一个作用就是可以初始化对象的初始值,你们可以把它叫做初始值。
一般做游戏开发的话,是不是就会给对象赋一些初始值?默认的大小、初始状态等等。那咱们来看一下怎么赋值呢?就是在 new 对象的时候,它会调用这个构造方法,等会咱们可以 debug 来看一下。
我们可以在构造器里写 this.name,这个 this.name 代表的是当前对象的 name 属性,还是那句话。然后等于什么呢?等于,比如说写一个最简单的 ——“秦江”。OK,那现在我们再输出这个 name,它就不是 null 了,它会显示 “秦江”。
你看这个地方,等会再 debug 一下,大家就明白了。构造器是一个非常重要的东西!那咱们来看一下,是不是现在结果输出了 “秦江”?没有任何问题吧?
那咱们来打一下 debug:我们在这个地方打个断点,然后再来运行一下。你看,我们以调试的方式看一下它的执行流程 ——OK,程序到这个地方停住了,我们让它往下走一步。
哎,你看它从这个位置是不是跳到了构造器的地方?然后再往下走,哎,它执行了 this.name = null(默认值),但是走完 this.name = "秦江" 这句话之后,name 是不是就等于 “秦江” 了?然后构造器执行完毕,返回。
OK,构造器走完了,对不对?构造器走完了,这句话才会生成对象!然后再往下走,输出咱们的 name——p.name 等于 “秦江”,所以说咱们才得到了这个值啊。
那大家可以理解这句话了:现在知道构造器是干嘛的了吧?对不对?来,我来给你们总结一下构造器,其实核心作用就两个:
第一个作用:使用 new 关键字创建对象时,必须要有构造器。这个如果没有构造器的话,代码这边就会报错啊。你看现在我们默认有一个无参构造器,我们显式写出来也可以。
那有一种情况可以把无参构造器 “干掉”—— 等会我们来看,就是定义有参构造器。上面是无参构造(没有参数的构造器),下面还有有参构造器。
那说白了,我跟你们说:在 new 一个对象的时候,本质上是在调用构造器!就是如果没有构造器,肯定没法创建对象。这是无参构造的情况,咱们来写个有参的。
现在写有参构造器:我们这个地方就不要写 this.name = "秦江" 了,我们可以加一个 String name 参数,给它来个参数,对不对?然后这样写 ——this.name = name。
来看一下区别:这里有个 this 关键字,首先这个 name(右边的)是不是代表参数传递进来的内容?而 this.name(左边的)代表对象本身的 name 属性,这两个东西是有区别的。
大家要知道,this 指代当前类的对象,而后面的 name 是传进来的参数。那咱们现在就有了有参构造器,你看 —— 一旦定义了有参构造器,无参构造器就必须显式定义,否则就无法使用无参的方式创建对象。
我们可以来试一下:咱们现在用 new Person () 创建对象,用的是无参构造器(没有传参数),对不对?那我们现在定义了一个有参构造器,把无参构造器删掉,诶,发现这边报错了,看到了吗?这个 Person 对象的创建就报错了。
你跑一下这个程序,看它会怎么样 —— 它提示 “无法将类的构造器应用给指定的类型”,因为找不到无参构造器,对不对?
所以说,一旦定义了有参构造器,你还想用无参构造器创建对象的话,就必须显式地定义一个无参构造器。所以我们正常情况下,只要定义了有参构造器,就默认把无参构造器留空就好了,它什么都不用干。
咱们刚才这个类,生成的 class 文件里就是这样的空无参构造器,你不用去做额外的事情。OK,像这样子的话,咱们就可以用两种方式创建对象了:
我们用无参构造器创建的对象,肯定是没有初始化 name 的,因为无参构造里什么都没写,name 等于 null;那假设我们现在传一个参数,比如说传一个 “狂神”,我传了一个 “狂神”,对不对?
传了一个 “狂神” 之后,你们说它会走哪个构造方法?它肯定也是调用方法 —— 通过 new 关键词调用构造方法,你们可以这样理解。那 new Person ("狂神") 的时候,你看它会匹配带参数的构造器,肯定会走下面这个有参构造。
那咱们来打个断点(debug),看一下 —— 走一个断点,一定要认真看啊,这个地方非常重要!我们往下走,你看这个地方是不是直接跳到了有参构造器啊?它并没有走无参构造,会自动根据参数来判断,因为方法是可以重载的。
OK,那咱们现在有值了,输出 name 等于 “狂神”,这个地方是没有任何问题的,对不对?要理解这样一个概念啊。
嗯,要总结的话:第一个,使用 new 关键词的本质是调用构造器;第二个,构造器一般用来初始化对象的值,这就是它的两个核心作用。初始化值,就是这样一个概念,把这个东西认认真真记住。
可以说,构造器的知识点就这么多:下面这个有参构造器的写法叫做重载,上面这个是默认的无参构造器,有参、无参就是这么来的。
然后记住一个快捷键:Alt 加 Insert(Alt+Insert),来试一下 ——Alt 加 Insert,看着,它会生成构造器。Alt+Insert,看到第一个是不是有个 “Generate”(生成)?有个 “Constructor”,Constructor 就是构造器的意思。
那点一下它,哎,你发现有个 name 属性,点 OK 它会自动帮你生成有参构造器,对不对?那怎么生成无参呢?Alt+Insert→Constructor,咱们可以看到下面有个 “Select None”(什么都不选),点它就是无参构造器。
你看,有参、无参都能一键生成了!所以说 IDEA 给了我们很多快捷键,当我们有非常多属性的时候(比如说再加个 age),那现在我们又可以定义多个有参构造器,我们可以重载很多个,大家可以去理解。
你看这样的话,下面的有参构造器就有两个了,你调用的时候传两个参数,它是不是就会调用对应的构造方法?哎,能不能理解这个逻辑?哎,所以说构造器并不是一个很难的东西啊。
那咱们还是把代码粘回来,这是咱们的笔记。那咱们现在对构造器已经有了了解,也知道如果不写构造器,它会有默认的无参构造器,这个东西一定要注意啊!
然后我给大家把注意点都写在下面的总结里,嗯,我们先把这个测试代码拿过来,对不对?要这样的话我们的笔记就会非常清楚了。还是往下,我们来写总结 —— 每一章学完,把面向对象的笔记都写在下面,因为东西还是比较多。
来回顾一下构造器:构造器是一个什么样的存在呢?它首先有两个特点,要让它合法存在的话:第一,方法名和类名相同,这个方法名必须和类名相同,对不对?第二,没有返回值,连 void 都不能写,这是它的两个核心特点。
然后它的作用,刚才其实已经说了:第一个,new 关键词创建对象时,一定会调用构造器,new 的本质就是调用构造器(也就是构造方法);如果构造方法不存在,那肯定就创建不了对象。
第二个作用,初始化对象的值,这是我们要做的核心事情。然后还有一个最重要的注意点(也不算作用):就是定义了有参构造器之后,如果想使用无参构造器创建对象,我们必须显式地定义一个无参构造器。
诶,这个是需要重点注意的点!因为如果你定义了有参构造器,还调用无参构造器创建对象,它就会找不到无参构造器,从而报错。这是它唯一的重点,大家把这些记住就好了。
然后再记住这节课的快捷键:Alt 加 Insert(Alt+Insert),我们以后会大量用到它。咱们刚才看到,生成构造器其实只是它的一个功能,这个快捷键还有很多其他用法。
然后还有一个注意点:就是 this 关键字 ——this.xxx 代表当前类的属性,而后面等于的这个值,一般是参数传进来的值。OK,这就是咱们构造器相关的内容啊!
大家一定要认真理解,理解完再往下学,因为面向对象的每一章都有新东西,希望大家把每一章都吸收完毕,总结到自己的博客里,理解透彻之后,再持续往后学。OK 吧?构造器必须要掌握,这还是重点!

那咱们继续来看啊!为了让大家更好地理解 Java 中对象是如何 new 出来的,给大家做一波简单的内存分析。当然,这个地方主要是为了让大家简单理解内存概念,并不是真正的内存图 —— 真正的内存图比这个复杂得多,还有类加载、Class 对象这些内容,我们会在后面的反射章节再给大家讲。这个地方大家先听一下,哎,重点是理解就好!
嗯,咱们来创建一个类,从头开始说:比如说咱们建一个 Demo03,就专门写一个类叫做 Pet(宠物类),我们写简单一点。这个类假设只有几个属性:比如宠物的名字(name)、宠物的年龄(age),诶,这个地方。然后宠物一般还会干嘛?还会叫,对不对?我们再写一个方法 —— 比如说 public void shout (),shout 代表 “叫”,对不对?
那咱们来看一下,现在我们写了一些内容:name、age 两个属性,还有一个 shout () 方法,方法里输出 “叫了一声”。好了,咱们这个类就写到这里,就是一个简单的类。咱们重点还是来看一下这个类的调用逻辑,对不对?
我们要使用这个 Pet 类,肯定要调用它。刚刚讲过,这个类里默认存在一个我们看不到的东西 —— 是不是叫无参构造器?我刚才说了,无参构造器是默认就有的,你们不写的话,它默认存在;但如果写了有参构造器,无参构造器就没了。
那咱们这个地方来实操一下:首先要使用 Pet 类,第一步是干嘛?来,咱们 new 出第一个宠物对象,比如说把它叫做 dog(狗),可以吧?然后给它的名字赋值 ——dog.name = ,当然这个地方要把属性设为 public,下面的 age 也设为 public,因为 public 的权限比较高(后续再给大家讲用 get/set 方法调用的方式)。
来,dog.name = "旺财",这是咱们的小狗 “旺财”;然后它还有年龄 ——dog.age = 3 岁。除了这个,我们还能 new 其他动物,对不对?那咱们先写到这,再来调用 dog.shout () 方法。OK,那咱们来看一下,现在做的这些操作,到底对应内存里的哪些行为?
咱们先明确:程序运行时,首先会进入 main 方法,然后 new 这个 Pet 对象,调用无参构造器,生成一个对象。这个对象一开始没有名字,对不对?然后我们给它的 name 赋值、给 age 赋值,还调用了它的 shout () 方法,大概是这样的逻辑 —— 之前通过 debug 是不是也能看到这个执行流程?
那在内存里,这些操作具体是什么样的呢?我们一点一点剖析:
首先,程序运行要加载代码模板。第一步,大家可以简单理解(但不要刻板理解):它会把 Application 这个类的代码信息加载进来。这个类里有什么?有个 main 方法,还有一些字符串常量(字符串会存到常量池里),比如 main 方法里的 “旺财” 就是常量;而 age 的 “3” 是 int 类型数字,不属于常量。
main 方法执行时,会被压入栈底 —— 我们讲方法的时候说过,main 方法在栈的最底部,当 main 方法执行结束被弹出栈时,程序基本就结束了,对不对?
main 方法执行到第一步:new Pet () 创建对象。我们打个 debug 断点,边看边分析 ——new 这个 Pet 对象时,是不是会先加载 Pet 类?所以第二步,会把 Pet 类加载进来:Pet 类有自己的属性(name、age)和方法(shout ()),Pet 类也有常量池,比如 shout () 方法里输出的 “叫了一声” 是字符串(不过我们这里是输出语句,为了方便理解,先忽略这个常量)。
Pet 类加载完成后,这个模板就有了:new 对象时,Pet 类的属性会有默认值 ——name 默认是 null,age 默认是 0,对不对?所以这个时候对象还没有具体的值,能理解吧?因为都是默认值(String 类型默认 null,int 类型默认 0)。
模板加载进来后,就要通过模板生成具体的对象了:当执行 Pet dog = new Pet () 时,栈里会生成一个变量名 “dog”,哎,dog 是放在栈里的;而真正 new 出来的 Pet 对象,是在堆里生成的 —— 这里可能大家一下子觉得绕,先把逻辑理清楚:栈里的是引用变量名,堆里的是真实对象。
记住这个核心:引用变量(比如 dog)在栈里,真正的对象在堆里。堆里的 Pet 对象我们可以简单给个内存地址,比如 0x0001,栈里的 dog 就指向这个地址,理解一下?
此时堆里的 Pet 对象,默认 name=null、age=0,还有 shout () 方法(方法会关联到 Pet 类模板里的 shout ())。这一步 new Pet () 就走完了,其实调用无参构造器时,就是做了这些事。
做完 new 之后,我们执行 dog.name = "旺财"—— 相当于把常量池里的 “旺财” 赋值给堆里对象的 name 属性,于是 name 才有了值;接着 dog.age = 3,把 3 赋值给 age 属性;然后调用 dog.shout (),其实是调用了 Pet 类里的 shout () 方法(没有传参)。
哎,这样大家就理解了:执行到这一步时,所有值都赋完了,堆里的对象就有了 “旺财” 和 3 这些具体值,然后我们就能使用这个对象了 —— 使用时,它就有了旺财(name)和 3(age),诶,大家现在简单理解一下,对不对?
那咱们再做个拓展:我们已经 new 了一个 dog,再来 new 一个 cat(猫)——Pet cat = new Pet (),现在有只小猫了,对不对?这个猫在内存里是怎么存在的?
其实,栈里会新增一个引用变量名 “cat”,它也是一个引用,指向堆里新的 Pet 对象:new Pet () 时,堆里会生成第二个 Pet 对象,地址比如 0x0002,这个对象的 name 默认 null、age 默认 0,cat 指向这个地址。这两个对象是完全不一样的,你可以理解吧?
现在知道为什么说 “类是模板,new 出来的对象是具体实例” 了吧?引用变量本身在栈里,真正指向的是堆中的具体对象 —— 只是我们通过栈里的变量名给它起了个名字,本质上它们是关联的。
当然,以后学封装、继承、多态时,你会发现同一个类型的变量,可能有不同的状态,不过这都是后话。大家现在重点先理解这些基础内容。
另外,还可以提一下 static(静态)关键字:我们之前学的 static 修饰的内容,会和类一起加载(一进程序就加载),所以所有对象都能直接调用它,这是 static 的一个好处。现在大家可能有点迷惑,自己画几张图,认真理解堆、栈、方法区的关系。
简单总结内存区域:咱们说的 “栈” 存方法和变量引用,“堆” 存具体创建的对象,堆里还有个特殊区域叫 “方法区”(方法区也属于堆)—— 方法区存放类模板、常量池等。具体高深的内容我们以后再讲,这个地方重点理解 “创建对象的内存逻辑” 就好。
现在知道为什么都是 new Pet,却能产生不同的对象了吧?因为堆里是不同的内存区域,地址不同,栈里的引用变量名也不同,所以看起来是 “不同的对象”。很多初学者会问:“我都是 new Pet,为什么出来的不一样?” 一画完这个图,大家瞬间就明白了,现在能理解了吧?
哎,现在下去什么都不要干,把这个内存图自己画好多遍,直到理解为止,好不好?直到大家自己能彻底理解。OK,咱们的内存图简单分析就分享到这了,不要绕进去了!


OK,各位同学!那咱们把这些内容总结一下 —— 因为面向对象的知识点,还是给大家放慢一点进度,对不对?
咱们来回顾一下学过的内容:首先,什么是类和对象?这是大家必须要搞清楚的核心概念。现在咱们都知道了:类是一个模板,对不对?大家认真回顾一下;那对象又是什么?是一个具体的实例。诶,上节课给大家画了内存图,大家应该也都理解得差不多了,这个知识点非常非常重要!
类是抽象的,对不对?对象则是具体的,这是类和对象的核心区别。
接下来是方法:方法的定义和调用,这个知识点应该不会再出问题了吧?如果还有问题,记得回看之前的内容,认真理解一下。
咱们重点说一下对象的引用 —— 对象的引用是什么意思?这个概念大家可能还不太好理解,我们先把 “引用类型” 这个概念搞清楚。引用类型对应的是什么?是基本类型,对不对?
基本类型咱们之前打基础的时候就讲过,总共有多少个?是不是八大基本类型?在 Java 中,除了这八大基本类型之外的所有类型,都可以叫做引用类型。引用类型说白了就是:对象是通过引用来操作的(这句话很重要,要记牢)。
这个引用,就是我们刚才画内存图时,栈里面的那个东西,对不对?栈里的引用最终指向谁?指向堆里面的真实对象。所以说,这是一个引用关系 —— 说白了,引用就是指向对象的一个地址,哎,能理解吧?
栈里的引用会指向堆中的对象,我们实际操作的是栈里的简单引用,真正的对象数据在堆里。
除了引用,咱们还要说对象的属性:属性也常被叫做字段(英文是 field),或者成员变量 —— 大家以后在书中会看到不同的叫法,但本质上都是属性,因为类里面只有属性和方法这两类内容,对不对?
属性有个非常重要的特点:默认初始化。也就是说,你定义了属性之后,哪怕不对它初始化,它也会有默认值。咱们回顾一下默认值的规则:
- 数字类型(整数 / 浮点数)默认是 0 或者 0.0;
- char 类型默认是 \u0000;
- boolean 类型默认是 false(如果什么都不赋值的话);
- 引用类型(除基本类型外的所有类型)默认都是 null。
把这个规则认真记住!OK,属性的定义就不多说了,遵循 Java 的万能公式:修饰符 + 属性类型 + 属性名 = 属性值,只要是赋值操作,基本都是这个格式。
除了属性,还有方法 —— 方法的定义和调用之前都讲过了,如果非要强调一点,就是要避免方法出现死循环,方法的定义格式必须掌握,这里就不重点说了。
咱们重点回顾对象的创建和使用,这个知识点特别特别重要:
- 创建对象必须使用 new 关键字,而且创建对象还需要构造器 —— 没有构造器的话,肯定是创建不了对象的;
- 对象该怎么使用?先看对象的属性:举个最简单的例子,代码里 new 一个 Person 对象(Person person = new Person ()),这个对象肯定有构造方法,会返回一个 Person 实例。给这个对象起个名字,比如 “狂神”(Person 狂神 = new Person ()),这样 “狂神” 这个对象就创建好了。要访问对象的属性,比如 name,就用 “狂神.name”,这样就能调用到对象的属性了;
- 对象的方法该怎么调用?也是通过点(.)操作符:比如调用 “狂神” 的 sleep(睡觉)方法,就是 “狂神.sleep ()”,直接以括号形式调用就行。
调用对象的属性和方法,都是通过点(.)操作符,在 IDEA 里这个操作符还会有代码提示,非常重要!
大家可以这样理解:类里面只有两个核心内容 —— 静态的属性(状态)和动态的行为,说白了就是属性和方法。只要记住 “类里只有属性和方法” 就 OK 了。
简单回顾完这些内容,学到这里,大家一定要自己认真做总结,之前的基础必须全部掌握!到这里,我们终于搞清楚了什么是类、什么是对象。接下来,我们就要学习 Java 面向对象的三大特征 —— 我说过,是不是封装、继承以及多态?
这个知识点是重点,但不是难点:因为人类的思维本身就偏向面向对象,我们习惯从宏观角度考虑问题,所以这些概念理解起来并不难。大家一定要把基础打扎实,再往后面学 —— 不要在这个阶段基础不牢,还想着赶进度,这样会欠越来越多的 “基础债”,到后面就学不动了,哎,甚至会想放弃。这也是很多自学的人半途而废的原因。

OK,那咱们这节课来聊一下面向对象三大特性之一 —— 封装。
“封装” 这两个字,其实就是大家字面上能看到的意思:把一个东西封装起来、装到箱子里,只留一个口,只有通过这个口才能拿到里面的东西,对不对?
举个例子:我们看电视的时候,完全没必要去了解电视机内部的构造,也没必要碰里面的显像管,对不对?电视机厂家为了方便我们使用,会把内部非常复杂的细节全部封装起来,只给我们暴露一些简单的接口 —— 比如电源开关、换台键,这样用户就能正常使用电视了,不需要了解产品内部的所有细节,这就是封装。
说白了,封装的核心就是 “该漏的漏,该藏的藏”:我们要把该暴露给用户的内容暴露出来,但程序的大部分细节都应该藏起来。这里有一句专业的话要记住 ——“高内聚,低耦合”,这是程序开发中必须追求的核心思想,无论是什么系统,都要朝着这个方向设计,这是大家第一次接触这个概念,一定要牢牢记住,不管是现在学面向对象,还是未来写项目,它都是核心思想。
那什么是高内聚?高内聚就是类的内部数据细节由自己完成,不允许外部干涉。比如银行里的总金额,应该由银行内部人员管理,不应该让所有人都能操作,每个人只能操作自己的账户,就是这个道理。
低耦合则是尽量只暴露少量的方法给外部使用。还是以银行为例:普通用户只能操作自己的银行卡取钱,却不能随意把钱借给别人,能调用的方法是有限的,这就是低耦合的思想。
对于代码来说,封装的实现其实很简单。可能有人听不懂抽象的概念,那咱们结合代码 demo 来理解 —— 还是以 Student(学生)类为例,不给大家写代码的话,大家可能理解不了,一旦写出来就很简单了。
学生类作为一个类,会有属性和方法(行为):比如属性有名字(name)、学号(id)、性别(sex),方法比如睡觉(sleep)。封装大多时候是针对属性的,对方法的封装用得比较少,重点在属性。
这里要记住两个核心关键字:private 和 public(它们是对应的)。之前我们定义属性时用 public,所有人都能直接操作这个属性;现在换成 private,外部就不能直接操作了 —— 比如把 name、id、sex 都设为 private:
- private String name;
- private int id;
- private char sex; // 比如赋值为 ' 男' 或 ' 女'
方法则可以正常编写,不用做太多封装。
当我们在 main 方法里创建 Student 对象时(Student s1 = new Student ()),如果属性是 public,我们可以直接通过 s1.name 操作;但换成 private 后,再写 s1.name 就会爆红,提示 “name has a private access”(name 是私有属性),无法直接调用 —— 这就是面向对象封装要做的改变,核心就是给属性加 private 关键字。
那外部想操作私有属性该怎么办?这就要用到 get/set 方法:给私有属性提供可以操作它的公共方法。
- get 方法:顾名思义,是用来获取数据 / 属性的。比如获取名字的方法:public String getName () {return this.name;}这样外部就可以通过 s1.getName () 获取 name 属性,而不是直接操作 name。
- set 方法:是用来给数据设置值的。比如设置名字的方法:public void setName (String name) {this.name = name;}外部可以通过 s1.setName ("秦江") 给 name 赋值,值会通过参数传递,最终赋给对象的 name 属性。
调用时,我们没有直接操作 name 属性,而是通过 set 方法设置值、get 方法获取值,对不对?
这里有几个注意事项:
- 属性一般都用 private 修饰;
- get/set 方法的命名遵循驼峰命名规则,比如 getName、setName(属性名首字母大写);
- IDEA 中有快捷方式:alt + insert(alt + 插入),可以自动为属性生成 get/set 方法 —— 选中要生成的属性,点击 OK,就能自动生成,平时使用频率很高。
可能有小伙伴觉得封装 “没什么用”,但其实封装的核心价值在于安全性控制。比如我们给 Student 类加一个 private int age(年龄)属性,人的年龄不可能无限大,也不可能为负数,这时候就可以在 setAge 方法里做安全性检查:public void setAge (int age) {// 合法区间:0 ≤ 年龄 ≤ 120if (age > 120 || age < 0) {this.age = 3; // 不合法则默认设为 3 岁} else {this.age = age; // 合法则赋值为输入值}}
如果外部调用 s1.setAge (999),程序会自动把年龄设为 3 岁;调用 s1.setAge (70),则正常赋值为 70 岁;调用 s1.setAge (-1),也会设为 3 岁 —— 通过封装,我们可以规避不合法的数据,让程序更安全,避免系统被破坏,这就是封装的重要作用。
封装的核心意义
- 提高程序的安全性,保护数据:避免外部随意修改核心数据,通过方法做合法性校验;
- 隐藏代码的实现细节:用户只需要调用暴露的方法,不需要知道内部的逻辑(比如设置年龄时的校验规则);
- 统一接口:所有属性的操作都通过 get/set 方法,形成规范的调用接口;
- 提高系统的可维护性:修改内部逻辑(比如调整年龄的合法区间)时,不需要改动外部调用的代码,便于维护。
良好的封装便于修改内部代码,提升程序的可维护性,大家只需要记住核心:将属性隐藏(private),通过公共的接口方法(get/set)来操作,必要时在方法中做安全性验证。
最后顺带回顾一下方法的重载:比如 System.out.println () 能输出任何类型的数据,就是因为它提供了多个同名但参数列表不同的方法(参数是 char、double、String、Object 等),这就是重载 —— 方法名相同,参数列表(个数、类型、顺序)不同,就是不同的方法。
虽然重载和封装无关,但也是面向对象中常用的特性,构造器中使用重载的场景会更多。
重点还是希望大家理解封装的思想:不用想着一节课就完全掌握,封装会贯穿在每一段代码中,慢慢写、慢慢练,就能逐渐接受并熟练使用。要理解 “属性私有化 + get/set 方法操作” 的核心,就是掌握了封装的关键。


这节课来聊聊面向对象的第二个特性,叫做继承。 这个继承呢,其实跟咱们生活中的是一样的。 现实世界中的继承是无处不在的。 哎,就比如说最简单的动物, 对不对? 动物咱们知道它是一个很高的分类了吧, 就在这里面。 因为动物下面还分为很多类别啊, 比如说哺乳动物、 爬行动物等等。 然后哺乳动物是不是还要再往下细分啊? 就是一层一层的分解。 那咱们之前学的封装, 它是不是对一个对象的封装、 对一个类的封装? 哎,比如说类它都有什么东西? 是不是有属性,以及什么的? 还有它的一些方法诶, 重点是这两个东西。 那么属性和方法构成了一个类,那类 如果太多了, 是不是也得进行抽象啊? 就是你要想办法对这些类进行抽象。 哎,比如说国家,对不对? 这么多人,他为什么叫美国人? 他所以说这个人,他其实“人”是一个很广泛的概念, 下面还通过这些一些的国家或者地区、 或者皮肤色种,来去判断出来了更加细分的一些类啊。 哎,就是这样的。 那这个继承呢,其实也差不多。 继承的本质,它是对一批类进行抽象, 相当于把类再次抽象, 从而可以让咱们的代码去慢慢实现世界上的一些建模。 哎,这也是OK的。 它这里面有个重要的关键词叫做extends(你说的exten是口误), 当然这个地方的extends拼写是t-e-n-d-s啊, extends,T-E-N-D-S。 OK,那咱们来看一下啊。 我们去写一个代码试一下。 咱们来个弹幕: 零五。 先简单体验一下,这个继承其实就跟咱们的父子关系一样诶。 比如说你儿子,是不是继承了爸爸的所有东西? 那就这么来的。 比如说咱们还是一样的, 我们写两个类。 首先写一个,嗯…… 比如具体的Person嘛,还是以人为主。 Person(你说的pert i s n是口误), 对不对? 这是咱们的一个人类。 人类的话,他肯定会有一些自己的属性, 这是一个人,把这地方写到这样。 “人”类写完了的话, 我们还可以让它有继承关系。 比如说人,他是一个很高的类, 我们刚才说的,对不对? 那咱们下面来对“人”进行分类, 我们按学生来分吧: 学生跟老师。 学生,对不对? 学生他也是人, 学生,他也是人, 对不对? 这是一个is-a的关系, 就是“学生是人”, 没有问题。 那怎么表示这种关系呢? 我们可以用学生继承了人: extends, 对不对? extend咱们的Person哎。 你看,就这样一个关键词, 就是学生诶, 继承了人的所有东西。 然后除了这个之外呢, 我们还可以有其他的继承关系。 哎,比如说咱们的Teacher(t-e-a-c-h-e-r), 他也是人, 对不对? 来理解一下: 就是老师也是人,is-a人, 对不对? 那这个Teacher类的话,他就要去继承咱们的Person诶。 这样的话,大家很明显可以发现一个关系: 它有一颗树一样的感觉, 对不对? 什么呀? 就是Person在最上面, 然后下面有Student(学生), 对不对? 那画一下图, 就是这样的理解哎。 比如说我这个地方,正常的话有一个学生类跟老师类, 咱们知道这个类是不是可以创建非常多的学生对象啊? 于是把它变成了一个父类(你说的负累是口误), 对不对? 就是这下面的所有子类,跟这个父类都有一点点关系。 那咱们这个东西就变得非常重要了: 继承是咱们最核心的一个东西啊! 封装是关于底层的, 对不对? 那咱们这个继承,相当于整个宏观的把握, 然后最后多态(你说的多肽是口误)也是要有继承的前提啊。 所以说,继承大家一定要认真理解。 那咱们来看一下,继承是什么呢? 继承就是扩展的意思, 子类是父类的扩展。 那咱们来试一下啊, 什么意思? 这句话还是回到代码, 我们来看一下。 在这个地方的话, 我们现在有三个类: 一个叫做Person, 一个叫做Student, 一个叫做Teacher,对吧? 这两个Student和Teacher都继承了这个Person哎。 那什么意思啊? 那这个Person它就是父类, 而这些子类就是Student跟Teacher, 他们都可以叫做派生类。 派生类, 派生类或者叫做子类, 就是相当于从这个父类下面派生出来的一些子类, Student当然也是了, 对不对? 那就有这样一个关系之后, 大家明白。 那除了这个继承啊, 其实Java里面还有一些其他的关系。 就比如说我Student想用到Person的特性, 我除了继承Person,我还能怎么办呢? 我其实还有一种办法,叫做组合。 我可以把Person组合成Student的一个属性: 哎,来个Person, 你看,Person aPerson; 这样的话,我就把Person的特性也拿到了, 对不对? 这就是不一样的关系啊。 所以说,继承还是比较明确的一个东西, 只是说在Java里面,有时候我们不一定会用继承来做一些事情, 继承只是实现这些功能的一个办法, 组合也是啊。 嗯,关于组合的话, 咱们以后再慢慢聊。 那咱们回到PPT,来理一下这些概念性的思路啊: 首先,继承是类和类之间的一种关系, 诶,这个大家没有任何问题, 对不对? 因为我们是这个类继承另外一个类嘛。 那除此之外,我刚才说了, 是不是还有其他的关系啊? 比如说依赖、组合、聚合等等。 哎,这个的话,以后有机会咱们再慢慢聊,先聊继承的关系。 继承关系分为两个角色: 第一个叫做子类, 也是派生类; 第二个叫做父类(你说的负累/积累是口误)或者基类。 一般情况下,我们就把它叫做父子关系就好了。 子类继承父类,用extends来表示。 那子类和父类之间是不是is-a关系啊? 比如说“老师是人”、“学生是人”诶, 比如说“旺财是一只狗”, 对不对? 这样的话,都是可以去体现继承关系的。 那下面的Object类、super以及方法的重写, 它就是咱们的一个重点。 等会大家听到这一块的时候, 就一定要竖起耳朵听,我的PPT也是非常简单的, 更多的内容会放在代码里面, 对不对? 那咱们来看一下啊。 其实这个父类跟子类, 它除了这样的写法, 它还有一些比较深入的操作。 哎,比如说我们在现实生活中, 子类是不是相当于儿子? 儿子是不是可以继承父亲的所有财产啊? 或者继承父亲的很多东西? 就是一个继承的关系。 那咱们代码里也是,子类可以继承父类的所有方法, 那咱们来试一下哈。 首先有一个前提啊: 我们现在都写的是public的方法, 你看到我没有用其他访问修饰符, 我用的是public。 比如说我现在给Person加一个“说话”的方法: 嗯, 说话——我现在写了一个方法叫做say(), 对不对? 那咱们来看一下这个say()方法, 我可以在这下面输出一下: “说了一句话”。 我就直接输出“说了一句话”。 OK,我在这个父类里面写了say()方法, 但是我们去看一下Student类里面有这个方法吗? 可以看到,是不是没有啊? Student里面没有东西, 它只是继承了Person。 那咱们来把Student的对象new一下, 那咱们来看一下Student能调用哪些方法。 来,Student——我们这个地方创建一个Student的对象: 那创建完这个对象之后, 我们去接收一下这个对象: 来,接收这个对象。 OK,Student s = new Student(); 我们来点一下它的方法, 正常的话,咱们知道Student类里什么都没有, 是点不出方法的, 它只有一个无参构造(你说的午餐构造是口误),对吧? 理论上就这一个无参构造。 那咱们先来点一下: 通过点操作符诶, 发现这个地方有个say()方法。 那咱们来执行一下这个方法, 看看效果哎。 就是这个Student为什么能调用say()? 其实大家诶,聪明的同学是不是已经想到了:这个Student继承了父类Person, 它由于继承的关系, 拥有了Person的say()方法。 看,是不是输出“说了一句话”呀? 这个Student对象也能调用say()方法说一句话, 这个方法是从哪来的? 是不是从Person来的呀? 所以说啊,非常简单的一个关系:子类继承了父类诶, 就会拥有父类的全部方法诶(前提是访问修饰符允许)。 这是一个前提啊。 然后,不仅是方法,属性也是如此。 那比如说咱们这个地方给Person加一个public int money; 来来,int money; 对不对? 咱们可以理解为“继承了父亲的所有钱”, 比如说赋值十个亿: 哎, 这够多了吧? 十个亿的话,我们可以用下划线分隔:10_0000_0000, 这是不是JDK 7的新特性啊? 我们在基础课也聊过。 OK,我们这个地方现在给Person的money赋值十个亿了, 哎,Student对象能访问到这个money吗? Student类里是不是没定义money呀? 那但是我们来输出一下: 来,输出一下student.money。 你看,哎,点一下,你会发现是不是也能访问这个money呀?来运行一下。 只要是子类继承了父类, 它就会拥有父类的所有方法和属性啊(前提是访问修饰符允许)。 当然,前提是我说的, 现在我们这个修饰符是不是都是public呀? 我们在这个阶段会给大家讲一下其他的访问修饰符(你说的修车师傅是口误)。 来, 我来把这个地方说一下: 首先,第一个是public,是公共的; 然后咱们上节课聊了private(p-r-i-v-a-t-e), 对不对? private。 那咱们把money改成private,你看Student还能直接用吗? 那子类你看,直接是不是报错了? “我是父亲的私有属性, 凭什么要让你直接用呢?” 对不对? 所以说,你们会发现访问修饰符是有很明显的作用的: 就是如果你们要让子类继承父类的一些东西, 访问修饰符的选择很关键。 那除了public和private, 其实我们不写修饰符的话, 它就是默认的(default), 比如说咱们写:int age; 是不是就是默认的访问权限?default。那除了这个默认的, 我们还有一种叫受保护的(protected), 就是它的访问权限啊, 要比default高一点。 protected(p-r-o-t-e-c-t-e-d)这个单词, 这是我们的四个访问修饰符啊。 当然你们可以在这个地方直接搜,就能搜到它们的区别, 是不是就这四个单词? 然后默认的话,你可以什么都不用写啊, 就是default。 这是四个访问修饰符的优先级: 咱们访问范围最广的是public, 如果要让子类继承父类的成员, 我们一般用public或者protected修饰, 我们一般都是用public修饰方法, 你看JDK源码里的方法,是不是大多是public的? 你应该能发现这些规律啊, 理解一下这个就好了。 按照我们的封装思想,属性用private, 然后给它设置两个公共的get/set方法就好了: getXXX()、setXXX(),就是你无法直接操作我这个私有属性, 但是我给你留了方法, 你可以按照我的方法来进行操作, 对不对? 唉,这样的话就是符合封装思想的。 你可以发现,继承里面是不是跟封装也有一些关联啊? 哎,咱们这是一种编程思想啊。 整个面向对象,其实代码本身理解起来是比较简单的, 重点还是难在这些编程思想。 OK,大家记住一个快捷键,叫做什么? 我来写到这边: Ctrl+H(C-O-N-T-R-L加H),来我们试一下Ctrl+H诶。 这个地方是不是打开了一个继承树啊? 你会发现侧边栏是不是有个继承树的感觉? 这个树是从哪来的? 它其实就是我们的继承关系。 你会发现我在Student这个类上按下Ctrl+H, 它是不是显示Student → Person → Object?这个Object是哪来的? 对不对? 为什么我们这个Student明明继承了Person, 这个我们能理解, 那这个Person为什么上面还有个Object呢? 哎,我们再来试一下: 光单独回到Person这个类, 来把光标先定位在Person类里面啊, 就是鼠标在Person类的代码区域, 然后Ctrl+H诶, 你会发现,诶,现在的树结构变了: 变成我们当前这个Person类了, 对不对? 这个Person在中间,它是标红的, 然后Person下面有两个子类: 一个叫做Teacher, 一个叫做Student。 这个是我们自己写的。 那上面还有个Object类, 你是不是没见过? 那是什么东西? 那其实大家来思考一个问题: 我们现在依旧来new对象, 现在大家其实可能就有点明白我要讲的意思了。 来,new一个Person: Person p = new Person(); 那咱们来拿到这个p对象, 我们来点一下它的方法: 我们把Person类里的东西也像刚才那样删得干干净净, 现在这个Person类里面什么都没有了, 对不对? 但是我来点一下p.,发现它这里面有这么多方法,是吗? 看,是不是equals()、hashCode()、toString()、 notify()、wait()? 这些方法都是什么东西啊? 诶,我好像没有定义这些方法啊。 那你们想,是不是有一个类是我们看不见的, 就跟咱们的无参构造一样, 我们是看不见的, 但是它冥冥之中存在呀? 那咱们来试一下诶, 它就是这样一个东西啊: 就是在Java中, 在Java中, 在Java中, 所有的类, 所有的类都默认继承Object类! 这是默认继承的: 就是当前类如果你不去显式继承其他类, 都直接继承Object;如果显式继承了其他类,就是间接继承Object诶。 这样的话,大家就挑不出来毛病了, 对不对? 那咱们来试一下啊: 比如说咱们来看一些常用类, 比如说String这个类,点进去String的源码诶, 你发现你是不是看不到它写extends什么东西? 你看到的是其他内容,按Ctrl+H一下, 诶, 发现String类是不是也在Object类下面呢? 那咱们去看一下这个Object类到底是什么东西啊: 我们先找到它, Object确实有这样一个类, 对不对? 对不对? 那我们来看一下这个Object类(class Object), 那这里面有些方法诶: 注册本地方法、 然后native getClass(),看到了吧? 这个地方有个方法叫做getClass()啊。 那咱们来看一下: p.getClass(), 来,p.getClass(); 诶,你发现确实有这样一个方法, 对不对? 那就是从Object类来的。 当然这个地方的方法为什么长这么奇怪? 这咱们未来会说,你可以发现这地方有个关键词叫做native, 对不对? 它是本地方法(底层是C/C++实现)。 然后再往下,这个地方有个hashCode(), 也发现它也是native方法。 然后除了这个之外呢, 诶,equals()、 然后再往下还有clone()方法诶、 toString()方法、 还有咱们的notify()、wait()。 你发现刚才我们看到的方法,是不是都在Object里面? 哎,现在你们就能记住了哎: Java中所有的类,无论你显不显示定义继承关系, 它都直接或者间接继承Object类。 那比如说咱们这个地方显式地给Person定义: extends Object, OK,这样子的话,跟不写extends Object没有任何区别。 你刷新一下继承树, 你看还是这个样子的。 所以说啊,写不写都一样,没什么用。 所以说,我们正常情况下可以把这个extends Object省略掉: 就是你写一个类, 如果没有显式定义继承任何类, 它其实也是继承Object类的。 关于Object类的话, 我们在之后的课程里面再去详细了解它的方法, 嗯, 它的底层原理, 我们甚至要学到多线程才会深入讲, 这是一个漫长的过程。 所以说,重点去理解继承这个概念啊, 并不要去纠结Object类的细节。 OK,目前的话,大家是不是就明白了什么是继承了? 哎,了解到继承之后, 那咱们等会儿来看一下继承里面的另外两个重点: 我刚才说了, 是不是一个叫做super, 一个叫做方法重写啊? 现在Object类咱们已经差不多看完了, 然后你们要记住一个点哦: Java中只有单继承, 没有多继承! 什么意思啊? 单继承的意思,就相当于你一个儿子是不是只能有一个亲生爸爸呀? 但是一个爸爸可以有多个儿子。 你们就这么理解, 对不对? 一个儿子,唉,可以干嘛? 儿子只能有一个亲生爸爸, 对不对? 这是Java的单继承规则。 你是不是不能让一个类继承多个父类啊? 只能单继承,嗯。 你们可能有其他办法实现类似多继承的效果吗? 是不是不可能直接多继承? 因为Java只支持单继承, 但是诶,一个爸爸(父类),对不对? 可以有多个儿子(子类)。 就这么去理解就好了。 你看像我们刚才的Student类, 它直接继承了Person之后, Object就变成了它的祖宗类了呀, 就是祖父类, 就是爸爸的爸爸这样一个类, 对不对? 所以说,继承有一个递进的关系啊: 它直接的话只能继承一个类, 但是它可以间接的继承多个类(通过父类的继承链), 对不对? 哎,就这样理解就好了。 然后在这一块的话, 咱们就聊到这儿。 等会儿的话,咱们来看一下super以及方法重写诶, 这两个是什么? 这两个都是咱们的重点啊, 我会详细的给大家去讲。 然后这个地方,先简单了解一下继承, OK。

更多推荐


所有评论(0)