方法
1、方法的声明
1)方法头:描述了方法的名称和规格;
返回类型:指的是自我调用的控件, 即返回值(return value, 方法中返回的数值)的类型;
方法名:方法的名称,方法就是通过该名称与其他控件进行调用的;
形参列表:方法中将用于接收 "辅助指示" 的变量即形参, 放在小括号中进行声明 。
2)方法体:方法体就是程序块(即用大括号括起来的0条以上的语句的集合)
方法max的主体中声明了max变量,方法体中可以声明和方法名同名的变量,因为方法和变量的类别不同, 不会发生名称冲突。
计算3个人的身高、体重、年龄的最大值并显示结果:
import java.util.Scanner;
public class Main {
//--- 返回a, b, c中的最大值 ---//
static int max(int a, int b, int c) { //定义方法
int max = a;
if (b > max) max = b;
if (c > max) max = c;
return max;
}
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
int[] height = new int[3]; // 身高
int[] weight = new int[3]; // 体重
int[] age = new int[3]; // 年龄
for (int i = 0; i < 3; i++) { // 读入
System.out.print("[" + (i + 1) + "] ");
System.out.print("身高:"); height[i] = stdIn.nextInt();
System.out.print(" 体重:"); weight[i] = stdIn.nextInt();
System.out.print(" 年龄:"); age[i] = stdIn.nextInt();
}
int maxHeight = max(height[0], height[1], height[2]); // 身高的最大值
int maxWeight = max(weight[0], weight[1], weight[2]); // 体重的最大值
int maxAge = max(age[0], age[1], age[2]); // 年龄的最大值
System.out.println("身高的最大值为" + maxHeight + "。");
System.out.println("体重的最大值为" + maxWeight + "。");
System.out.println("年龄的最大值为" + maxAge + "。");
}
}
输出:
2、方法的调用
使用方法控件的操作称为“调用(启动)方法,上述代码中为:
int maxHeight = max(height[0], height[1], height[2]); // 身高的最大值
int maxWeight = max(weight[0], weight[1], weight[2]); // 体重的最大值
int maxAge = max(age[0], age[1], age[2]); // 年龄的最大值
方法的凋用是通过在方法名的后面加上小括号来执行的;
这个小括号是下图所示的方法调用运算符,传给方法的"辅助指示"的实参就放在小括号中,用逗号隔开。
1)当调用方法时,程序流程会跳转到该方法中
当调用方法时, 程序流程会跳入该方法中。因此, main 方法的执行会暂时中断,开始执行方法max
2)方法接收的形参使用传递的实参值进行初始化
当形参初始化结束后.方法体开始执行。这里是将a、b、c中的最大值181赋给变量max
3)方法调用表达式的值为该方法的返回值
方法max将最大值返回给调用方,负责执行此项操作的是 return max;
执行return语句时.程序流程会返回到调用方处,返回值可以通过对方法调用表达式进行求值得到
return语句会结束方法的运行, 使程序流程返回到调用方处, 其语法结构图如图:
import java.util.Scanner;
public class Main {
//--- 返回a, b中的最大值 ---//
static int max(int a, int b) {
if (a > b)
return a;
else
return b;
}
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
System.out.print("整数a:"); int a = stdIn.nextInt();
System.out.print("整数b:"); int b = stdIn.nextInt();
System.out.println("最大值是" + max(a, b) + "。");
}
}
输出:
3、值传递
1)方法间的参数交换是通过值传递进行的
计算指数幂:
import java.util.Scanner;
public class Main {
//--- 返回x的n次幂 ---//
static double power(double x, int n) {
double tmp = 1.0;
for (int i = 1; i <= n; i++)
tmp *= x; // 将tmp乘以x
return tmp;
}
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
System.out.println("计算a的b次幂。");
System.out.print("实数a:"); double a = stdIn.nextDouble();
System.out.print("整数b:"); int b = stdIn.nextInt();
System.out.println(a + "的" + b + "次幂为" + power(a, b) + "。");
}
}
输出:
形参x初始化为实参a的值,形参n则初始化为实参b的值,像这样方法间通过参数来进行数值交换的机制称为值传递
2)灵活运用值传递的优点,可以让方法更加简洁紧凑
对x的值进行n次乘法运符,n的值会像5, 4, ···1这样逐渐递减
import java.util.Scanner;
public class Main {
//--- 返回x的n次幂 ---//
static double power(double x, int n) {
double tmp = 1.0;
while (n-- > 0)
tmp *= x; // 将tmp乘以x
return tmp;
}
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
System.out.println("计算a的b次幂。");
System.out.print("实数a:"); double a = stdIn.nextDouble();
System.out.print("整数b:"); int b = stdIn.nextInt();
System.out.println(a + "的" + b + "次幂为" + power(a, b) + "。");
}
}
输出:这里不再需要用下控制循环的变量i、方法变得更加简洁紧凑
4、void 方法
显示直角在左下方的直角三角形
import java.util.Scanner;
public class Main {
//--- 连续显示n个字符'*' ---//
static void putStars(int n) {
while (n-- > 0)
System.out.print('*');
}
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
System.out.println("显示直角在左下方的三角形。");
System.out.print("层数:");
int n = stdIn.nextInt();
for (int i = 1; i <= n; i++) {
putStars(i);
System.out.println();
}
}
}
输出:方法 putStars 会连续显示 n 个 '*' ,该方法只用于显示,没有返回值;这种方法的返回类型要声明为 void。
由于void方法不会返回值,因此return语句也不是必需的。
如果在方法的中途要强制将程序流程返回到调用方,可以执行没有返回值的return 语句;
2)方法的通用性
尽可能创建通用性高的方法
程序中新定义了一个方法putChars,该方法会连续显示n个赋给形参c的字符;
这里可以显示任意字符,比起只能显示'*'的putChars方法,通用性更高
显示直角在右下方的直角三角形:
import java.util.Scanner;
public class Main {
//--- 连续显示n个字符c ---//
static void putChars(char c, int n) {
while (n-- > 0)
System.out.print(c);
}
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
System.out.println("显示直角在右下方的三角形。");
System.out.print("层数:");
int n = stdIn.nextInt();
for (int i = 1; i <= n; i++) {
putChars(' ', n - i); // 显示n - i个' '
putChars('+', i); // 显示i个'+'
System.out.println();
}
}
}
输出:
3)其他方法的调用
方法是程序的一个控件。在创建控件时, 如果有其他方便的控件, 我们也可以大量地使用。
在自己创建的方法中调用方法:显示长方形和正方形
import java.util.Scanner;
public class Main {
//--- 连续显示n个字符c ---//
static void putChars(char c, int n) {
while (n-- > 0)
System.out.print(c);
}
//--- 通过排列字符'+'来显示边长为n的正方形 ---//
static void putSquare(int n) {
for (int i = 1; i <= n; i++) { // 执行n次下述处理
putChars('+', n); // ·显示n个字符'+'
System.out.println(); // ·换行
}
}
//--- 通过排列字符'*'来显示宽为h长为w的长方形 ---//
static void putRectangle(int h, int w) {
for (int i = 1; i <= h; i++) { // 执行h次下述处理
putChars('*', w); // ·显示w个字符'*'
System.out.println(); // ·换行
}
}
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
System.out.println("显示正方形。");
System.out.print("边长:"); int n = stdIn.nextInt();
putSquare(n); // 显示正方形
System.out.println("显示长方形。");
System.out.print("宽:"); int h = stdIn.nextInt();
System.out.print("长:"); int w = stdIn.nextInt();
putRectangle(h, w); // 显示长方形
}
}
输出:用于显示正方形的方法putSquare和用于显示长方形的方法putRectangle都内部调川了方法putChars
4)声明为final的形参
当将形参声明为final时,方法中就不能再修改该形参的值:
import java.util.Scanner;
public class Main {
//--- 计算三个形参值的和 ---//
static int sumOf(final int x, final int y, final int z) {
// x = 10;
return x + y + z;
}
public static void main(String[] args) {
System.out.println(sumOf(1, 2, 3));
}
}
输出:6
5、作用域
变量不仅可以在方法内部进行声明、还可以在方法外部进行声明;下面代码就是在方法内部和外部声明了变量
确认标识符的作用域:
class Scope {
static int x = 700;
static void printX() {
System.out.println("x = " + x);
}
public static void main(String[] args) {
System.out.println("x = " + x);
int x = 800; //块作用域局部声明
System.out.println("x = " + x);
System.out.println("Scope.x = " + Scope.x);
printX();
}
}
输出:作用域就是标识符(名称)的通用范围
1)类作用域:多个方法中共享的变量一定要在方法外部进行声明,并加上static
static int x = 700;
在方法外部声明的变量的标识符在整个类中都通用;因此, x标识符(名称)在方法printX和main方法中都通用;
在方法外部声明的变量称为字段(field), 以区别于在方法内部声明的变量。
2)块作用域
程序块中声明的变量称为局部变量,变量的标识符从声明的位置开始,到包含该声明的程序块最后的大括号为止都通用
int x = 800;中声明的x在main方法末尾的大括号}之前都是通用的;
当类作用域和块作用域中存在相同名称的变量时,局部变量是可见的, 而字段会被隐藏。 int x = 800中 x为800;
System.out.println("Scope.x = " + Scope.x);--像Scope.x 这样,使用"类名.字段名"可以访问上述被隐藏的类作用域中的字段;Scope.x是static int x = 700中的x, 因此其值显示为700。
3)变量的种类
6、不接受参数的方法
1)不接收形参的方法在声明时小括号()中是空的
心算能力训练:
import java.util.Random;
import java.util.Scanner;
class MentalArithmetic {
static Scanner stdIn = new Scanner(System.in);
//--- 确认是否继续 ---//
static boolean confirmRetry() { //不接受参数
int cont;
do {
System.out.print("再来一次?<Yes…1/No…0>:");
cont = stdIn.nextInt();
} while (cont != 0 && cont != 1);
return cont == 1;
}
public static void main(String[] args) {
Random rand = new Random();
System.out.println("心算能力训练!!");
do {
int x = rand.nextInt(900) + 100; // 3位数
int y = rand.nextInt(900) + 100; // 3位数
int z = rand.nextInt(900) + 100; // 3位数
while (true) {
System.out.print(x + " + " + y + " + " + z + " = ");
int k = stdIn.nextInt(); // 读入的值
if (k == x + y + z) // 正确答案
break;
System.out.println("回答错误!!");
}
} while (confirmRetry());
}
}
输出:方法confirmRetry和main方法中都会执行 “通过键盘输入数值" 的操作。
由于方法confirmRetry和main方法中都要使用变量stdIn;因此之前的程序中在main方法中声明的部分在本程序中移到了方法的外部
2)实参的求值顺序
确认实参的求值顺序:
class Argument {
//--- 显示3个参数的值 ---//
static void method(int x, int y, int z) {
System.out.println("x = " + x + " y = " + y + " z = " + z);
}
public static void main(String[] args) {
int i = 0;
method(i, i = 5, ++i);
}
}
输出:
传递给方法method的实参有3个。由于是从前往后依次进行求值,因此传递的值如图: