方法(Java)

目录

一、什么是方法

二、方法定义

三、实参与形参的关系

四、方法重载

一、什么是方法

           方法是一个代码段,相当于c语言中的函数。

           特点:模块化

                      可被重复使用

                      方便快捷

二、方法定义

    // 方法定义
修饰符 返回值类型 方法名称([参数类型 形参 ...]){
        方法体代码;
[return 返回值];
}


     // 方法调用
方法名(实参...);
返回值变量 = 方法名(实参...)

      举例实现两数相乘:

import java.util.Scanner;

public class By {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int a=sc.nextInt();
        int b=sc.nextInt();
        int ret=mul(a,b);
        System.out.println(ret);
    }
    public static int mul(int x,int y){
        return x*y;
    }
}

注意事项:

1. 方法定义时, 参数可以没有,如果需要,每个参数要指定类型
2. 方法定义时, 返回值也可以没有,比如main方法,如果没有返回值, 则返回值类型必须写成 void
3. 方法定义不能嵌套
4. 方法定义时的参数称为 "形参", 方法调用时的参数称为 "实参"
比如:上述mul方法的定义中,x和y是形参,mul方法调用时a和b就是实参。
5. 方法必须定义在类之中, 方法定义的位置在调用位置的上方或者下方均可
6. Java 中没有 "函数声明" 这样的概念.

三、实参与形参的关系

        举一个很好理解的例子,如果这里有一个数学函数,那么形参就相当于其中的自变量,用于接受函数调用时传递的值,形参只是方法在定义时需要借助的一个变量,用来保存方法在调用时传递过来的值。

        在理解实参与形参之间的关系时,要注意:

        在Java中,实参的值永远都是“拷贝”到形参中,形参和实参本质是两个实体。下面看一个例子:

public class By {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        swap(a, b);//调用swap方法
        System.out.println("main: a = " + a + " b = " + b);//交换后结果
    }
    public static void swap(int x, int y) {
        int tmp = x;
        x = y;
        y = tmp;
        System.out.println("swap: x = " + x + " y = " + y);
    }
}

           运行结果:

 

           一个看似简单的swap方法调用,但实际上只有形参的值发生了调换,main方法中的a,b值并没有发生调换,这个结果从侧面反映了实参的值只是拷贝到形参中的。

          为了更好的去理解,我们知道,每个方法都有自己的运行环境,即栈帧。通过栈帧这种数据结构,将方法运行时所需要的与该方法相关的一切信息组织起来,例如形式参数,局部变量等。

          

          那么针对上述例子,画图来解释:

        实参a和b 与 形参x和y是两个没有任何关联性的变量,在swap方法调用时,只是将实参a和b中的值拷贝了一份传递给了形参x和y,因此对形参x和y操作不会对实参a和b 产生任何影响。

四、方法重载

       1.概念:

       在自然语言中,有很多一词多义的现象,比如“好人”,有可能今天做了好人好事,这是好人;还有另外一层意思,就是被某些人无情的发好人卡。在自然语言中,一个词语如果有多重含义,那么就说该词语被重载了,具体代表什么含义需要结合具体的场景。在Java中方法也是可以重载的。

       在Java中,如果多个方法的名字相同,参数列表不同,则称该几种方法被重载了。 

       比如:

public class By {
    public static void main(String[] args) {
       add(1,2);
       add(1.0,2.0);
       add(1.0,2.0,3.0);
    }
    public static int add(int a, int b) {
        return a+b;
    }
    public static double add(double a,double b){
        return a+b;
    }
    public static double add(double a,double b,double c){
        return a+b+c;
    }
}

方法重载时要注意:
   1. 方法名必须相同
   2. 参数列表必须不同(参数的个数不同、参数的类型不同、类型的次序必须不同)
   3. 与返回值类型是否相同无关

问题:

1.构成方法重载的方法名是一致的,jvm是如何知道要调用哪个方法的?

       原理:需要调用的方法,是在编译之后就确定了。在编译的过程中,编译器会对传递的实参数据类型进行推演,比如add(1,2),推演结果为两个int,那么就在类中找到两个参数都是int类型的add方法,若是add(1.0,2.0),推演结果为两个double,那么就在类中找到两个参数都是double类型的add方法。找到之后进行调用即可;如果没有找到对应的方法,编译器会尝试进行隐式类型转换,类型转换之后有合适的方式可以进行调用,否则直接报错。例如:

public class By {
    public static void main(String[] args) {
        byte a=1;
        byte b=2;
        add(a,b);//隐式类型转换,可以编译成功
      /*  String x="hello";
        String y="world";
        add(x,y);
        匹配不到对应方法,并且也无法进行隐式类型转换,报错!
      */
    }
    public static int add(int a, int b) {
        return a+b;
    }
}

        2.方法签名:

        问题:

        我们知道在函数中,不能存在名字相同的变量,那为什么在类中可以存在名字相同的方法

        方法签名:经过编译器编译修改过之后方法最终的名字。具体方式:方法全路径名+参数列表+返回值类型,构成方法完整的名字。

        也就是说,在人眼中看到的多个方法名是相同的,但是jvm看到的是被编译器修改过后的字节码文件,也就是看到被编译器修改过的add方法,即方法全路径名+参数列表+返回值类型。

        接下来使用javap反汇编工具查看编译后的如下代码

public class By {
    public static void main(String[] args) {
       add(1,2);
       add(1.0,2.0);
    }
    public static int add(int a, int b) {
        return a+b;
    }
    public static double add(double a,double b){
        return a+b;
    }
}

         反汇编之后,在这里可以看到:

 

       在常量池中,可以看到在字节码文件当中的命名方式:

 

       可以明显的看出,两个add方法在字节码文件中的名字是不同的。

       也可以使用jiclasslib插件,他是一个字节码阅读器,找到main方法:

                    

        在调用指令后方的#2以及#5,打开常量池后找到2和5号位置,如下:

 

       也可以看出,在字节码文件中两个add方法的名字是不一样的。

       所以这就解释了为什么在函数中不能存在名字相同的变量,但在类中可以存在名字相同的方法。

       那么解决了这个问题后,就有随之出现了一个问题。从上述方法名修饰规则中可以看出,编译器将返回值类型也放到最终的方法名中了,也就说明了如果返回值类型不同,那么最终在底层修改过后的名字也是不一样的,那么为什么方法重载与返回值没有关系?

       通过下图来回答:

 

     

        报错如下:

        

Over!!!!!

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值