java方法的使用

方法

方法是什么

方法(method)是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集。类似c语言的函数。

注意:

  • 你要执行的方法必须是你已经定义好了的
  • 方法调用,那个方法才会被执行,并不是你定义了这个方法,这个方法就会被执行的

方法定义格式:

无参无返回方法

定义格式:

public static void 方法名 (   ) {
	// 方法体;
}

无参无返回方法调用格式:

方法名();

方法调用的执行过程:

你点击运行,就会运行这个类的main方法,这个main方法就会入栈,然后执行main里面的代码,就执行到了isEvenNumber();方法,因为是调用方法,所以,这个isEvenNumber会开始入栈,且在栈顶,程序是先执行栈顶的方法的,所以main的方法先停住,然后执行isEvenNumber方法里的int number=10;等语句,这个方法执行完后,方法就出栈了,因为是返回类型是void,所以没有放回值,然后继续执行main方法剩下的语句,然后main方法执行完毕就出栈。

注意:每个方法在被调用执行的时候,都会进入栈内存,并且拥有自己独立的内存空间,方法内部代码调用完毕之后,会从栈内存中弹栈消失。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oQ3vxJaI-1657264084831)(第五次任务/无参数方法调用图解-16571844770781.png)]

带参不带返回方法

  1. 定义格式:

    public static void 方法名 (参数1) {//一个参数的方法
    	方法体;
    }
    
    public static void 方法名 (参数1, 参数2, 参数3...) {//多个参数的方法
    	方法体;
    }
    

    参数格式为:数据类型 变量名,比如 int i;

    定义方法的时候的注意点:

    方法定义时,参数中的数据类型与变量名都不能缺少,缺少任意一个程序将报错

    方法定义时,多个参数之间使用逗号( ,)分隔

  2. 调用格式

    方法名(参数);//单个参数的定义的方法的调用
    方法名(参数1,参数2);//多参方法的调用,调用时要写多少个参数主要看,定义的时候的形参个数
    

    注意:

    方法调用时,参数的数量与类型必须与方法定义中的设置相匹配,否则程序将报错

    调用方法的那个实参要可以被形参接收,比如:你定义的时候形参是int,但是调用的时候传了12.1,就不行,这个接收和赋值的接收一样,比如你int i=1.2;就会出错,但是你定义的时候形参是double可以接收int的实参,就像double d=12;是可以的。你形参是double的可以接收一个int的实参。或者你形参是父类,实参可以接受子类的对象,这一点,子类赋值给父类也是可以做到的。

  3. 形参和实参

    形参:方法定义中的参数

    格式与定义变量的格式一样,例如:下面的int number

    实参:方法调用中的参数

    调用方法的时候,那个括号里写的,可以是常量或变量。

    例子:

    public class MethodDemo02 {
        public static void main(String[] args) {
            //直接传递常量
            isEvenNumber( 10 );
            //定义变量,传递
            int number  = 10;
            isEvenNumber( number );
        }
        //接收一个变量,判断该数据是否是偶数
        public static void isEvenNumber(int number) {
            if (number % 2 == 0) {
                System.out.println(true);
            } else {
                System.out.println(false);
            }
        }
    }
    

带返回值方法

  1. 格式

    public static 数据类型 方法名 ( 参数 ) { 
    	return 数据 ;
    }
    
  2. 带返回值的调用要注意的点是:

    方法定义时return后面的返回值与方法定义上的数据类型要匹配,否则程序将报错。

  3. 调用格式:

    格式1:方法名 ( 参数 ) ;

    格式2:数据类型 变量名 = 方法名 ( 参数 ) ;

    像格式1这样,有放回值不设置变量去接收他的,没有关系。但是方法的返回值一般都是会使用变量来接收的,否则该返回值将无意义。

  4. 方法的注意事项

    • 方法应该定义在类下面,不能定义在方法里面。比如

      public class MethodDemo {
          public static void main(String[] args) {
      
          }
      
          public static void methodOne() {
      	//	public static void methodTwo() {
             		// 这里会引发编译错误!!!
          	//}
          }
      }
      
    • void表示无返回值,可以省略return;也可以单独的书写return,但是return后面不加数据,直接跟分号。

    • 还有就是,return;之后,后面要是还有语句的话,将会报错。

      public class MethodDemo {
          public static void main(String[] args) {
      
          }
          public static void methodTwo() {
              //return 100; 编译错误,因为没有具体返回值类型
              return;	
              //System.out.println(100);//报错,提示你return语句后面不能跟数据或代码
          }
      }
      

