这个世界技术的进步都是懒人推动的,我一直这样认为,故而我时常偷懒,却也心安理得。
当我把这个观点说给她听的时候,她强烈地表达了不同的观点。
“怎么可能?”她大声说道,“美好的世界是靠人们勤劳的双手创造的。”
“我不否认勤劳的力量,但也不能忽略懒惰的力量。”我争辩到。
“没想到你是这样的戴老师,说起瞎话来,脸都不红一下的。”
“我没有瞎说啊,举个例子吧,洗衣机的发明不就是因为懒惰吗?”
“这么说,好像也不是没有道理。”她终于对自己的观点产生了动摇。
“所以别那么勤奋,停下来偷偷懒是很有必要的。”
“你今天怎么神神叨叨的,有什么话不能直接说吗?”她似乎有些生气,因为她“很忙”。
“我是想说上回你写的那个排序的代码中,找出最小数的那段在之前就写过,然后你在排序的代码中又写了一遍。”说到这我停了一下,她则翻出之前写的代码,然后点了点头。
“有没有什么想法?”我问她。
“我写得还可以。”她说,然后笑起来。
“你的想法很好,不过,这不是我想你有的想法。”
“虚心使人进步嘛,我明白你的良苦用心的。”
“也不是这个。”
“那是什么?”
“难道你就不想偷偷懒吗?前面写过的代码能不能有什么好的方式直接拿过来用呢,而不是再去写一遍。”
“额,这个,我倒没想过。”
“所以啊,别那么勤奋,停下来多想想是很有必要的。”
“好吧,那你说这个怎么做呢?”她想都不想就直接问我,因为她知道我提出这样的问题,就是准备给她讲相关的内容。
“很简单,将具有相同功能的代码封装成一个方法,需要用的地方调用这个方法就可以了。”
“那么具体表现在代码上要怎么写呢?”她说着把笔记本电脑推到我面前,她倒是学会偷懒了,也不想着尝试自己去写了。
“也好,我先写个例子给你看,然后再给你讲是怎么做的。”
我改过的上次排序的程序:
编译运行:
“看到没?找最小数的代码写到一个方法中了,这样代码看起来也整洁很多。”
“嗯,确实是这样,那么...”说着,她转过头来看向我。
我被她看得一愣,随即明白过来,她是在等着我给她解释怎么写一个方法。
“你现在知道方法就是为了完成某一项独立操作的若干条语句的组合。”说完我看她点了点头,就从身边拿来纸笔,“那么现在我们就来看看怎么来写一个方法。”
说着,我在纸上写下定义一个方法的公式来:
[修饰符] 返回值类型 方法名称([参数表]){
方法体
[return (表达式);//返回值]
}
“其中,中括号([])代表可选内容。那你现在可以把我写那个方法各部分套用这个公式解释一下吗?”
“我试试。”她说着拿过那张纸对着电脑屏幕看了看,然后就开始给我解释起来。
“public static对应的是修饰符?”她有些不确定,见我点了点头后,她继续说,“int 对应的是返回值类型,getMinNumSerial对应的是方法名,float []heights,int beginSerial这两个对应的是参数表,大括号里面的对应的就是方法体,return n对应的就是返回值。”
“非常正确。”我对她的领悟能力之强已经不惊讶了,“不过,你一定还有很多疑问吧?”
“确实有。”
“那就说出你的疑问。”
“首先那两个修饰符是代表什么意思?为什么是可选的,在什么情况下可以不写,又在什么情况下必须要写呢?”
“public以及private和protected这几个修饰符叫作访问控制修饰符,用来规定类的变量和方法的访问权限的。public表示任何地方都可以调用这个方法,private表示只能被同一个类的方法调用,protected表示的访问权限是同一个类、同一个包以及子类。”说着我看向她,果然从她的头顶看到了更多的问号,于是我接着说,“为什么是类的方法呢,是因为java是面向对象的编程语言,所有方法都是要写到类里面的,不会有类外面的方法的。至于什么是类,什么是包,什么是子类这些,我们后面讲类的时候专门来讲,现在你只要知道这些概念就是了。”
“哦,原来如此,所以所有的代码都要写在class XX后面的大括号里面,我想class XX这个就是在定义一个类吧。”
“说得没错,你真是太聪明了。”
她早已习惯我这样有些夸张和敷衍的夸奖了,所以她很心平气和地回了一句:“那是当然。”
“那么static这个修饰符是用来干什么的呢?”她接着提出她的疑问。
“这个修饰符表示这个方法是一个静态方法,当然也可以用到类变量上,表示静态变量。”
“这个...说了好像和没说一样,那么什么是静态方法呢?”
我确实是说了和没说一样,可是要怎么解释呢?我有些犯难,真想说只可意会不可言传,但我没有说出来,而是说:“这个理解了类的一些概念就明白了,暂时你记着写方法的时候一定要加上这个修饰符就好了。”
“好吧。”她倒也是拿得起放得下的人,不再纠结这个问题,而是换了一个问题,“返回值应该就是方法计算后得到的结果,返回值的类型和方法定义的返回值类型一定要一样,是不是?”
“对。”
“有一个问题,按说那个程序运行的入口main也是一个方法,它的返回值类型怎么是void,void是一个什么类型啊,我记得没这个类型来着。”说着她还拿出书来翻了翻,确定了确实没有后,她接着说:“还有这个main方法为什么不用return返回呢?”
“严格来说void不是一个数据类型,它只用在方法返回值类型这里,表示这个方法没有返回值,既然没有返回值,就不需要返回了。所以说方法体中的return语句是可以没有的。”说到这里,我突然觉得我写在纸上的公式有些不对,return语句应该是方法体的一部分,不应该单独写出来。于是,我没等她说什么,接着解释道:“在方法中任何地方都可以出现return这个语句,程序执行到return语句后就会退出这个方法,不管后面还有多少代码都不会执行了。当然,return后面的返回值要根据方法定义的返回值类型来确定,如果是void的话就不需要任何返回值,否则就需要在return后面跟相应返回值类型的值,这个值可以是一个变量里的值,也可以是一个表达式计算后得到的结果。”
“这个我明白的,就像那个getMinNumSerial方法返回的就是一个变量n里面的值。而且这个值在方法调用后赋值给了main方法中的局部变量n。”
“对对,你说得没错。”我连声说对,因为她把我没讲明白的地方说清楚了。
“哈哈,我基本上已经搞懂这个方法了。”在听到我说对后,她高兴地笑着说。
“真的都懂了吗?”
“真的。”
“那你给我解释一下参数表呗。”
“这个很好理解啊。”她自信满满,倒是把我看成一个初学者一样,“参数表指的是一些参数,用来在方法调用时把一些数据传递给方法。在main方法中调用getMinNumSerial这个方法的时候通过参数表把数组heights和变量i的值传递到getMinNumSerial这个方法中来,在getMinNumSerial这个方法中就可以使用了。就像你是一个买烧烤的方法一样,我给你10块钱,让你去买烧烤,你拿着这10块钱去买了烧烤,然后回来把烧烤给我,这里10块钱就是参数,烧烤就是返回值。”
“为什么要这样麻烦呢,在getMinNumSerial方法中不能直接使用heights和i吗?”
“当然不能,变量都有作用域的,方法中的变量就只能在定义它的方法中使用,在别的方法中是不能使用的。”
她的回答让我很意外,我记得我没有讲过变量的作用域,然而她却很显然地对变量作用域这个概念很是理解。
“哈哈,不用这么惊讶地看着我。”看到我惊讶的表情,她解释说,“大学的时候,为了过计算机二级,学过一点c语言,我现在发现这个和c语言差不多,通过这些天的学习,我那沉睡的c语言知识有些苏醒了。”
原来如此,难怪她会很快掌握各个知识点,原来还是有一些基础的。
“既然这样,那你给我讲讲变量的作用域,看看你的c语言知识苏醒了多少。”
“不过那是c语言,和java真的一样吗?”
“关于变量的作用域到目前为止是一样的,后面有不同的时候,我再给你讲。”
“那好吧,我试试讲一下。”她说着清了清嗓子,然后说:“变量的作用域是通过大括号来划分的,在同一个大括号内的变量具有相同的作用域;在嵌套的大括号中,外层定义的变量在内层是有效的,但是在内层定义的变量在外层是无效的。还有一个例外,就是方法的参数表中变量虽然没在大括号内,但是它们的作用域是在方法这个大括号内的。”
说完,她看向我,问:“老师,我回答得对不?”
“对,说得太对了。看来关于方法你已经没什么疑问了。”
“嗯,暂时没有了。”
“那么就上手做做练习呗。”
“好啊。”
“就把那个排序的程序里面,交换最小数和开始找最小数的位置的数,那段代码封装成一个方法呗。”
“没问题。”
她的努力成果:
程序编译后运行没有任何问题。
“怎么样?我还是很可以的。”她得意地说。
“没错是没错,不过为什么要把数组传给方法又当着返回值返回呢?”
“这个还用解释吗?变量有作用域的啊,在exchange方法中的heights数组的作用域只在这个方法中,如果不返回的话,main方法中怎么得到交换过的数组呢。”
“可是我觉得这里可以不用返回值的呢,你信不信?”
“我信。”
我以为她会说不信,然后我就可以改改程序,让事实说服她,可她尽然说信,这让我一时竟无言以对。
“哈哈,没话说了吧?”她笑着说。
“你知道为什么了?”我以为她已经明白了原因。
“我不知道啊,不过,我就是相信你啊。”
说实话,听到这一句话,我突然有一种感动的小情绪了。仿佛一对患难与共的情侣,在闯荡江湖时,女主对男主的深情告白。
正当我沉浸在想入非非的幻想时,她的声音把我从中拉了出来:“发什么愣呢?快给我讲讲啊。”
“好,我先改改程序让你看看结果,我再讲为什么。”
我改过的程序:
编译运行:
“还真可以呢!”看到运行结果她惊叫道,“快讲讲为什么。”
“这个其实很简单,在java中,除了基本数据类型是值传递外,其它的都是引用传递。”看她一脸茫然,我接着说:“值传递就是传递实实在在的值,不管是赋值还是方法中的传参都是完全复制了一份数据给另一个变量;而引用传递呢,数据是一直放在一个地方,变量里面存的只是数据在哪里的一个信息,所以对这类变量的操作实际上一直都是操作的同一个数据。”
她依然茫然一脸,于是我想了想说:“举个例子吧。假如你有10块钱,你让我帮你花掉5块,这个时候你有两种方案:第一种,你给我10块钱现金,我去买个串吃了,花掉5块钱,然后我回来给你5块钱,这就是值传递;第二种,你给我一个有10块钱的微信付款码,我拿着这个付款码去花掉5块钱,我回来不用给你任何东西,你的账户里就只剩5块钱了,这就是引用传递。”
听了我举的例子,她想了想说:“你这么一举例我就明白了,这就是java和c的不同了吧?”
“算是一个不同吧。”我说。
“好开心,又学到一个重要的知识点。”她很开心,像一个学霸一样,虽然我不知道她读书的时候是不是真的学霸。
美好的时光总是溜得很快,不知不觉已经下班很久了。
“该回家了。”我说。
“呀,又这么晚了。”她说。
于是,我们收拾了一下,肩并肩地走出公司大门,那一刻我突然有一种去牵着她的手的冲动,但我最终克制了下来,毕竟我们只是同事关系,如果非得要把我们的关系定义得近一些的话,也不过是老师与学生的关系,我不能做一个流氓。
走到大街上,看到路边的烧烤摊,她突然说:“想吃个串。”
“好啊,我请你。”我说。
正要走向烧烤摊,却看到老板推着小推车和其他小贩一道一溜烟地跑了,留下一脸错愕的我和她。
“难道你经常吃霸王餐,故而小贩们看到你就跑了?”我打趣道。
“你才经常吃霸王餐呢。”她反驳道。
这时几个穿着制服的人从眼前悠悠然地走过,我们这才恍然大悟,继而狂笑不已。