什么是方法
方法是程序中最小的执行单元
方法有什么作用
如果有重复的代码,就可以将重复的部分打包成方法,要使用的话就可以直接调用这个方法

我们可以将发射的代码进行打包,如有需要就可以直接进行调用

这可以提高代码的复用性和提高代码的可维护性
易于维护: 如果有一天你想把"送人头"改成"拿五杀",你只需要修改 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

传递引用数据类型时,传递的是地址值,形参的改变,影响实际参数的值
结论