方法定义的通用格式

  1. 即,不区分有没有放回值,有没有参数的通用格式

    public static 返回值类型 方法名(参数列表/) {
       方法体; 
       return 数据/;
    }
    
  2. 通用格式各部分的解释:

    public static 修饰符,目前先记住这个格式/

    返回值类型 方法操作完毕之后返回的数据的数据类型

    ​ 如果方法操作完毕,不需要返回数据的,这里可以写void,而且返回类型为void的方法的方法体中一般不写return

    方法名 调用方法时候使用的标识,小驼峰命名法

    参数 由数据类型和变量名组成,多个参数之间用逗号隔开,可以为空

    方法体 完成功能的代码块

    return 如果方法操作完毕,若有数据返回,return可以把数据返回给调用者

  3. 设计并定义方法时主要应思考的是:

    • 思考这个方法操作完毕之后需要数据返回,如果没有,写void;如果有,写对应的数据类型
    • 这个方法需要接收的参数、这些参数是什么类型的还有参数的个数
    • 最后才是方法体怎么写,具体怎么实现
  4. 调用方法时的注意:

    • 如果是void类型的方法,直接调用即可
    • 如果是非void类型的方法,推荐用变量接收调用

方法重载

  1. 方法重载的定义:方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载

  2. 条件(总之是不是重载?就只看在一个类下,方法名一样,参数列表不一样,那就是重载方法):

    • 这几个方法在一个类里面
    • 多个方法具有相同的方法名
    • 这多个方法的参数不相同,类型不同或者数量不同,或顺序不同

    注意:

    • 重载仅针对同一个类中方法的名称与参数进行识别,不看放回值(完全不用去看返回值),与返回值无关。换句话说是否相互构成重载,完全不看返回值类型。

    • 调用的时候虚拟机看调用哪一个方法,是先看方法名的,他发现有多个方法名一样的方法,就再看方法的参数列表。要是有实参和形参完全匹配的先考虑那个完全符合的,没有完全符合的再看自动类型转换后是否有匹配的(优先匹配自动转型少的)。

      例子:

      package com.liudashuai;
      public class TwoDimensionArray {
          public static void main(String[] args) {
              compare(12,12);
          }
          public static void compare(long i,long j) {
              System.out.println((i==j)+" 1");
          }
      //    public static void compare(int i,int j) {
      //        System.out.println((i==j)+" 2");
      //    }
          public static void compare(int i,long j) {
              System.out.println((i==j)+" 3");
          }
      }
      这样结果输出:true 3
      
      package com.liudashuai;
      public class TwoDimensionArray {
          public static void main(String[] args) {
              compare(12,12);
          }
          public static void compare(long i,long j) {
              System.out.println((i==j)+" 1");
          }
          public static void compare(int i,int j) {
              System.out.println((i==j)+" 2");
          }
          public static void compare(int i,long j) {
              System.out.println((i==j)+" 3");
          }
      }
      这样输出true 2
      
      package com.liudashuai;
      public class TwoDimensionArray {
          public static void main(String[] args) {
              compare(12,12);
          }
          public static void compare(long i,long j) {
              System.out.println((i==j)+" 1");
          }
      //    public static void compare(int i,int j) {
      //        System.out.println((i==j)+" 2");
      //    }
      //    public static void compare(int i,long j) {
      //        System.out.println((i==j)+" 3");
      //    }
      }
      这样才输出true 1
      
  3. 正确范例:

    public class MethodDemo {
    	public static void fn(int a) {
        	//方法体
        }
        public static int fn(double a) {
        	//方法体
        }
    }
    
    public class MethodDemo {
    	public static float fn(int a) {
        	//方法体
        }
        public static int fn(int a , int b) {
        	//方法体
        }
    }
    
  4. 错误范例:

    public class MethodDemo {
    	public static void fn(int a) {
        	//方法体
        }
        public static int fn(int a) { 	/*错误原因:重载与返回值无关*/
        	//方法体
        }
    }
    
    public class MethodDemo01 {
        public static void fn(int a) {
            //方法体
        }
    } 
    public class MethodDemo02 {
        public static int fn(double a) { /*错误原因:这是两个类的两个fn方法*/
            //方法体
        }
    }
    
  5. 例子:

    void show(int a,char b,double c){}构成重载的有:
    a) void show(int x,char y,double z){} // no
    b) int show(int a,double c,char b){} //yes
    c) void show(int a,double c,char b){} // yes
    d) boolean show(int c,char b){} //yes
    e) void show(double c){} //yes 
    f) double show(int x,char y,double z){} // no
    g) void shows(){double c} // no
    

