一、方法
1、方法的定义及调用
1.1定义
[修饰符列表] 返回值类型 方法名(形式参数列表){
方法体;
}
例如代码:
public static void sumInt(int a , int b){
int c = a + b;
System.out.println(a + "+" + b + "=" + c);
}
public static 是修饰符列表;
void是返回值类型;
sumInt 是方法名;
(int a , int b)是形式参数列表,简称形参,每一个形参都是局部变量;
形参后面使用一对儿大括号括起来的是方法体,方法体是完成功能的核
心代码,方法体中的代码有执行顺序的要求,遵循自上而下的顺序依次逐行 执行,不存在跳行执行的情况。
再如代码:
public static int sumInt(int a , int b){
int c = a + b;
return c;
} 以上程序中 sumInt 之前的 int 是返回值类型
1.2方法的调用
不同类中:类名.方法名。
同一个类中,可以省略类名。
2、方法返回值详解
每个方法都是为了完成某个特定的功能,例如:登录功能、求和功能等,既然是功能,那么当这个功能完成之后,大多数情况下都会有一个结果的,比如,登录成功了或者失败了 (true/false),求和之后最后的结果是100 或者 200,当然也有极少数的情况下是没有结果的。 这个结果本质上就是一个数据,那么既然是一个数据,就一定会有对应的类型,所以在方法定 义的时候需要指定该方法的返回值类型。
java语言中方法的返回值类型可以是任何一种数据类型,包括基本数据类型,也包括引用数据类型,例如:byte,short,int,long,float,double,boolean,char,String,Student(自定义类)等。当 然,如果这个方法在执行完之后不需要返回任何数据,返回值类型必须写 void 关键字,不能空着不写。
方法执行完后,需接受一个返回值,该返回值类型与定义方法时的数据类型必须一样,一般用return返回。带有return关键字的语句只要执行,所在的方法则执行结束。
return和break的区别:
我们可以得出 break和 return根本不是一个级别的,break用来终止循环, return用来终止一个方法的执行。需要注意的是:“return;”只能出现在返回值类型是 void的方法中。
方法执行结束之后的返回值我们可以接收,也可以不接收,不是必须的,但大多数情况下方法的返回值还是需要接收的,要不然就没有意义了,另外方法的 返回值在接收的时候采用变量的方式接收,要求这个变量的数据类型和返回值类型一致(当然, 也可以遵守自动类型转换规则)。
3、栈数据结构
栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是:仅允许在表的一端进行插
入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作 进栈、入栈或压栈(push),它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从 一个栈删除元素又称作出栈、退栈或弹栈(pop),它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
栈数据结构存储数据的特点:先进后出,或者后进先出原则。也就是说最先进去的元素一定是最后出去,最后进去的元素一定是最先出去,因为 一端是开口的,另一端是封闭的。
4、方法执行过程中内存的变化
先看一张图:
上图是一张标准的 java虚拟机内存结构图,目前我们只看其中的“栈”和“方法区”,其它的后期研究,方法区中存储类的信息,或者也可以理解为代码片段,方法在执行过程中需要 的内存空间在栈中分配。java程序开始执行的时候先通过类加载器子系统找到硬盘上的字节码 (class)文件,然后将其加载到 java虚拟机的方法区当中,开始调用main方法,main方法被调 用的瞬间,会给main方法在“栈”内存中分配所属的活动空间,此时发生压栈动作,main方 法的活动空间处于栈底
也就是说,方法只定义不去调用的话,只是把它的代码片段存储在方法区当中,java虚拟机是不会在栈内存当中给该方法分配活动空间的,只有在调用的瞬间,java虚拟机才会在“栈 内存”当中给该方法分配活动空间,此时发生压栈动作,直到这个方法执行结束的时候,这个 方法在栈内存中所对应的活动空间就会释放掉,此时发生弹栈动作。由于栈的特点是先进后出, 所以最先调用的方法(最先压栈)一定是最后结束的(最后弹栈)。比如:main 方法最先被调用,那么它一定是最后一个结束的。换句话说:main 方法结束了,程序也就结束了(目前 来说是这样)
二、方法重载(overload)
方法重载(overload)是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。调用重载方法时,Java编译器能通过检 查调用的方法的参数类型和个数选择一个恰当的方法。方法重载通常用于创建完成一组任务相 似但参数的类型或参数的个数不同的方法。调用方法时通过传递给它们的不同个数和类型的实 参来决定具体使用哪个方法。
什么情况下我们考虑使用方法重载呢?在同一个类当中,如果多个功能是相似的,可以考虑将它们的方法名定义的一致,使用方法重载机制,这样便于程序员的调用,以及代码美观, 但相反,如果两个方法所完成的功能完全不同,那么方法名也一定要不一样,这样才是合理的。
代码满足什么条件的时候构成方法重载呢?
满足以下三个条件:
① 在同一个类当中。
② 方法名相同。
③ 参数列表不同:个数不同算不同,顺序不同算不同,类型不同也算不同。
三、方法递归
递归其实就是方法在执行的过程中调用了另一个方法,而另一个方法则是自己本身。使用递归须谨慎,因为递归在使用的时候必须有结束条件,没有结束条件就会导致无终止的压栈,栈内存最终必然会溢出,程序因错误的发生而终止
思考一个问题,一个递归程序有合法有效的结束条件就一定不会发生栈内存溢出 错误吗?在实际开发中遇到这个错误应该怎么办?
一个递归程序有的时候存在合法有效的终止条件,但由于递归的太深,在还没有等到条件成立的时候,栈内存已经发生了溢出,这种情况也是存在的,所以实际开发中我们尽可能使用 循环来代替递归算法,原则是:能不用递归尽量不用,能用循环代替的尽可能使用循环。当然, 如果在开发中遇到了由于使用递归导致栈内存溢出错误的发生,首先,我们要检查递归的终止条件是否合法,如果是合法的还是发生栈内存溢出错误,那么我们可以尝试调整堆栈空间的大小。
1到N求和的递归代码:
public class RecursionTest03 {
public static void main(String[] args){
int n = 5;
int result = accumulate(n);
System.out.println("1 到" + n + "的和是:" + result);
}
public static int accumulate(int n){
if(n == 1){
return 1;
}
return n + accumulate(n - 1);
}
}
总结
本章节内容主要了解了 Java 中方法相关的语法机制,其实这个在 C 语言中被称为函数,一般在开发中我们都会把独立的功能单独定义成一个方法,在需要的时候调用就行了,这样可以让写过的代码得到重复利用。
方法的定义、执行过程以及会画方法执行过程的内存变化需要掌握。另外还要掌握方法的重载机制,以及方法的递归算法。尤其是递归时的内存变化有助于我们对递归执行原理的理解。