java方法|方法(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;
}
}
【java方法|方法(Java)】注意事项:
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!!!!!
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 对抗抑郁最好的方法
- 事件代理
- 怎样用黑谜速冻膜去黑头,|怎样用黑谜速冻膜去黑头, 最有效的去黑头的方法看这!
- Java|Java OpenCV图像处理之SIFT角点检测详解
- java中如何实现重建二叉树
- 移动端h5调试方法
- 唱歌教学(导致嗓音损坏的几个常见的错误唱歌方法!)
- 拆书方法训练营
- 数组常用方法一