目录
一、方法的定义和调用
方法是一种语法结构,它可以把一段代码封装成一个功能,方便调用。
方法的定义:
方法的调用:
方法名(...)
使用方法的好处:
- 提高了代码的复用性
- 让程序的逻辑更清晰
其他的定义格式:
无参数无返回值 public static void name()。调用时不需要定义变量接受结果,直接调用name()。
方法写完要记得对方法的功能进行注释只需要输入 /**加回车
/**
* 根据学生的学号查询学生对象返回
* @param students 存储全部学生对象的集合
* @param number 搜索的学生的学号
*/
public static void getStudentId(ArrayList<Student> students,String number ) {
}
二、方法定义的常见问题
- 方法的编写顺序无所谓,可以在main函数上面也可以在下面
- 方法与方法之间是平级关系,不能嵌套定义。
public static void main(String[] args) {
public static int add(int a,int b) {
//在main函数中嵌套定义 会报错
}
}
- 方法的返回值类型为void(无返回值类型),方法中不能使用return返回数据,调用时也不需要定义变量接返回值;如果方法的返回值声明了具体类型,方法内部必须使用return语句。
- return语句下面,不能编写代码,因为永远执行不到,属于无效的代码
- 方法不调用就不执行,调用时必须严格匹配方法的参数情况
三、方法的案例
1、判断奇偶数
public class MethodTest2 {
public static void main(String[] args) {
//判断奇数偶数
judje(6);
}
public static void judje(int a) {
if (a % 2 == 0) {
System.out.println("是偶数");
}
else {
System.out.println("是奇数");
}
}
}
2、求1~n的和
public class MethodTest {
public static void main(String[] args) {
//通过方法计算1~n的和
int sum = add(5);
System.out.println(sum);
}
public static int add(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
return sum;
}
}
3、求数组中的最大值
public class MethodTest3 {
public static void main(String[] args) {
//数组求最值
int[] a = {1,2,3,4,5,6};
System.out.println(max(a));
}
public static int max(int[] a) {
int max = a[0];
for (int i = 0; i < a.length; i++) {
if (a[i] > max) {
max = a[i];
}
}
return max;
}
}
四、方法的调用流程
先将程序的.class文件提到方法区中,方法区有main方法和add方法,然后开始先执行main方法,将main方法提到栈内存中,执行int sum = add(10,20),执行这个代码的过程中程序会先暂停,寻找add方法,将add方法提到栈内存中,将10传给a,20传给b,在add方法内部就会开辟一个空间分别存放a,b变量,再执行c = a + b;将得到的结果返回给sum。
结果返回完成add方法退出栈内存,main方法继续执行输出语句,并输出结果,调用完成,退出栈内存,输出结果。
2、 多方法的调用流程
先将程序的.class文件提到方法区中,加载class文件,产生四个方法main、study、sleep、eat。
按顺序调用方法,先将main方法提到栈内存中,调用study()方法,main方法就会暂停,然后寻找study()方法,将study方法提到栈内存中。
在study方法中会先去调用eat方法,将eat方法提到栈内存,执行eat方法输出"吃饭",eat调用完毕退出栈内存,study方法接着执行输出语句输出"学习",再调用sleep方法,将sleep方法提到栈内存中,执行输出语句"睡觉",调用完毕退出栈内存,study方法调用完毕退出栈内存,main方法也调用完毕退出栈内存,清空栈内存。
五、方法的参数传递机制
1、基本类型的参数传递
java的参数传递机制:
在传输实参给方法的形参时,并不是传输实参变量本身,而是传输实参变量中存储的值,这就是值传递。
实参:方法内部定义的变量
形参:在定义方法时,“( )”中声明的参数
在基本类型的参数传递中,调用方法不能改变变量本身的值
面试题:调用方法后a的值是多少?
先将.class文件加载到方法区,main方法和change方法,先运行main方法,将main方法提到栈内存中,开辟一块空间存储 a=10,接着调用change方法,将change方法提到栈内存将int a = 10中的值10传递给change方法中,change方法会在栈内存中开辟一块区域来存储a = 10,然后进行输出语句,再修改内部形参变量a的值为20,再进行输出语句,结束change方法,退出栈内存,回到main方法中输出实参a的值为10。在这个过程中改变的是形参的值而实参没有改变。
2、引用类型的参数传递
引用类型的参数传递也是值传递,但是参数中存放的值是引用的地址,因此可能会产生实参的改变
面试题:arrs[1]的值是否发生变化
先将.class文件加载到方法区,main方法和change方法,先运行main方法,将mian方法提到栈内存,为数组变量开辟一块区域(等号左边),在堆内存中开辟一块区域,创建数组对象,将数据存放在区域中(等号右边),将数组地址赋给数组变量中存储(等号),使数组变量指向数组对象,再调用change方法,通过值传递将数组变量中存储的地址传递给change方法。
接着将change方法提到栈内存中,change方法中的形参arrs存储的也是数组的地址,执行第一条输出语句输出arrs[1]的值,执行下一条语句,将数组中arrs[1]的值修改为222,再执行下一条输出语句,change方法调用完成退出栈内存,再执行main方法中的输出语句,输出arrs[1]的值,此时arrd[1]的值已经被修改。
六、方法的参数传递案例
1、打印数组内容
打印数组内容,格式为[11,22,33,44]
public class MethodParamDemo1 {
public static void main(String[] args) {
//参数传递实例1:打印整型数组内容
int[] a = {11,22,33,44,55};
conlog(a);
}
public static void conlog(int[] a ) {
System.out.print("[");
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + ",");
}
System.out.println("]");
}
}
[11,22,33,44,55,]
代码优化,去除末尾逗号
public class MethodParamDemo1 {
public static void main(String[] args) {
//参数传递实例1:打印整型数组内容
int[] a = {11, 22, 33, 44, 55};
conlog(a);
}
public static void conlog(int[] a) {
System.out.print("[");
//优化2、考虑传入数组为空的情况
if (a != null && a.length > 0) {
for (int i = 0; i < a.length; i++) {
/*优化1、当打印到最后一个元素时不接逗号
if (i == a.length - 1) {
System.out.print(a[i]);
}
else {
System.out.print(a[i] + ",");
}*/
//一行优化
System.out.println(i == a.length - 1 ? a[i] : a[i] + ",");
}
}
System.out.println("]");
}
}
2、查询数组元素的索引
public class MethodParamDemo2 {
public static void main(String[] args) {
//从数组中查询指定元素的索引
int[] a = {11,22,33,44};
int b = index(a,22);
System.out.println(b);
}
public static int index(int[] arr,int a) {
//判断数组不为空
if (arr != null && arr.length > 0) {
//遍历数组,找到指定元素的索引并输出
for (int i = 0; i < arr.length; i++) {
if (arr[i] == a) {
//方法中一旦执行return语句,则表明方法调用完成
return i;
}
}
}
else {
System.out.println("数组为空");
}
return -1;
}
}
3、比较两个数组内容是否一样
public class MethodParamDeno3 {
public static void main(String[] args) {
//比较两个数组内容是否一样
int[] a = {1,2,3,4,5};
int[] b = {1,5,3,2,5};
System.out.println(compare(a, b));
}
public static Boolean compare(int[] a, int[] b) {
int j = 0;
//判断数组是否完全一样
if (a.length == b.length) {
for (int i = 0; i < a.length; i++) {
if (a[i] == b[i]) {
j++;
}
}
/*判断数组元素是否相同
for (int i = 0; i < a.length; i++) {
for (int i1 = 0; i1 < b.length; i1++) {
if (a[i] == b[i1]) {
j++;
}
}
}*/
//通过查看j的值是否等于数组长度判断
if (j == a.length) {
return true;
}
else {
return false;
}
} else {
return false;
}
}
}
进行代码优化
public class MethodParamDeno3 {
public static void main(String[] args) {
//比较两个数组内容是否一样
int[] a = {1,2,3,4,5};
int[] b = {1,5,3,2,5};
System.out.println(compare(a, b));
}
public static Boolean compare(int[] a, int[] b) {
//判断数组是否完全一样
if (a.length == b.length) {
for (int i = 0; i < a.length; i++) {
//优化:通过逆向思维,讨论不相等的情况,有一个不相等整个数组都不相等
if (a[i] != b[i]) {
return false;
}
}
} else {
return false;
}
return true;
}
}
七、方法重载
同一个类中,出现多个方法名称相同,但形参列表是不同,那么这些方法就是重载方法。
系统会根据参数不同,匹配对应参数的方法,调用不同的方法。
public class MethodLoad {
public static void main(String[] args) {
//方法重载
fire();
fire("mei国");
fire("mei国",900);
}
public static void fire() {
System.out.println("发射一枚导弹");
}
public static void fire(String location) {
System.out.println("向" + location + "发射一枚导弹");
}
public static void fire(String location,int num) {
System.out.println("向" + location +"发射" + num +"枚导弹");
}
}
1、方法重载的优点:
相同类型的方法设置相同的方法名,例如上面的代码,三个方法都是与发射有关,所以可以定义相同的方法名。方法重载使代码可读性好,方法名称是同一类型的功能,通过形参不同实现功能差异化的选择,这是一种专业的代码设计。
2、方法重载的识别
- 只要是同一个类中,方法名称相同、形参列表不同,那么他们就是重载的方法,其他都不管。(只看方法名称和形参列表)
- 形参列表不同指的是:形参的个数、类型、顺序不同,不关心形参的名称。
八、return关键字的单独使用
return; 可以立即跳出并结束当前方法的执行,return关键字单独使用可以放在任何方法中。