JAVA学习笔记day06
什么是方法
方法是程序中最小的执行单元
方法有什么作用
如果有重复的代码,就可以将重复的部分打包成方法,要使用的话就可以直接调用这个方法
我们可以将发射的代码进行打包,如有需要就可以直接进行调用
这可以提高代码的复用性和提高代码的可维护性
易于维护:如果有一天你想把“送人头”改成“拿五杀”,你只需要修改playGame方法里面的那一行,所有调用它的地方都会跟着变。如果不打包,你得一个一个去改,很容易漏掉。
在实际开发中,我们会将有重复的代码、具有独立功能的代码抽取到方法中,以后有用到就不需要再写可以直接调用方法
方法的格式
方法就是将代码打包在一起,用的时候就调用
方法的定义:把一些代码打包在一起,该过程称为方法的定义
方法的调用:方法定义后并不是直接运行的,需要手动调用才能执行,该过程称为方法调用
方法的定义格式:
最简单的方法的定义和调用
方法的定义:
public static void 方法名() { 方法体(就是打包起来的代码); }方法的调用:
方法名();主要:方法必须先定义后调用,否则程序将会报错
方法的定义要写在main方法的外面,类的里面
方法的调用是在main方法里面
调用两次游戏
package demo1; public class Test2 { public static void main(String[] args) { playGame(); playGame(); } public static void playGame(){ System.out.println("选择人物"); System.out.println("准备开局"); System.out.println("对线"); System.out.println("崩盘"); System.out.println("骂队友"); System.out.println("送人头"); System.out.println("GG"); } }练习1:
package demo1; public class Test2 { public static void main(String[] args) { printGFInfo(); } public static void printGFInfo(){ System.out.println("姓名:小红"); System.out.println("年龄:18岁"); System.out.println("职业:学生"); } }练习2:
看到方法进入方法,执行完毕回到调用处
练习3:
人肉计算器
需求:定义一个方法,在方法内部定义两个变量。
求出他们的和并进行打印
package demo1; public class Test2 { public static void main(String[] args) { getSum(); } public static void getSum(){ int number1 = 10; int number2 = 20; int sum = number1 + number2; System.out.println(sum); } }带参数的方法的定义和调用
当参数值不确定时,我们就可以将参数定义在方法名后面的小括号中,在调用这个方法时根据不同的情况来传入值
注意:方法调用时,参数的数量与类型必须与方法定义中小括号里面的变量一一对应,否则程序将报错。
练习1:
package demo1; public class Test2 { public static void main(String[] args) { getSum(12,35); } public static void getSum(int number1,int number2){ int sum = number1 + number2; System.out.println(sum); } }形参和实参
例如:
练习1:
人肉计算机1
需求:定义一个方法,求长方形的周长,将结果在方法中进行打印。
package demo1; public class Test2 { public static void main(String[] args) { getLength(35,12); } public static void getLength(double len,double width){ double result = len*2+width*2; System.out.println(result); } }练习2:
人肉计算机2
需求:定义一个方法,求圆的面积,将结果在方法中进行打印。
package demo1; public class Test2 { public static void main(String[] args) { printCircleArea(12); } public static void printCircleArea(double radius){ double area = Math.PI*radius*radius; System.out.println(area); } }带返回值方法的定义和调用
带返回值方法的调用
练习1:
人肉计算机
需求:定义一个方法,求一家商场每个季度的营业额。
根据方法结果再计算出全年营业额。
package demo1; public class Test2 { public static void main(String[] args) { //先计算第一个季度的营业额 int sum1 = getSum(10,20,30); //先计算第二个季度的营业额 int sum2 = getSum(20,40,30); //先计算第三个季度的营业额 int sum3 = getSum(10,50,30); //先计算第四个季度的营业额 int sum4 = getSum(40,70,30); //求全年的总营业额 int sum =sum1+sum2+sum3+sum4; System.out.println(sum); } public static int getSum(int num1, int num2, int num3){ int sum = num1 + num2 + num3; return sum; } }这时参数就有了值,那么在getSum方法中的result就是60,返回的结果就是60,方法的返回值是返回给了调用处,所以int sum = 就是返回值的结果60
练习1:
比较大小
需求:定义方法,比较两个长方形的面积。
写之前要问自己三个问题
1.我要干什么
2.需要什么
3.方法的调用处,是否需要继续使用方法的结果。如果要用那么方法必须有返回值,如果不用,方法可以写返回值,也可以不写返回值
package demo1; public class Test2 { public static void main(String[] args) { double area1=getArea(5.0,3.0); double area2 =getArea(6.0,4.0); if(area1>area2){ System.out.println("第一个长方形更大"); }else{ System.out.println("第二个长方形更大"); } } public static double getArea(double len , double width){ double area = len*width; return area; } }方法的注意事项
return
方法没有返回值:可以省略不写。如果书写,表示结束方法
方法有返回值:必须要写。表示结束方法和返回结果
方法的重载
在同一个类中,定义了多个同名的方法,这些同名的方法具有相同的功能。
每一个方法具有不同的参数类型或参数个数,这些同名的方法,就构成了重载关系
简单记忆:同一个类中,方法名相同,参数不同的方法,与返回值无关
参数不同:个数不同,类型不同,顺序不同
Java虚拟机会通过不同的参数来区分同名的方法
练习:区分以下方法是否构成重载关系
这个是因为不在一个类中
在同一个类的相同方法,个数相同,类型相同,但是顺序不同,但是不建议使用这种重载关系
练习2:
方法重载
需求:使用方法重载的思想,设计比较两个整数是否相同的方法。要求:兼容全整数类型(byte,short,int,long)
package demo1; public class Test2 { public static void main(String[] args) { compare(10,20); compare((byte) 10,(byte) 10); long n1 = 10; long n2 = 40; compare(n1,n2); } public static void compare(byte a,byte b){ System.out.println("byte:"); System.out.println(a==b); } public static void compare(short s1,short s2){ System.out.println("short:"); System.out.println(s1==s2); } public static void compare(int c1,int c2){ System.out.println("int:"); System.out.println(c1==c2); } public static void compare(long n1,long n2){ System.out.println("long:"); System.out.println(n1==n2); } }好处:
定义方法的时候可以不用那么多的单词了
调用方法的时候也不需要那么麻烦了。
练习1:
数组遍历
需求:设计一个方法用于数组遍历,要求遍历的结果是在一行上的。例如:[11,22,33,44,55]
package demo1; public class Test2 { public static void main(String[] args) { //1.先定义一个数组 int[] array={11,22,33,44,55}; //3.调用方法遍历数组 printArray(array); } //2.定义方法用于数组遍历 //我要干什么 遍历数组 //我干这件事情需要什么才能完成 数组 //方法的调用处是否需要继续使用结果? 不需要返回值 public static void printArray(int[] array){ System.out.print("["); for(int i=0;i<array.length;i++){ if(i==array.length-1){ System.out.print(array[i]); }else{ System.out.print(array[i]+", "); } } System.out.print("]"); } }System.out.println("abc"); //先进行打印abc,然后再进行换行 System.out.print("cbf"); //只打印cbf,不换行 System.out.println(); //不打印任何数据,只做换行处理练习2:
数组最大值
需求:设计一个方法求数组的最大值,并将最大值返回
package demo1; public class Test2 { public static void main(String[] args) { //1.先定义一个数组 int[] array = {11, 22, 33, 44, 55}; //3.调用方法求最大值 int max = getMax(array); System.out.println("数组的最大值:"+max); } //2.定义方法用于求最大值 //我要干什么 求最大值 //我干这件事情需要什么才能完成 数组 //方法的调用处是否需要继续使用结果? 需要返回值 public static int getMax(int[] array) { int max = array[0]; for (int i = 1; i < array.length; i++) { if(max<array[i]){ max = array[i]; } } return max; } }练习3:
定义一个方法判断数组中的某一个数是否存在,将结果返回给调用处
package demo1; public class Test2 { public static void main(String[] args) { //1.先定义一个数组 int[] array = {11, 22, 33, 44, 55}; //3.调用方法求是否存在 boolean flag = contains(array,4); System.out.println("是否存在:"+flag); } //2.定义方法用于求是否存在 //我要干什么 求是否存在 //我干这件事情需要什么才能完成 数组 数字 //方法的调用处是否需要继续使用结果? 需要返回值 public static boolean contains(int[] array,int number) { for (int i = 1; i < array.length; i++) { if(array[i]==number){ return true; } } //当数组中的所有数字全部比较完毕之后,才能断定是false return false; } }练习4:
复制数组
需求:定义一个方法copyOfRange(int[]arr,int from,int to)
功能:将数组arr中从索引from(包含from)开始。到索引to结束(不包含to)的元素复制到新数组中,将新数组返回。
索引3到7
package demo1; public class Test2 { public static void main(String[] args) { //1.定义原始数组 int[] array = {1,2,4,6,88,9,45,6}; //3.调用方法拷贝数据 int[] copyArr = copyOfRange(array,2,7); for(int i=0;i<copyArr.length;i++){ System.out.println(copyArr[i]); } } //2.将数组中从索引from(包含from)开始,到索引to(不包含to)结束的元素复制到新数组中 public static int[] copyOfRange(int[]array,int from,int to){ //定义数组 int[] newArray=new int[to-from]; //将原始数组array中的从from到to对应的元素直接拷贝到newArray中 //伪造索引的思想 int index=0; for(int i=from;i<to;i++){ //数组名[索引] = 数据值; newArray[index]= array[i]; index++; } return newArray; } }方法的内存
1.方法调用的基本内存原理
2.方法传递基本数据类型的内存原理
3.方法传递引用数据类型的内存原理
Java内存结构
方法调用的基本内存原理
方法被调用之后就会进栈执行
public class MethodDemo { public static void main(String[] args) { int number = 100; sout("number的值为:"+ number); } }1.程序刚运行时main方法就要进栈
2.程序从上往下执行时,第一行是一个变量,所以在main方法里面就会命名一个变量number,它的类型是int,值是100
3.输出number,就是在main方法里找number里面记录的多少,值就是多少
4.代码结束后,main方法就会随之出栈,main方法里面的变量就会随之消失
出栈是先进入的后出去
public class MethodDemo { public static void main(String[] args) { eat(); } public static void eat() { study(); System.out.println("吃饭"); sleep(); } public static void sleep(){ System.out.println("睡觉"); } public static void study(){ System.out.println("学习"); }程序运行先是从上到下依次先是进入main方法,里面记录着eat()方法,
所以下面是eat方法进栈,eat方法的第一行是study方法,
所以study方法进栈,study方法里面是打印输出学习,所以控制行上就出现了学习,当学习打印输出结束后,回到调用处继续往下走,下面是eat方法中的第二行打印输出吃饭,所以在控制行中会出现吃饭,当吃饭打印输出结束后会继续往下执行,eat的第三行是sleep方法,
所以sleep方法会进栈,sleep方法里面是打印输出睡觉,所以控制行上面就会出现睡觉,当睡觉打印输出结束后sleep就会出栈,然后sleep返回调用处,然后继续往下执行,这是eat方法已经全部执行完了,
这是sleep方法出栈后,栈内的情况:
所以eat方法出栈,出栈后回到调用处(main方法中)回到调用处后继续往下执行,发现main方法也执行完了,所以main方法出栈
什么基本数据类型和引用数据类型
强行记忆
基本数据类型
在基本数据类型中变量中存储的是真实的数据
引用数据类型
只要是new出来的都是引用数据类型
数组的格式是int[] arr = new int[]{1,2,4,6,88,9,45,6};其中是在栈终main方法里面,而 new int[]{1,2,4,6,88,9,45,6};是在堆内存中的,如果想要获取数据就要先通过arr找到堆内存中对应的地址值,然后在通过索引找到对应的数据
引用数据类型中的变量中存储的是地址值,
引用:使用了其他空间的数据
从内存的角度去解释:
基本数据类型:数据值是存储在自己的空间中
特点:赋值给其他变量,也是赋的真实的值。
这样当b的数值发生了变化a是不会受其影响
引用数据类型:数据值是存储在其他空间中,自己空间中存储的是地址值。
特点:赋值给其他变量,赋的地址值。
这是如果数组arr1中的值发生了变化,那么arr2中的值也会有所变化
方法传递基本数据类型的内存原理
package demo1; public class Test2 { public static void main(String[] args) { int number = 100; System.out.println("调用change方法前:" + number); change(number); System.out.println(" 调用change方法后: " + number); } public static void change(int number){ number = 200; } }变量只能在所属的方法里面有效
所以在栈中,先是进入main方法,在main方法中有一个int类型的变量number,值为100,继续向下执行就是输出number的值,当控制台出现了number的值后结束,继续先下,调用change方法,所以change方法进栈,然后在change方法中有一个int类型的变量number,这个number的值就是100,继续先下执行change里面的代码,我要将200赋值给number,这是change方法里面的number的值为200,但是要注意是change里面的number的值变成了200,(这是不会影响main里面number的值 ,这是因为变量是有作用范围的,变量只能在所属的方法里面有效),然后继续向下就是},change方法就要出栈,回到调用处,然后继续向下执行打印输出number的值,所以main方法里面的number还是100,打印完成后代码就结束了,所以main方法也要出栈
传递基本数据类型时,传递的是真实的数据,形参的改变,不影响实际参数的值
如果在change方法处加上返回值(return number)这代表要将number的值返回调用处,然后再将number=change(number),这是第二个返回值就是200
package demo1; public class Test2 { public static void main(String[] args) { int number = 100; System.out.println("调用change方法前:" + number); number = change(number); System.out.println(" 调用change方法后: " + number); } public static int change(int number){ number = 200; return number; } }数组
package demo1; public class Test2 { public static void main(String[] args) { int[] arr = {10, 20, 30}; System.out.println("调用change方法前:" + arr[1]); change(arr); System.out.println("调用change方法后:" + arr[1]); } public static void change(int[] arr) { arr[1] = 200; } }这段代码在执行时是main方法先进栈,main方法里面有int[] arr =对应的地址值
接着打印输出arr[1]对应的值20(就是现在栈中的main中找到arr对应的地址值,知道地址值后可以到堆内存中找对应1索引的值20)打印完成后
调用change方法,change方法进栈,change方法里面有int[] arr =对应的地址值
但是arr对应的索引1的值是200,所以堆内存的索引1对应的值也要改为200
完成后change方法就要出栈,但是堆内存里面改成200后就不会因为change方法出栈而变化,所以接下来要打印输出arr[1]时找到的堆内存所对应的值为200
传递引用数据类型时,传递的是地址值,形参的改变,影响实际参数的值
结论
