每日正能量
人生如逆旅,我亦是行人,乱花渐欲迷人眼,沉醉不知归路。既然无法留住身边的美好,那就一直往前,看到更多。
方法
方法是完成特定功能的、相对独立的程序段,与其它编程语言中的子程序、函数等概念相当。方法一旦定义,就可以在不同的程序段中多次调用,故方法可以增强程序结构的清晰度,提高编程效率。方法的知识点涉及到方法声明、方法调用、方法参数、方法返回值。
方法可分为Java提供的方法(称为API,即应用程序接口)和我们自己定义的方法。在之前的学习中我们已经多次使用过系统API,例如
System.out.println();
其中println()就是一个方法,方法的特征是小括号,即()。
本章主要讲解自定义方法。
讲: | API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。 |
---|---|
1. 方法的声明
在java中方法的声明格式如下
[修饰符] 返回值类型 方法名称([参数表]){
//方法体
}
说明:
-
方法声明包括方法头和方法体两部分。其中方法头确定方法的名称、形式参数的名称和类型、返回值的类型和访问限制。方法体由括在花括号内的语句组成,这些语句实现方法的功能。
-
修饰符可以是公共访问修饰符public、私有访问修饰符private、保护访问修饰符protected。
-
返回值类型反映方法完成其功能后返回的运算结果的数据类型。如果方法没有返回值,使用void关键字声明。
-
方法名称要符合标识符命名规则,不要与java中的关键字重名。
-
参数表指定在调用该方法时,应该传递的参数的个数和数据类型。参数表中可以包含多个参数,相邻的两个参数之间用逗号隔开。
-
方法也可以没有参数,称为无参方法
-
对于有返回值的方法,其方法体中至少有一条return语句,形式如下
return 表达式;
当调用该方法时,方法的返回值就是return后面的表达式。
return返回值的类型必须与方法声明的返回值类型一致。
方法不能嵌套,不能在一个方法中声明另外一个方法。
public static double add(double d1,double d2) {
return d1+d2;
}
上例中定义了一个方法,名称是add,方法有两个参数,分别是double类型的d1和double 类型的d2,方法有double类型的返回值。方法体实现了返回d1+d2的和。
2. 方法的调用
调用方法,即执行该方法。发出调用的方法称为主调方法,被调用的方法称为被调方法。
任务1:学生成绩管理 |
---|
分别输入三个学生的Java成绩,SQL成绩,Oracle成绩,然后分别计算三个同学的平均成绩。 |
代码示例
public class Task1 {
public static void main(String[] args) {
java.util.Scanner input = new java.util.Scanner(System.in);
//第一个学生的成绩
int java1 = 0;
int sql1 = 0;
int oracle1 = 0;
System.out.println("请输入Java成绩:");
java1 = input.nextInt();
System.out.println("请输入SQL成绩:");
sql1 = input.nextInt();
System.out.println("请输入Oracle成绩:");
oracle1 = input.nextInt();
double result1 = (java1 + sql1 + oracle1) * 1.0 / 3;
System.out.println("第一个学生的平均成绩是:"+result1);
//第二个学生的成绩
int java2 = 0;
int sql2 = 0;
int oracle2 = 0;
System.out.println("请输入Java成绩:");
java2 = input.nextInt();
System.out.println("请输入SQL成绩:");
sql2 = input.nextInt();
System.out.println("请输入Oracle成绩:");
oracle2 = input.nextInt();
double result2 = (java2 + sql2 + oracle2) * 1.0 / 3;
System.out.println("第二个学生的平均成绩是:"+result2);
//第三个学生的成绩
int java3 = 0;
int sql3 = 0;
int oracle3 = 0;
System.out.println("请输入Java成绩:");
java3 = input.nextInt();
System.out.println("请输入SQL成绩:");
sql3 = input.nextInt();
System.out.println("请输入Oracle成绩:");
oracle3 = input.nextInt();
double result3 = (java3 + sql3 + oracle3) * 1.0 / 3;
System.out.println("第一个学生的平均成绩是:"+result3);
}
}
带你分析代码:
在上面的示例中看到代码分为三部分,并且三部分的功能是一样的,这是典型的代码冗余。
把功能相同的部分定义成为一个方法,然后把这个方法使用三次即可。
将上面的任务重构成方法
任务2:第一次重构学生成绩管理 |
---|
将新生成绩的录入,计算平均值,输出结果封装到方法中,将方法调用3次。 |
代码示例
public class Task2 {
public static void average() {
int java = 0;
int sql = 0;
int oracle = 0;
java.util.Scanner input = new java.util.Scanner(System.in);
System.out.print("请输入Java成绩:");
java = input.nextInt();
System.out.print("请输入SQL成绩:");
sql = input.nextInt();
System.out.print("请输入Oracle成绩:");
oracle = input.nextInt();
double result1 = (java + sql + oracle) * 1.0 / 3;
System.out.println("该新生的平均成绩是:"+result1);
}
public static void main(String[] args) {
average();//第一次方法调用。
average();//第二次方法调用。
average();//第三次方法调用。
}
}
带你分析代码:
public static void average()声明了一个没有参数,没有返回值的方法。
在main方法中调用了3次average()方法,因此average()被执行3次,使得方法中的语句被重复使用。
发出调用的方法称为主调方法(main方法),被调用的方法称为被调方法(average方法)
3. 方法的返回值
方法的设计遵循功能单一原则,即一个方法只做一件事。上例中的方法average()即包含了输入成绩的功能,也包含了输出成绩的功能,违背了方法功能单一原则。为此重构上例,将average()方法中输出成绩的功能移除,将成绩返回给主调方法,由主调方法输出成绩。
被调方法通过return语句将数据返回给主调方法,一个方法只能返回一个数据给主调方法。return 语句后面的返回值必须与方法声明的返回值类型一致。
任务3:第二次重构学生成绩管理 |
---|
将新生成绩的平均值返回给主调方法,由主调方法输出新生成绩。 |
代码示例
public class Task3 {
public static double average() {
int java = 0;
int sql = 0;
int oracle = 0;
java.util.Scanner input = new java.util.Scanner(System.in);
System.out.print("请输入Java成绩:");
java = input.nextInt();
System.out.print("请输入SQL成绩:");
sql = input.nextInt();
System.out.print("请输入Oracle成绩:");
oracle = input.nextInt();
double result1 = (java + sql + oracle) * 1.0 / 3;
return result1;
}
public static void main(String[] args) {
double result1= average();//第一次方法调用。
double result2= average();//第二次方法调用。
double result3= average();//第三次方法调用。
System.out.println("第一名新生的成绩是"+ result1);
System.out.println("第二名新生的成绩是"+ result2);
System.out.println("第三名新生的成绩是"+ result3);
}
}
带你分析代码:
average()方法中定义了返回double类型的数据。
average 方法中使用return 语句将double类型的数据 result1返回给主调方法,
main方法中通过赋值语句double result1= average();将average()方法的返回值赋值给result1。
最后在main方法中输出新生的成绩。
4. 方法的参数
在前面学习过的方法定义和方法调用中都没有使用方法参数,方法就是去做一件事情,做事情的结果就是方法的返回值,那么方法的参数就是做事的前提条件。也就是说,如果方法定义中有参数,那么调用方法的时候,一定要满足参数定义才能调用。
在设计方法时,每次调用方法都变化的数据设计成方法参数,不变化的数据设计到方法内部。
被调方法中的参数称为形式参数,主调方法中的参数被称为实际参数。当主调方法调用被调方法时,是将主调方法的实际参数传递传递给被调方法的形式参数。形式参数与实际参数必须在个数、类型、顺序上一致。
上例中当输入新生成绩时并未提示是第几个新生的成绩,将上例重构,在主调方法main中调用average方法时,向average()方法传递参数,告知average()方法输入的是第几个新生的成绩。
任务4:第三次重构学生成绩管理 |
---|
在主调方法main中调用average方法时,向average方法传递参数,告知average方法输入的是第几个新生的成绩。 |
代码示例
public class Task4 {
public static double average(int count) {
int java = 0;
int sql = 0;
int oracle = 0;
java.util.Scanner input = new java.util.Scanner(System.in);
System.out.print("请输入第"+count+"个新生的Java成绩:");
java = input.nextInt();
System.out.print("请输入第"+count+"个新生的SQL成绩:");
sql = input.nextInt();
System.out.print("请输入第"+count+"个新生的Oracle成绩:");
oracle = input.nextInt();
double result1 = (java + sql + oracle) * 1.0 / 3;
return result1;
}
public static void main(String[] args) {
double result[] = new double[3];
for (int i = 1; i <= result.length; i++) {
result[i-1] = average(i);
}
for (int i = 0; i < result.length; i++) {
System.out.println("第"+(i+1)+"名新生的平均成绩是"+result[i]);
}
}
}
带你分析代码:
average()方法中定义了int类型的形式参数,表示第几个新生。
main方法中定义了double类型的数组用来存储三个新生的平均成绩。
main方法通过for循环,调用三次average方法,main方法的实际参数i传递给average方法的形式参数count,在average方法内部提示用户输入的是第count名新生的成绩。
最后在main方法中输出新生的平均成绩。
图 形式参数实际参数传递
5. 变量的作用域和生命周期
变量的作用域就是指一个变量定义后,在程序的什么地方能够使用。变量的生命周期是指变量什么时候分配内存,什么时候从内存中回收。
前面学过代码块的概念,就是在程序设计的时候,一对大括号 { } 包含的区域。在Java中,使用大括号的地方有:类定义、方法定义、方法中的循环、判断等,一个变量的作用域只被限制在当前变量所在的语句块中(也就包含该变量的,离该变量最近的大括号)。
方法中定义的变量,称为局部变量,方法的形式参数也是方法的局部变量。只能在当前方法中使用,包括当前方法中的判断语句块,循环语句块。在判断语句块中声明的变量只能在当前判断语句块中使用,当前判断语句块之外不能正常使用,对循环语句块也是一样。
变量的生命周期就是从变量声明到变量终结,普通变量的生命周期与作用域范围一致,一个变量在当前语句块结束时,变量被系统回收。
阅读下面的代码,分析结果
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
}
System.out.println("i=" + i );
}
上面的代码无法编译,原因是变量i是在for循环中定义的,也就是说i的作用域是for循环内部。而输出语句中输出的i已经超出了i的作用域。