目录
1.方法概念及使用
1.1 什么是方法
即一个代码片段,类似于C语言中的函数。
方法存在的意义:
- 是能够模块化的组织代码(当代码规模比较复杂的时候)
- 做到代码被重复使用, 一份代码可以在多个位置使用
- 让代码更好理解更简单
- 直接调用现有方法开发, 不必重复造轮子
例如:
代码1-1:(判断一个年是否为闰年)
public static void main(String[] args) {
int year = 1900;
if((year % 4 == 0 && year % 100 != 0)||(year % 400 == 0 )) {
System.out.println("是闰年");
}
else{
System.out.println("不是闰年");
}
}
1.2 方法定义
定义格式如下:
下面看代码1-2:(实现一个函数,检查一个年份是否为闰年)
public class Test {
public static boolean isLeapYear(int year){
if((year % 4 == 0 && year % 100 != 0)||(year % 400 == 0)){
return true;
}
else{
return false;
}
}
}
代码1-3:(实现两个整数相加的方法 )
public class Test {
public static int add(int a, int b){
return a + b;
}
}
注意事项:
- 修饰符:现阶段直接使用public static 固定搭配
- 返回值类型:如果方法有返回值,返回值类型必须要与返回的实体类型一致,如果没有返回值,必须写成 void
- 方法名字:采用小驼峰命名
- 参数列表:如果方法没有参数,()中什么都不写,如果有参数,需指定参数类型,多个参数之间使用逗号隔开
- 方法体:方法内部要执行的语句
- 在java当中,方法必须写在类当中
- 在java当中,方法不能嵌套定义
- 在java当中,没有方法声明一说
1.3 方法调用的执行过程
【方法调用过程】:
调用方法--->传递参数--->找到方法地址--->执行被调方法的方法体--->被调方法结束返回--->回到主调方法继续往下执行
每次方法的调用,都会在栈上开辟内存
每个方法都要有独立的空间
注意事项:
- 定义方法的时候, 不会执行方法的代码. 只有调用的时候才会执行.
- 一个方法可以被多次调用.
代码1-4:(实现两个整数相加)
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("第一次调用方法之前");
int ret = add(a,b);
System.out.println("第一次调用方法之后");
System.out.println("ret= " + ret);
System.out.println("第二次调用方法之前");
ret = add(30,50);
System.out.println("第二次调用方法之后");
System.out.println("ret= " + ret);
}
public static int add(int x, int y){
System.out.println("调用方法中x= " + x +"y= " + y);
return x + y;
}
}
运行结果如下:
代码1-5:(计算1!+2!+3!+4!+5! )
public class Test {
public static int fac(int n) {
System.out.println("计算n的阶乘n!= " + n);
int result = 1;
for(int i =1; i <= n; i++) {
result *= i;
}
return result;
}
public static void main(String[] args) {
int sum = 0;
for(int i = 1; i <= 5; i++) {
sum += fac(i);
}
System.out.println("sum = " + sum);
}
运行结果如下:
使用方法,可以避免二重循环,让代码更简单清晰
1.4 实参和形参的关系
- 方法的形参相当于数学函数中的自变量
- 形参的名字可以随意取,对方法都没有任何影响,形参只是方法在定义时需要借助的一个变量,用来保存方法在调用时传递过来的值
比如:
public static int add(int a, int b){ //a,b是形参
return a+b;
}
add(2,3)//其中2,3是实参,在调用时参给形参a,b
注意:在Java中,实参的值永远都是拷贝到形参中,形参和实参本质是两个实体
下面看代码1-6:(交换两个整型变量)
public class Test {
public static void swap(int x,int y) {
int tmp = x;
x = y;
y = tmp;
}
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("交换前: "+a+" "+ b );
swap(a,b);
System.out.println("交换后: "+a+" "+ b );
}
}
运行结果如下:
(Java当中,无法获取到栈上的内存地址)
可以看到,在swap函数交换之后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-7:
public class Test {
public static void swap(int[] array) {
int tmp = array[0];
array[0] = array[1];
array[1]= tmp;
}
public static void main(String[] args) {
int[] array = {1,2};
System.out.println("交换前: "+array[0]+" "+ array[1] );
swap(array);
System.out.println("交换后: "+array[0]+" "+ array[1] );
}
}
1.5 没有返回值的方法
方法的返回值是可选的. 有些时候可以没有的,没有时返回值类型必须写成void
例如刚刚交换两个整数的方法,就是没有返回值的
2.方法重载
2.1 为什么需要方法重载
代码2-1:
public static void main(String[] args) {
int a = 10;
int b = 20;
int ret = add(a,b);
System.out.println(ret);
double c = 2.2;
double d = 3.4;
double ret2 = add(c,d);
System.out.println(ret2);
}
public static int add(int x,int y){
return x+y;
}
运行结果如下:
此时由于参数类型不匹配,编译出错,不能直接使用现有的add方法
那么此时为了正确运行,我们就会想到再写一个add2方法
看代码2-2:
public static void main(String[] args) {
int a = 10;
int b = 20;
int ret = add(a,b);
System.out.println(ret);
double c = 2.2;
double d = 3.4;
double ret2 = add2(c,d);
System.out.println(ret2);
}
public static int add(int x,int y) {
return x + y;
}
public static double add2(double x,double y){
return x+y;
}
代码2-2的确可以解决问题,可是这样的话我们需要提供许多不同的方法名,那么是否能将所有的名字都给为add呢?
2.2 方法重载概念
再Java中,如果多个方法的名字相同,参数列表不同,则称该几种方法被重载了
看代码2-3:
public static void main(String[] args) {
int ret1 = add(1,2);
double ret2 = add(1.4,5.7);
double ret3 = add(2.4,5.6,7.9);
System.out.print(ret1+" ");
System.out.print(ret2+" ");
System.out.print(ret3 );
}
public static int add(int x,int y){
return x+y;
}
public static double add(double x,double y){
return x+y;
}
public static double add(double x,double y,double z){
return x+y+z;
}
运行结果如下:
注意:
- 方法名必须相同
- 参数列表不同(参数的个数不同,参数的类型不同,类型的次序必须不同)
- 与返回值类型是否相同无关
- 编译器再编译代码时,会对实参类型进行推演,根据推演的结果来确定调用哪个方法
下面看代码2-3:
public static void main(String[] args) {
int a = 10;
int b = 20;
int ret = add(a,b);
System.out.println(ret);
}
public static int add(int x,int y){
return x+y;
}
public static double add(int x,int y){
return x+y;
}
运行结果如下:
由此可以看出:两个方法如果仅仅只是因为返回值类型不同,是不能构成重载的
2.3 方法签名
在同一个作用域中不能定义两个相同名称的标识符。比如:方法中不能定义两个名字一样的变量,那为什么类中就 可以定义方法名相同的方法呢?
方法签名即:经过编译器编译修改过之后方法最终的名字。具体方式:方法全路径名+参数列表+返回值类型,构成方法完整的名字。
看代码2-4:
public static void main(String[] args) {
int ret1 = add(2,3);
double ret2 = add(2.4,4.8);
System.out.println(ret1);
System.out.println(ret2);
}
public static int add(int x,int y){
return x+y;
}
public static double add(double x,double y){
return x+y;
}
方法签名中的一些特殊符号说明:
特殊字符 | 数据类型 |
V | void |
Z | boolean |
B | byte |
C | char |
S | short |
I | int |
J | long |
F | float |
D | double |
[ | 数组(以[开头,配合其他的特殊字符, 表述对应数据类型的数组,几个[表述几维数组) |
L | 引用类型,以L开头,以;结尾,中间是引用类型的全类名 |