JAVA基础06方法

6. 方法

方法可以用于定义可重用的代码以及组织和简化编码

6.1 定义方法

方法的定义由方法名称参数返回值类型以及方法体组成

定义方法的语法如下所示

修饰符 返回值类型 方法名( 参数列表 ){ 
// 方法体 ; 
}

我们一起来看一个方法的定义该方法找出两个整数中哪个数比较大这个名为 max 的方法有两个 int 型参数num1 mnn2, 方法返回两个数中较大的一个。下图解释了这个方法的组成

方法头method header) 是指方法的修饰符modifier)返回值类型return value type)方法名method name) 和方法的参数(parameter)

方法可以返回一个值retumValiieType 是方法返回值的数据类型有些方法只是完成某些要求的操作,而不返回值在这种情况下retuniValueType 为关键字 void例如main 方法中 returnValueType 就是 void, System.exitSystem.out.println 方法中返回值类型也是如此。如果方法有返回值则称为带返回值的方法value-returning method), 否则就称这个该方法为 void 方法void method)

定义在方法头中的变量称为形式参教formal parameter)或者简称为形参parameter)。参数就像占位符。当调用方法时就给参数传递一个值这个值称为实际参数actual parameter) 实参argument)参数列表parameter list)指明方法中参数的类型顺序和个数。方法名和参数列表一起构成方法签名method signature)参数是可选的也就是说,方法可以不包含参数例如Math.randomO 方法就没有参数

方法体中包含一个执行方法的语句集合max 方法的方法体使用一个if语句来判断哪个数较大,然后返回该数的值为使带返回值的方法能返回一个结果必须要使用带关键字 return 的返回语句执行 return 语句时方法终止

在其他某些语言中方法称为过程procedure) 或函数fimction)带返回值的方法称为函数,返回值类型为 void 的方法称为过程

警告:在方法头中需要对每一个参数进行独立的数据类型声明例如max(int numl,1nt num2)是正确的max(int num1,mim2)是错误的

注意我们经常会说 定义方法声明变量这里我们谈谈两者的细微差别定义是指被定义的条目是什么,而声明通常是指为被声明的条目分配内存来存储数据

 

 

6.2 调用方法

方法的调用是执行方法中的代码

在方法定义中定义方法要做什么为了使用方法必须调用call invoke)根据方法是否有返回值,调用方法有两种途径

如果方法返回一个值对方法的调用通常就当作一个值处理例如

int larger = max(3, 4);

调用方法 max(3,4)并将其结果赋给变量 larger另一个把它当作值处理的调用例子是

System.out.println(max(3 , 4));

这条语句打印调用方法 max(3,4)后的返回值

如果方法返回 void, 对方法的调用必须是一条语句例如println 方法返回 void下面的调用就是一条语句:

System.out.println("Weicome to Java!");

注意Java 带返回值的方法也可以当作语句调用这种情况下函数调用者只需忽略返回值即可。虽然这种情况很少见但是如果调用者对返回值不感兴趣这样也是允许的。

当程序调用一个方法时程序控制就转移到被调用的方法当执行完 return 语句或执行到表示方法结束的右括号时,被调用的方法将程序控制返还给调用者

警告:对带返回值的方法而言,return 语句是必需的下面图 a 中显示的方法在逻辑上是正确的,但它会有编译错误因为 Java 编译器认为该方法有可能不会返回任何值

为解决这个问題删除图 a 中的 if(n<0), 这样编译器将发现不管 if 语句如何执行总可以执行到 return 语句

 注意方法能够带来代码的共享和重用除了可以在 TestMax 中调用 max 方法还可以在其他类中调用它。如果创建了一个新类可以通过使用 类名 .方法名TestMax.max )来调用 max 方法

每当调用一个方法时系统会创建一个活动记录也称为活动框架)用于保存方法中的参数和变量。活动记录置于一个内存区域中称为调用堆栈call stack)调用堆栈也称为执行堆栈、运行时堆栈或者一个机器堆栈常简称为 堆栈当一个方法调用另一个方法时,调用者的活动记录保持不动一个新的活动记录被创建用于被调用的新方法。一个方法结束返回到调用者时,其相应的活动记录也被释放

下图描述了堆栈中用于方法调用的活动记录。

 

 

6.3 void 方法示例

void 方法不返回值。

下列程序清单给出的程序定义了一个名为 printGrade 的方法然后调用它打印出给定分数的

等级。

    TestVoidMethod.java
public class TestVoidMethod { 
    public static void main(String[] args) { 
        System.out.print("The grade is "); 
        printGrade(78.5); 

        System.out.print("The grade is "); 
        printGradeC59.5); 
        } 

    public static void printGrade(double score) {
        if (score >= 90.0) {
            System,out.println('A');
        }
        else if (score >= 80.0) {
            System.out.println('B');
        }
        else if (score >=70.0) {
            System.out.println('C');
        }
        else if (score >=60.0) {
            System.out.println('D');
        }
        else {
            System.out.println('F');
        }
    }
}

显示

The grade is C
The grade is F

printGrade 方法是一个 void 方法它不返回任何值void 方法的调用必须是一条语句。因此main 方法的第 4 PrintGrade 方法作为一条语句调用这条语句同其他 Java 语句一样以分号结束

注意:void 方法不需要 return 语句但它能用于终止方法并返回到方法的调用者它的语法是:

return;

这种用法很少但是对于改变 void 方法中的正常流程控制是很有用的例如当分数是无效值时,下列代码就用 return 语句结束方法

public static void printGrade(double score){
    if (score < 0||score > 100){
        System.out.println("Invalid score");
        return;
    If (score >= 90.0){
        System.out.println('A'); 
    }
    else if (score >= 80.0){
        System.out.println('B'); 
    }
    else if (score >= 70.0){
        System.out.println('C'); 
    }
    else if (score >= 60.0){
        System.out.println('D'); 
    }
    else {
    System.out.print1n('F');
    } 
}

 

 

6.4 通过传值进行参数传递

调用方法的时候是通过传值的方式将实参传给形参的

方法的强大之处在于它处理参数的能力可以使用方法 println 打印任意字符串用 max 法求任意两个 int 值的最大值调用方法时需要提供实参它们必须与方法签名中所对应的形参次序相同。这称作参数顺序匹配parameter order association)例如下面的方法打印 message 信息 n

public static void nPrintln(String message , int n) {
    for (int i = 0; i < n; i ++){
        System.out. println(message);
    }
}

可以使用nPrintln("Hello", 3) 打印 "Hello"3 语句 nPrintln("Hello" , 3) 把实际的字符串参数 "Hello"传给参数 massage , 3 传给 n , 然后打印  "Hello"3 然而语句 nPrintln(3 ,"Hello") 是错误的3 的数据类型不匹配第一个参数 message 的数据类型第二个参数"Hello"不匹配第二个参数 n

警告:实参必须与方法签名中定义的参数在次序和数量上匹配在类型上兼容类型兼容是指不需要经过显式的类型转换,实参的值就可以传递给形参例如int 型的实参值传递给 double 型形参

当调用带参数的方法时实参的值传递给形参,这个过程称为按值传递pass - by value)。如果实参是变量而不是直接量,则将该变量的值传递给形参。无论形参在方法中是否改变该变量都不受影响

注意为了简便Java 程序员经常说将实参 x 传给形参 y, 实际含义是指将 x 的值传递给 y

 

 

6.5 模块化代码

模块化使得代码易于维护和调试并且使得代码可以被重用

使用方法可以减少冗余的代码提高代码的复用性方法也可以用来模块化代码以提高程序的质量。

 

 

6.6 重载方法

重载方法使得你可以使用同样的名字来定义不同方法,只要它们的签名是不同的。

前面用到的 max 方法只能用于 int 型数据类型但是如果需要决定两个浮点数中哪个较大,该怎么办呢解决办法是创建另一个方法名相同但参数不同的方法代码如下所示

public static double max(double numl, double num2){
    if(numl > num2){
    return numl;
    }else{
    return num2; 
    }
}

如果调用带 int 型参数的 max 方法就将调用需要 int 型参数的 max 方法如果调用带 double 型参数的 max 方法就将调用需要 double 型参数的 max 方法。这称为方法重载(method overloading)。 也就是说在一个类中有两个方法它们具有相同的名字但有不同的参数列表。Java 编译器根据方法签名决定使用哪个方法

提示重载方法可以使得程序更加清楚,以及更加具有可读性执行同样功能但是具有不同参数类型的方法应该使用同样的名字。

注意被重载的方法必须具有不同的参数列表。不能基于不同修饰符或返田值类型来重载方法。

注意有时调用一个方法时会有两个或更多可能的匹配但是编译器无法判断哪个是最精确的匹配。这称为歧义调用ambiguous invocation)歧义调用会产生一个编译错误

考虑如下代码

public class AmbiguousOverloading {
    public static void main(String[] args){
        System.out.println(max(1 , 2));
    }

    public static double max(int num1, double num2){
        if (num1 > num2){
            return num1;
        }else{
            return num2;
        }
    }

    public static double max(double num1,int num2){
        If (num1 > num2){
            return num1;
        }else{
            return num2;
        }
    }
}

max(int,double)max(doubleint)都有可能与 max(1,2)匹配由于两个方法谁也不比谁更精确,所以这个调用是有歧义的它会导致一个编译错误

 

 

6.7 变量的作用域

变量的作用域scope ofa variable) 是指变量可以在程序中引用的范围

在方法中定义的变量称为局部变量(local variable)。局部变量的作用域从声明变量的地方开始,直到包含该变量的块结束为止。局部变量都必须在使用之前进行声明和赋值。

参数实际上就是一个局部变量个方法的参数的作用域涵盖整个方法在 for 循环头中初始动作部分声明的变量其作用域是整个 for 循环但是在 for 循环体内声明的变量,其作用域只限于循环体内,是从它的声明处开始,到包含该变量的块结束为止,如下图所示:

可以在一个方法中的不同块里声明同名的局部变量但是不能在嵌套块中或同一块中两次声明同一个局部变量,如下图所示:

警告不要在块内声明一个变量然后企图在块外使用它下面是一个常见错误的例子:

for (int i = 0;i < 10;i++){ 
}
System,out.println(i);

因为变量 i 没有在 for 循环外定义所以最后一条语句就会产生一个语法错误

 

 

6.8 方法抽象和逐步求精

开发软件的关键在于应用抽象的概念

方法抽象method abstraction) 是通过将方法的使用和它的实现分离来实现的。用户在不知道方法是如何实现的情况下,就可以使用方法方法的实现细节封装在方法内,对使用该方法的用户来说是隐藏的这就称为信息隐藏information hiding ) 或封装(encapsulation)如果决定改变方法的实现但只要不改变方法签名,用户的程序就不受影响方法的实现对用户隐藏在 “黑盒子如下图所示

方法抽象的概念可以应用于程序的开发过程中当编写一个大程序时可以使用 分治” ( divid - and - conquer) 策略也称为逐步求精stepwise refinement), 将大问题分解成子问题。子问题又分解成更小、更容易处理的问题

 

方法抽象:

  • 自顶向下的设计
  • 自顶向下和自底向上的实现
  • 实现细节

 

 

逐步求精的优势:

1. 更简单的程序

打印日历的程序比较长逐步求精方法将其分解为较小的方法而不是在一个方法中写很长的语句序列。这样简化了程序使得整个程序易于阅读和理解

2. 重用方法

逐步求精提高了一个程序中的方法重用isLeapYear 方法只定义了一次getTotalNumberOfDays getNumberOfDaysInMonth 方法中都进行了调用这减少了冗余的代码

3. 易于开发调试和测试

因为每个子问题在一个方法中解决而一个方法可以分别的开发调试以及测试这隔离了错误,使得开发调试和测试更加容易。编写大型程序时,可以使用自顶向下或自底向上的方法不要一次性地编写整个程序a 使用这些方法似乎浪费了更多的开发时间(因为要反复编译和运行程序)但实际上它会更节省时间并使调试更容易。

4. 更方便团队合作

当一个大问题分解为许多子问题各个子问题可以分配给不同的编程人员。这更加易于编程人员进行团队工作。

 

 

 

 

 

附录

 

 

 

编译运算练习

1.

 

 

2.

 

 

3.

 

 

4.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值