方法的使用
1.方法概念及使用
1.1 什么是方法
方法就是一个代码片段,类似C语言中的"函数"。
方法的作用:
1.是能够模块化的组织代码(当代码规模比较复杂的时候)。
2.做到代码被重复使用,一份代码可以在多个位置使用。
3.让代码更好理解更简单。
4.直接调用现有方法开发。
1.2 方法定义
基本语法:
//方法定义
修饰符 返回值类型 方法名称([参数类型 形参...]){
方法体代码;
[return 返回值];
}
//方法调用
方法名(实参...)
返回值变量=方法名(实参...)
注意:
1.在现阶段,方法的修饰暂时采用----> public static (固定搭配)。修饰符即对方法进行一些限定(谁可以使用)。
2.返回值类型-—>方法执行完了之后,是否需要将结果带出去。
- 有些方法有返回值,在定义方法时,必须要给出返回值类型。
- 有些方法没有返回值,在定义方法时,返回值类型的位置使用void来代替。
3.方法必须定义在类中,方法定义的位置在调用位置的上方或者下方均可。
4.方法的命名:按照小驼峰(第一个单词小写后面的首字母大写)规则来命名。
5.参数列表:
- 有些方法可能没有参数—方法名之后的()不能省略
- 有些方法的参数可能是1个,也可能是两个
6.方法定义不能嵌套。
7.Java中没有"函数声明"这样的概念,直接在一个类中就将方法定义了。
代码示例1:
//实现一个函数,检测一个年份是否为闰年
public static boolean isLeapYear(int year) {
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
return true;
} else {
return false;
}
}
public static void main (String[]args){
int year = 1900;
boolean isLeap=isLeapYear(year);//方法调用
System.out.println(isLeap);
}
代码示例2:
//实现两个整数相加
public static int add(int a,int b){
return a+b;
}
public static void main(String[] args) {
int x=10;
int y=20;
int z=add(x,y);
System.out.println(z);
}
1.3 方法调用的执行过程
方法调用过程:
调用方法----->传递参数----->找到方法地址----->执行被调方法的方法体----->被调方法结束返回------>回到主调方法继续往下执行
注意:
- 定义方法的时候,不会执行方法的代码。只有调用的时候才执行。
- 一个方法可以被多次调用。
代码示例:
//计算1!+2!+3!+4!+5!
//先写一个计算n的阶乘的方法
public static int fac(int n) {
int rst = 1;
for (int i = 1; i <= n; i++) {
rst *= i;
}
return rst;
}
public static void main12(String[] args) {
int sum=0;
for(int j=1;j<=5;j++){
sum+=fac(j);
}
System.out.println(sum);
}
//输出结果 153
1.4 实参和形参的关系*
方法的形参相当于数学函数中的自变量,比如1+2+3+…+n的sum(n)=
(
1
+
n
)
∗
n
2
\frac{(1+n)*n}{2}
2(1+n)∗n。
在Java语言中,方法的形参就相当于sum函数中的自变量n,用来接收sum函数调用时传递的值。形参的名字可以任意起,对方法都没有任何影响,形参只是方法在定义时需要借助的一个变量,用来保存方法在调用时传递过来的值。
例1:
public static int getSum(int N){ //N是形参
return (1+N)*N/2;
}
getSum(10);//10是实参,在方法调用时,形参N用来保存10
getSum(100);//100是实参,在方法调用时,形参N用来保存100
例2:
public static int add(int a,int b){
return a+b;
}
add(2,3);//2和3是实参,在调用时传给形参a和b
注意:在Java中,实参的值永远都是拷贝到形参中,形参和实参本质是两个实体 。
代码示例:
//交换两个整型变量
public static void swap(int x,int y ){
int tmp=x;
x=y;
y=tmp;
System.out.println("swap: x="+x+" y="+y);
}
public static void main(String[] args) {
int a=10;
int b=20;
swap(a,b);
System.out.println("main: a="+a+" b="+b);
}
//输出结果
swap: x=20 y=10
main: a=10 b=20
可以看到,在swap函数交换之后,形参x和y的值发生了改变,但是main方法中a和b还是交换之前的值,即没有交换成功。
原因:
实参a和b是main方法中的两个变量,其空间在main方法的栈中,而形参x和y是swap方法中的两个变量,x和y的空间在swap方法运行时的栈中。因此,实参a、b与形参x、y是没有任何关联的变量。在swap方法调用时,只是将实参a、b中的值拷贝了一份传递给了x、y,所以对形参x、y进行操作不会对实参a、b产生任何影响。
1.5 没有返回值的方法
方法的返回值有时候可以没有,没有返回值类型时,必须写成void
代码示例:
class Test{
public static void main(String[] args){
int a=10;
int b=20;
print(a,b);
}
public static void print(int x,int y){
System.out.println("x= "+x+" y= "+y)
}
}
2.方法重载
2.1 为什么需要方法重载
先来看一段代码:
public class Method {
//方法重载
public static int add(int m, int n) {
return m + n;
}
public static void main(String[] args) {
int a1=10;
int b1=20;
int ret1=add(a1,b1);
System.out.println(ret1);
double a2=10.5;
double b2=20.5;
double ret2=add(a2,b2);
System.out.println(ret2);
}
}
//编译出错
java: 不兼容的类型: 从double转换到int可能会有损失
由于参数类型不匹配,所以不能直接使用现有的add方法。
一种简单粗暴的解决方法:
public static int addInt(int m, int n) {
return m + n;
}
public static double addDouble(double m, double n) {
return m + n;
}
public static void main(String[] args) {
int a1=10;
int b1=20;
int ret1=addInt(a1,b1);
System.out.println(ret1);
double a2=10.5;
double b2=20.5;
double ret2=addDouble(a2,b2);
System.out.println(ret2);
}
//输出结果:
30
31.0
上述代码的确可以解决问题,但是需要提供许多不同的方法名,使工作更加繁琐。我们能否将所有的名字都给成add呢?
2.2 方法重载概念
在Java中,如果多个方法的名字相同,参数列表不同,则称这些方法被重载了。
代码示例:
public static int add(int m, int n) {
return m + n;
}
public static double add(double m, double n) {
return m + n;
}
public static double add(double m, double n,double p) {
return m + n + p;
}
public static void main(String[] args) {
add(1,2);//调用add(int m, int n)
add(1.5,2.5);//调用add(double m, double n)
add(1.5,2.5,3.9);//调用add(double m, double n,double p)
}
注意:
- 方法名必须相同。
- 参数列表必须不同(参数的个数不同、参数的类型不同、类型的次序必须不同)。
- 与返回值类型是否相同无关,如果只是因为返回值类型不同,是不能构成重载的。
例如:
public static int add(int m, int n) {
return m + n;
}
public static double add(int m, int n) {
return m + n;
}
public static void main(String[] args) {
int a=10;
int b=20;
int ret=add(a,b);
System.out.println(ret);
}
//编译报错
java: 已在类 Method中定义了方法 add(int,int)
- 编译器在编译代码时,会对实参类型进行推演,根据推演的结果来确定调用哪个方法。
重载方法调用原理:
对于重载的方法到底要调用哪个,在编译期间就已经确定好了。在编译时,编译器会对传递的实参类型进行推演。对于上面的代码示例:
add(10,20)---->推演的结果:int, int,然后在类中找两个参数都是int类型的add方法。
add(1.1,2.2)---->推演的结果:double,double,然后在类中找两个参数都是double类型的add方法。
如果找到了,则进行调用;如果没有找到,编译器会尝试进行隐式类型转换,如果类型转换之后有合适的方法可以进行调用,则调用该方法,否则报错。
2.3 方法签名
在同一个作用域中不能定义两个相同名称的标识符,比如:方法中不能定义两个名字一样的变量。那为什么类中就可以定义方法名相同的方法呢?
先介绍一个新的概念
**方法签名:**经过编译器编译修改过后方法最终的名字。具体方式:方法全路径名+参数列表+返回值类型,构成方法完整的名字。
public static int add(int m, int n) {
return m + n;
}
public static double add(double m, double n) {
return m + n;
}
public static void main(String[] args) {
add(1,2);
add(1.5,2.5);
}
上述代码经过编译之后,使用JDK自带的javap反汇编工具查看,具体操作:
- 先对工程进行编译,生成.class字节码文件。
- 在控制台中进入到要查看的.class所在的目录。
- 输入:javap-v字节码文件名即可
main方法编译之后的部分字节码
方法签名中的一些特殊符号说明:
特殊字符 | 数据类型 |
---|---|
V | void |
Z | boolean |
B | byte |
C | char |
S | short |
I | int |
J | long |
F | float |
D | double |
[ | 数组(以[开头,配合其他的特殊字符,表述对应数据类型的数组,几个[表示几维数组) |
L | 引用类型,以L开头,以;结尾,中间是引用类型的全类名 |