上篇我们介绍了什么是类和类中的成员变量。其实除了成员变量,类里还可以放其它东西,就好比游戏里的人物除了属性还可以有任务。一个网红也一样,除了有姓名年龄爱好外,他可以有他的日程安排,今天有今天的事,明天有明天的事,也就是行为。java专门为行为定义了一种结构,我们管它叫方法,或者叫函数。简单说就是你把想做的事都放在方法里,然后执行方法即可。方法的格式如下:
简单看看这几个部分。咱先不要管访问修饰符,以后再讨论。先看方法名,方法名看起来和实例化对象很像,都是一个名称加上"()",但含义却截然不同。类名后面带括号代表对象,而方法则是类中的成员,两者不要搞混。和变量名一样,方法名的命名规范也是用小写字符开始;返回类型的意思是返回值的类型,可有可无。参数也是可有可无。先看最简单的 --- 无返回类型无参数。还用上篇java类和成员变量的例子,比如咪蒙要做的事是写文章,所以方法可能就是:
这里面返回类型void在英文里是空的,没有的意思,用在java里代表的就是无返回类型,大白话就是不需要任何返回值。我只是简简单单在终端打出一句话来,并没有返回什么东西。把这个方法放进上篇文章的代码中就会是:
上篇说过,对于成员变量来说我们可以用对象访问成员变量的方式来赋初值,比如mm.name = "咪蒙";打印的时候也用mm.name来访问。那么对于方法来说,它本身并不存在赋什么初值,但打印的时候我们也是用对象访问方法来实现:
对象访问方法也叫调用方法。我们在程序入口里继续写mm.writing():
执行程序调用方法,执行方法体里的内容,这样“今晚写文章”就被打印出来了:
这是无返回值无参数的一个小例子,是最简单的情况。那有返回值是什么样呢?拿王思聪举例。比如现在王思聪玩游戏要去做任务了,打5场战役,每场都打了10个怪,然后他的任务是计算一下今晚总共打了多少个怪。这个问题很简单,都知道是50。当然,游戏会自动给你计算总共打了多少个怪,毕竟现实中的国民老公不可能自己去数:
方法体里的前几行我就不解释了,不太明白的请翻阅java的流控机制 - 分支与循环里关于for循环的讲解。return翻译过来是返回的意思,java里代表返回什么值。注意,方法声明中的返回类型是int,因为我的total变量是整型,所以可以被返回。你要是返回一个其它类型的值就会报错。这里一定要注意,我们以后写自动化代码经常要调用方法,返回类型一定要和真正返回值的类型是一样的。用代表王思聪的对象wsc调用countGuai()的执行如下:
执行程序,发现王思聪打的50个怪没出结果。有人说不是有返回值吗?没错,但返回值并不是自己就打印出来了,你没有System.out.println()是绝对输出不了任何结果的。所谓的返回值其实是方法把值返回到主体程序中罢了,这点别弄混。wsc.countGuai()返回的值是50。所以,我们可以再声明一个变量存返回值,然后用System.out.println()打印出结果:
有人说我用咪蒙的对象mm调用countGuai()可不可以?当然没问题啊。刚才我们已经看到了,每个对象都有name,age,hobby三个成员属性,对于成员方法也是一个道理,每个对象也都有writing()和countGuai()这两个成员方法。只不过按照实际项目需要选择调用哪个罢了,假设咪蒙不玩游戏,你写mm.countGuai()不就没意义了么?
实际项目中很多时候并不需要打印出返回值,而是把返回值再存入一个变量中继续后面的操作。比如我说王思聪每打50个怪程序会自动给它奖励,多加10个怪给他。题目里他正好打了50个怪,所以系统自动把数目加10。最后一部分就变成了:
现在考虑一个问题。假设游戏出bug了,老王每场打的怪其实不是10个,是20个。怎么办呢?有人说这简单,把方法里的numOfEach改成20就行了。可这真的是好方法么?如果变成30/40/50了呢?每次都去修改这个方法是不是很麻烦?这就需要参数的帮助了。参数这个概念由来已久了,其实就是为了使代码更加灵活。咱们修改一下这个方法,把方法名后面那个括号里添一个整型参数:
你看,参数的写法也跟声明变量差不多,也是"变量类型 变量名"的格式。参数其实就是个变量,既可以用基本类型也可用复杂类型,甚至是对象。现在如果我们把wsc.countGuai()改成wsc.countGuai(20),执行的时候程序就会把20传给numOfEach,并在方法体中使用。执行看一下:
130被打印出来。你看,主体程序中20作为参数传给countGuai方法里的numOfEach参数,其实也就是给参数这个变量赋值了对不对?其实也就是完成了int numOfEach = 20这么一个过程。然后numOfEach带着值参与到方法体的运算之中。这里面的20由于是个实际的数值,所以叫实际参数。而方法里的numOfEach并不是一个实际的值,它只能接收从其它地方传过来的实参,只是参数的一种表达形式,所以叫形式参数。你看,有了实参和形参,程序的表达是不是省事多了?
注意,有一个地方容易犯错:参数的类型一定要一致。形参已经表明了numOfEach是整型,你非要传个浮点型或是字符型的肯定就要报错。还有一点,不要把参数和成员变量混淆,参数只能在方法体里被声明和使用,出了方法体就无效了。
参数不一定只有一个,可以有多个。比如王思聪又说了,游戏又出bug了,我明明打了6场比赛,少算一场。得,那我们还得把循环的终值改掉。那我也可以把终值写成参数:
同样,实参我们也得传两个,并且参数的顺序和数据类型也必须一致。因为是6场比赛,由于循环初值是0,所以我把5传给n。程序就变成了:
总之,参数可以是一个,可以是两个,可以是多个,也可以没有。关键是调用时实参和形参的数据类型,个数,顺序都要匹配,否则就会报错。比如王思聪不信邪,countGuai(int numOfEach, int n)明明要求传入两个参数,但他调用的时候偏偏写成wsc.countGuai(),就不放实参,这种情况下程序调用的时候肯定会出错。一种情况注意一下,有时候你会看见有人直接返回计算出来的值,没创建变量,比如“return true”,意思是返回布尔值“true”,这种写法也对,相当于“boolean b = true; return b;”。
但王思聪又说了,不是我轴,我也是被逼无奈,我爸王健林这两天盯我盯得比较紧,不让我随便玩游戏,天天查我打怪数量有没有增长,如果看出增长这不就暴露了吗?所以我还得要countGuai()这方法,不加任何参数,就让它永远保持一个数。这样countGuai(int numOfEach, int n)用来记录打怪真实数量,countGuai()用来糊弄我爸。两个同名方法并存行么?没问题,这就引出了方法的一个重要特性 - 重载。
重载允许两个或多个同名方法存在,但形参必须独一无二。怎么个独一无二法呢?这里主要指的是参数个数、类型、顺序的不同,说白了就是看起来都不一样。程序执行时会根据实参的实际情况来选择调用哪一个方法。比如我多写几个countGuai方法,先举例再总结:
你看,同样是countGuai方法,但它们的参数看起来都不一样,这时重载就成立。反过来,只要有任意两个参数一模一样(包括类型)的方法就不行,就报错。执行的时候,在实参和形参对应的条件下,程序会根据参数的个数、类型、顺序不同而选择性地调用。
除此之外,方法的返回类型也可以不一样,比如上面有一个方法是void countGuai(int numOfEach),没有返回值。当然,你也可以让它返回字符或是浮点型数据。重载我们以后介绍访问修饰符时还会提到,而且后面还会有一个和它容易混淆的概念叫重写,到时我会给大家总结它们的不同。
这就是方法的介绍。一个方法可以无参无返回值,无参有返回值,有参无返回值,有参有返回值。这些都是根据项目的实际需要进行变化的。但只要我们随时保证参数的数目顺序一致,返回值类型准确,处理方法就会非常容易。现在把成员方法也包含在类的结构图里:
本篇知识点及注意事项:
1. 一个类中除了成员变量还有成员方法;
2. 成员方法包含访问修饰符,返回类型,方法名,以及参数;
3. 一个方法可以无参无返回值,无参有返回值,有参无返回值,有参有返回值;
4. 参数只能在方法体里被声明和使用,出了方法体就无效了;
5. 方法可以进行重载。
这篇文章的源代码在OOP2里,下篇我们介绍main函数及其他相关知识。
网友评论