方法

定义方法

要点提示 : 方法可以用于定义可重用的代码以及组织和简化编码 。

要点提示 : 方法的定义由方法名称 、 参数 、 返回值类型以及方法体组成。

定义方法的语法如下所示 :

方法可以返回一个值 。 retumValiieType 是方法返回值的数据类型 。 有些方法只是完成某些要求的操作 , 而不返回值 。 在这种情况下, retuniValueType 为关键字 void。

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

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

瞥告 : 在方法头中 , 需要对每一个参数进行独立的数据类型声明 。 例如 : max ( int numl , 1 nt num 2 ) 是正肩的 , 而 max ( int numl , mim 2 ) 是错误的 。

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

调用方法

要点提示 : 方法的调用是执行方法中的代码。

在方法定义中 , 定义方法要做什么 。 为了使用方法 , 必须调用 ( cal 丨或 invoke ) 它 。 跟据方法是否有返回值 , 调用方法有两种途径 。

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

如果方法返回 void , 对方法的调用必须是一条语句 。

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

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

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

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

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

要点提示 : void 方法不返回值 。

通过传值进行参数传递

要点提示 : 调用方法的时候是通过传值的方式将实参传给形麥的 。

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

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

模块化代码

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

通过将求最大公约数的代码封装在一个方法中 , 这个程序就具备了以下几个优点 :

1 ) 它将计算最大公约数的问题和 main 方法中的其他代码分隔开 , 这样做会使逻辑更加清晰而且程序的可读性更强 。

2 ) 计箅最大公约数的错误就限定在 gcd 方法中 , 这样就缩小了调试的范围 。

3 ) 现在 , 其他程序就可以重复使用 gcd 方法 

重载方法

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

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

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

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

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

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

变置的作用域

要点提示 : 变量的作用域 ( scope of a variable ) 是指变量可以在程序中引用的范围 。

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

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

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

瞀告 : 不要在块内声明一个变量然后企图在块外使用它。

示例学习 : 生成随机字符

 要点提示 : 字符使用整數来编码 。 产生一个随机字符就是产生一个随机整數 。

计算机程序处理数值数据和字符 。 前面已经看到了许多涉及数值数据的例子 。 了解字符和如何处理字符也是很重要的 。

 每个字符都有一个唯一的在十六进制数 0 到 FFFF ( 即十进制的6 S 53 S ) 之间的 Unicode 。 生成一个随机字符就是使用下面的表达式 , 生成从 0 到 6 S 53 S 之间的一个随机整数 ( 注意 : 因为 0 < = Math . random () < l _ 0 , 必须给 6 S 53 S 上加 1 ) :

( int )( Math . random () * ( 65535 + 1 ) )

现在让我们来考虑如何生成一个随机小写字母 。 小写字母的 Unicode 是一串连续的整数 , 从小写字母 i 的 Unicode 开 始 , 然 后 是'b'、'c'、····和'z'的 Unicode。'a'的Unicode 是 :

所以 , ( int ) 4 • 到 ( int ) ' z • 之间的随机整数是 :

自顶向下的设计

如何开始编写这样一个程序呢 ? 你会立即开始编写代码吗 ? 程序员新手常常一开始就想解决每一个细节 。 尽管细节对最终程序很重要, 但在前期过多关注细节会阻碍解决问题的进程 。 为使解决问题的流程尽可能地流畅 , 本例先用方法抽象把细节与设计分离 , 只在后面才实现这些细节 。对本例来说 , 先把问题拆分成两个子问题 : 读取用户输人和打印该月的日历 。 在这一阶段 , 应该考虑还能分解成什么子问题 , 而不是用什么方法来读取输入和打印整个日历 。 可以画一个结构图 , 这有助于看清楚问题的分解过程 ( 参见图 6 - 8)。

你可以使用 Scanner 来读取年和月份的输人 。 打印给定月份的日历问题可以分解成两个子问题 : 打印日历的标题和日历的主体 , 如图 6 - 8 b 所示 。 月历的标题由三行组成 : 年月 、虚线 、 每周七天的星期名称 。 需要通过表示月份的数字 ( 例如 : 1 ) 来确定该月的全称 ( 例如 : January ) 。 这个步骤是由 getMonthName 来完成的 ( 参见图 6 - 9 a ) 

为了打印日历的主体 , 需要知道这个月的第一天是星期几 ( getStartDay ) , 以及该月有多少天 ( getNumberO « ) aysInMonth ) , 如图 6 - 9 b 所示 。 例如 : 2013 年 12 月有 31 天 , 2013 年12 月丨号是星期天 。

怎样才能知道一个月的第一天是星期几呢 ? 有几种方法可以求得 。 这里 , 我们采用下面的方法 。 假设知道 1800 年丨月 1 日是星期三 ( START _ DAY _ F 0 R _ ] AN _ l _ 1800 - 3 ) , 然后计算 1800 年 1 月 1 日和日历月份的第一天之间相差的总天数 ( totalNumberOfDays ) 。 因为每个星期有 7 天 , 所以日历月份第一天的星期就是 ( totalNumberOfDayS + START _ DAY _ FOR _〕 AN _ 1 _ 1800 ) X 7 。 这样 getStartDay 问题就可以进一步细化为 getTotalNumberOfDays , 如图6 - 10 a 所示 。

要计算总天数 , 需要知道该年是否是闰年以及每个月的天数 。 所以 , getTotalNumber -OfDays 可以进一步细化成两个子问题 : isLeapYear 和 getNumberOfDaysInMonth , 如图 6 - 10 b 所示。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值