参数传递

  1. 例子1:

    public class ArgsDemo01 {
        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;
        }
    }
    

    结果:调用方法前和调用方法后的值没有改变。都是输出100。

    结论:方法传一个基本数据类型的实数,然后在方法里面改变形式参数的值,实际参数的值并不会改变。

  2. 原因:不同方法进入栈内存是在不同的栈帧里面的,每个栈帧有他独立的存储空间(所以不同方法可以定义同样的变量名,因为程序会报重复定义变量的错误,是依据本栈帧里面已经有了同样名字的变量,那为什么一个方法里面多个for 循环可以定义 i 变量呢?因为一个方法里面程序运运行出那个变量所在的块,变量就会立即被回收,回收了就没有了,所以后面的for的块里面又可以定义i变量了)。一个栈帧没有能力改变另一个栈帧里面的值,且你在这个栈帧里面的改变只是针对本栈帧的变量。但是成员变量,类的实例,和基本所有对象都是在堆里面存储的,堆里面的数据是共享的,由GC来回收的,所以你某方法建立了一个对象,然后那个方法出栈,并不会回收堆里面的内存,堆里面的数据不会像栈里面那样,运行完了就回收死亡,要GC线程根据GC线程的特有算法决定什么时候回收,反正只要由其他地方用这个对象,这个对象就一定不会自动回收的。所以那个创建对象的那个方法只要把它创建的对象的引用传递出去,别人就可以访问了,并且,就算创建那个对象的方法已经出栈死亡了,别的方法也可以访问那个对象,因为它是由GC线程回收的。

  3. 下面看模型图来理解上面说的原因。

    下面是解释为什么形参改变不会影响实参的模型图。你先调用main方法,main方法入栈,然后运行int number=100;就在main栈帧里面生成一个int number变量,并存了一个100这个值在里面,然后运行change()方法,并传值100,给方法的形参。

    然后结束后,那个change方法就入栈了,且参数列表的定义的变量在change()这个栈帧里面生成,所以在这个change方法里面就存在了int number的变量(这就是为什么方法的括号里面声明的变量看起来也局部变量的效果一样的原因,只是方法的这个形参是比一般的局部变量多了一个传值的作用,其他和局部变量一模一样,生存期和作用域都一样),因为这个方法是被调用的,所以外面的参数的值传进来了number的值变为了100(方法传进来的都是值,就算传引用类型也是传那个里面的值(比如 String s=" ";然后change(s)这样也是传了地址值过来,所以也是值)),然后change方法中的number=200;把number的值给为了200;然后change()方法出栈,方法出栈会把局部变量一起带出栈的,所以那个number就不存在了。然后main在栈顶,所以运行main方法,输出number,就是输出main中的number,这个number在方法change()执行的时候不会被change()的语句影响,所以值还是100,所以输出100。

在这里插入图片描述

  1. 例子2:

    public class ArgsDemo02 {
        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;
        }
    }
    结果是输出
    20
    200
    

    下面是解释例子2。

    结论:方法传递引用类型的值,形参可以靠这个值来影响实际参数的值 。

    解释如下:因为方法change()传递的是引用类型的值,传的是对象的地址,然后change();方法里面用arr[1]=200;改变的是堆里面的那个值,然后change()方法出栈,但是那个堆里面数组的值是依然存在的。然后main里面去访问arr[1]的值,所以输出是200。

    模型图长这样:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N2ZttPGV-1657264084834)(第五次任务/方法传参-引用数据类型.png)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值