方法是为完成一个操作而组合在一起的语句组。比如我们最早接触的在Java 库中预定义的方法,例如:System.out.println、System.exit、Math . pow 和 Math .random,接下来我会分享如何定义自己的方法以及应用方法抽象来解决复杂问题。
一、定义方法
1、方法的定义由方法名称
、参数、
返回值类型以及方法体组成
。
2、定义方法的语法如下所示
:
修饰符 返回值类型 方法名( 参数列表 ){
方法体 ;
}
3、名词解释:
1)方法头:是由方法的修饰符、
返回值类型
、
方法名
和方法的参数组成。
2)带返回值的方法:方法有返回值
3)
void
方法:方法没有返回值
4)形式参数:定义在方法头中的变量就是形式参数,也叫形参。
5)实际参数:当调用方法时
,
就给参数传递一个值
,
这个值称为实际参数,也叫实参。
6)参数列表:
指明方法中参数的类型、顺序和个数
。
7)方法签名:由方法名和参数列表一起构成。
注:
1)
方法可以返回一个值。
有些方法只是完成某些要求的操作,
而不返回值
。
在这种情况下
其关键字
void
。
例如
:
在
main
方法中 方法返回值的数据类型 就是
void
,
在
System
.
exit、
System
.
out
.
pri
nt
ln
方法中返回值类型也是如此。
2)
参数是可选的
,
也就是说, 方法可以不包含参数。
例如
:
Math
.
randomO
方法就没有参数
3)在其他某些语言中
,
方法称为过程
(
procedure
)
或函数
(
fimction
)
。
带返回值的方 法称为函数,
返回值类型为
void
的方法称为过程
。
4)在方法头中,
需要对每一个参数进行独立的数据类型声明
。
例如
:
sub
(
int numl,
1
nt
num
2
)
是正确的
,
而
sub
(
int
numl
,
mim
2
)
是错误的
。
5)
“
定义方法
”
和
“
声明变量
”
的细微差别
。
定义是指被定义的条目是什么,
而声明通常是指为被声明的条目分配内存来存储数据
。
函数传参图示
二、调用方法
1、调用方法就是指执行方法中的代码。
2、调用方法的途径:
1)如果方法返回一个值,对方法的调用通常就当作一个值处理。
例如: int z = sub(7, 3); 调用方法sub(7, 3)并将其结果附给变量 z。另一个把它当作值处理的调用例子是:
System.out.println(sub(7, 3)); 这条语句打印调用方法 sub(7, 3)后的返回值。
2)如果方法返回 void, 对方法的调用必须是一条语句。
例如,println 方法返回 void。下面的调用就是一条语句: System.out.println("Weicome to Java!");
注:
(1)在 Java
中
,
带返回值的方法也可以当作语句调用
。
这种情况下
,
函数调用者只需忽略返回值即可。虽
然这种情况很少见
,
但是
,
如果调用者对返回值不感兴趣
,
这样也是允许的。
(2)当程序调用一个方法时
,
程序控制就转移到被调用的方法
。
当执行完
return
语句或执行到表示方法结束的右括号时,
被调用的方法将程序控制返还给调用者。对带返回值的方法而言,return 语句是必需的。
3、方法能够带来代码的共享和重用
。除了可以在 TestSub
中调用
sub
方法
,
还可以在其他类中调用它。
如果创建了一个新类
,
可以通过使用
“
类名
.
方法名
”
(
即 TestSub .
sub
) 来调用 sub
方法。
4、方法到底是如何被调用的?
第一种:通过对象名.方法名进行调用,这是最普通的也是最常见的一种调用方式。
第二种:通过new关键字调用构造方法,这种是在实例化对象时使用的方式。
第三种:通过类名.方法名调用,当需要调用的那个方法为静态(有static的)方法时使用。
注:
1、调用方法时
,
需要提供实参
,
它们必须与方法签名中 所对应的形参次序相同。
这称作参数顺序匹配。实参必须与方法签名中定义的参数在次序和数量上匹配,
在类型上兼容
。
类型兼容 是指不需要经过显式的类型转换,
实参的值就可以传递给形参
,
例如
,将 int
型的实参值传递给 double
型形参。
2、形参是方法中具有自己存储空间的变量
。
局部变量是在调用方法时分配的,
当方法返回到调用者后它就消失了
。
三、方法栈
方法的运行是基于栈内存的,栈是一个先进后出的一个容器结构,如子弹按顺序123456进栈,按顺序出栈654321,可以将每一
个函数理解为是子弹(函数帧/栈帧),位于栈顶的函数帧优先运行的,主函数绝对是第一个进栈的。
return结束当前函数 -> 当前函数弹栈
方法栈运行流程图示
四、模块化代码
模块化使得代码易于维护和调试
,
并且使得代码可以被重用
。 使用方法可以减少冗余的代码,
提高代码的复用性
。
方法也可以用
来模块化代码
,
以提高程序的质量。通过将求最大公约数的代码封装在一个方法中,这个程序就具备了以下几个优点:
1 )
它将计算最大公约数的问题和 main 方法中的其他代码分隔开,这样做会使逻辑更加清晰而且程序的可读性更强。
2 ) 计箅最大公约数的错误就限定在 gcd 方法中,这样就缩小了调试的范围。
3 ) 现在,其他程序就可以重复使用gcd方法。
五、重载方法
1、重载方法使得你可以使用同样的名字来定义不同方法
,只要它们的签名不同即可,java编译器根据方法签名决定使用哪个方法。
2、重载的优点:可以使得程序更加清楚,
以及更加具有可读性
。
执行同样功能但是具有不同参数类型的方法应该使用同样的名字。
注
:
1)
被重载的方法必须具有不同的参数列表
。
不能基于不同修饰符或返田值类型来重载方法。
2)有时调用一个方法时
,
会有两个或更多可能的匹配
,
但是
,
编译器无法判断哪个是最精确的匹配。
这称为歧义调用
(
ambiguous
invocation
)
。
歧义调用会产生一个编译错误
。
考虑如下代码
:
class Test01{
public static void main(String[] args){
System.out.println(add(3,3));
}
public static double add(int a,double b){
System.out.println("int+double");
return a+b;
}
public static double add(double a,int b){
System.out.println("double+int");
return a+b;
}
}
六、变量的作用域
变量的作用域是指变量可以在程序中引用的范围。
局部变量:在方法中定义的变量,其
作用域从声明变量的地方开始,直到包含该变量的块结束为止。
局部变量都必须
在使用之前进行声明和陚值
。可以在一个方法中的不同块里声明同名的局部变量,但是不能在嵌套块中或同一块中两次声明同一
个局部变量,— 个变量可以在非嵌套的块中多次声明,而在嵌套块中只能声明一次。不要在块内声明一个变量然后企图在块外使
用它。下面是一个常见错误的例子:
int sum = 0;
for(int i =1;i<=8;i++){
sum =sum + i;
}
i=sum + 1;
System.out.print(i);
因为变量
i
没有在
for
循环外定义
,
所以i = sum + 1;就会产生一个语法错误。
全局变量:
在方法外定义的变量,在整个工程文件内都有效;即从定义变量的位置到本源文件结束都有效。由于同一文件中的所
有函数都能引用全局变量的值,因此如果在一个函数中改变了全局变量的值, 就能影响到其他函数中全局变量的值。