前言
我们在C语言中学习函数,因为我们太懒了懒的写代码,为了提高代码的复用性避免重复的造轮子,我们可以将常用的功能独立成函数,在java中也是如此只是在java中没有函数这个概念,却有等同于函数的东西,那就是方法,接下来让我们走进java中方法,去领略方法的调用,方法的声明周期以及方法重载。
文章目录
🏆1.什么是方法?
方法是程序中具有独立功能的代码块的封装。比如我们在main方法中写了一个加法,但是这个加法需要在其它方法中使用,我们可以将具有加法功能的代码块封装成一个方法,下次使用的时候直接调用即可。所以方法不是个很抽象的事物,它就是代码块。
🎲1.1方法存在的意义
在哲学中存在就有意义,那么方法也有它存在的意义,如下。
1.是能够模块化的组织代码(当代码规模比较复杂的时候).
2.做到代码被重复使用, 一份代码可以在多个位置使用.
3.让代码更好理解更简单
4.直接调用现有方法开发, 不必重复造轮子.
我们已经了解了什么是方法以及方法的意义之后,接下来我们需要知道如何定义一个方法。
🎲1.2方法定义定义的基本格式
// 方法定义 public static 方法返回值 方法名称([参数类型 形参 ...]){ 方法体代码; [return 返回值]; }
假设我们已经定义好了方法,如同木匠中的工具箱里已经装满了锤子等工具,这个时候我们并没有去使用工具(即方法),那么我们在程序中如何使用方法呢?对于木匠师父而言开箱即用,对于我们而言也是大同小异,我们将使用方法称之为调用,没有调用,方法就在箱子闲着,所以学会调用是非常重要的。
🎲1.3方法的调用格式
// 方法调用 格式一:返回值变量 = 方法名称(实参...); 格式而:方法名称(实参...);
对于有返回值的方法我们可以用变量来接收,对于没有返回值的方法直接调用即可。
代码实例:使用一个方法实现两个数相加
class Test { public static void main(String[] args) { int a = 10; int b = 20; // 方法的调用 int ret = add(a, b); System.out.println("ret = " + ret); } // 方法的定义 public static int add(int x, int y) { return x + y; } } // 执行结果 ret = 30
我们在使用方法时有一下注意事项
1.public 和 static 两个关键字在此处具有特定含义,
2.方法定义时, 参数可以没有. 每个参数要指定类型
3.方法定义时, 返回值也可以没有, 如果没有返回值, 则返回值类型应写成 void
4.方法定义时的参数称为 “形参”, 方法调用时的参数称为 "实参
5.方法的定义必须在类之中, 代码书写在调用位置的上方或者下方均可
6.Java 中没有 “函数声明” 这样的概念.
对于public和static关键字在此就不详细展开,等到面向对象篇时将会一一讲解,到目前为止我们我们定义方法时暂时都使用public static 修饰。
🏆1.4方法的调用过程
🎲1.5方法调用的基本规则
1.定义方法的时候, 不会执行方法的代码. 只有调用的时候才会执行
2.当方法被调用的时候, 会将实参赋值给形参
3.参数传递完毕后, 就会执行到方法体代码.
4.当方法执行完毕之后(遇到 return 语句), 就执行完毕, 回到方法调用位置继续往下执行.
5.一个方法可以被多次调用.
为了更直观的理解方法的调用我们可以在idea中使用调试的方式来观察方法的执行顺序,接下来我将以上文提到的两个整数相加的方法为示范案例,在idea中观察add()方法的执行顺序。
首先我们在调用方法处打个断点
然后我们进入方法
在点下一步,就结束该方法
方法结束有一个整型的返回值,用整型的变量接收
🎲1.5方法常见问题
方法的编写顺序无所谓。
方法与方法之间是平级关系,不能嵌套定义。
方法的返回值类型为void(无返回值),方法内则不能使用return返回数据,如果方法的返回值类型写了具体类型,方法内部则必须使用return返回对应类型的数据。
return语句下面,不能编写代码,因为永远执行不到,属于无效的代码。
方法不调用就不执行, 调用时必须严格匹配方法的参数情况。
有返回值的方法调用时可以选择定义变量接收结果,或者直接输出调用,甚至直接调用;无返回值方法的调用只能直接调用。
🎲4.没有返回值的方法
方法的返回值是可选的. 有些时候可以没有的
代码示例
有没有返回值根据方法的功能来定,具体问题具体分析即可。
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.实参和形参的关系(重要)
代码示例: 交换两个整型变量
class Test { public static void main(String[] args) { int a = 10; int b = 20; swap(a, b); System.out.println("a = " + a + " b = " + b); } public static void swap(int x, int y) { int tmp = x; x = y; y = tmp; } } // 运行结果 a = 10 b = 20
原因分析 刚才的代码, 没有完成数据的交换. 对于基础类型来说, 形参相当于实参的拷贝. 即传值调用,该add()方法中的变量属于局部变量,交换的也只是在add()方法所开辟的栈内存区域交换,不会影响main中的。
int a = 10; int b = 20; int x = a; int y = b; int tmp = x; x = y; y = tmp;
可以看到, 对 x 和 y 的修改, 不影响 a 和 b.
解决办法: 传引用类型参数 (例如数组来解决这个问题)
class Test { public static void main(String[] args) { int[] arr = {10, 20};//等价于int [] arr=new int [2]; arr[0]=10;arr[1]=20; swap(arr); System.out.println("a = " + arr[0] + " b = " + arr[1]); } public static void swap(int[] arr) { int tmp = arr[0]; arr[0] = arr[1]; arr[1] = tmp; } } // 运行结果 a = 20 b = 10
对于上述关于数组的代码,先补充一点知识再来看看
🏆3.方法的参数传递机制
🎲3.1java内存分配
堆(Heap),此内存区域的唯一目的 就是存放对象实例,几乎所有的对象 实例都在这里分配内存。这一点在 Java虚拟机规范中的描述是:所有的 对象实例以及数组都要在堆上分配。
通常所说的栈(Stack),是指虚拟机栈。虚拟机栈用于存储局部变量等。 局部变量表存放了编译期可知长度的 各种基本数据类型(boolean、byte、 char 、 short 、 int 、 float 、 long 、 double)、对象引用(reference类型, 它不等同于对象本身,是对象在堆内 存的首地址)。 方法执行完,自动释 放。
方法区(Method Area),用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
java内存分配上我们关注最多的就是栈,堆,方法区,它还有其它区域,可以参考以下图片。
关于这张图,后期再来看看吧,我自己也有点蒙对于java的底层。常用的就是栈,堆,以及方法区,我们只需记住在这三个区域存放的是啥就行了。
上述数组名作为参数传递属于引用类型的的参数传递,关于什么引用在数组篇再来细说,暂时就记住引用存放的是一个指向数组的地址就行了。
🎲3.2引用类型的的参数传递
图解使用数组来交换两个数
首先Test.class会加载到方法区,然后main方法启动,创建一个数组,该数组本质上是new出来所以会在堆上开辟空间,然后将该将数组首元素的地址赋值给arr,然后在栈区调用swap();方法,该方法将2个数交换,此时堆中数组的内容也随之变化,而引用arr依旧指向的是该数组,所以就可以做到2个数的交换。
🎲3.3基本类型的参数传递
这里就拿add()方法来举例。
基本数据类型的参数传递比较简单,毕竟少考虑了一个堆区,关于此程序的执行,我们要明确先是加载class文件到方法区中,其次main是程序的入口
所以先会执行main方法,再执行add()方法。最后输出sum后main离开栈区此时整个程序结束。
🏆5.方法重载
上文的add()方法只针对于两个整数求和,那么我们如果要对浮点数求和是否我们需要再写一个add()方法求浮点数的和,在java中允许方法名相同但是参数列表或者返回值类型要不同,这样我们就不要为求浮点数的方法单独的起个别名,这样就解决了逻辑相同的方法,因为参数个数或者参数类型不同,反复起名的过程。
使用方法重载写个add()方法。
class Test { public static void main(String[] args) { int a = 10; int b = 20; int ret = add(a, b); System.out.println("ret = " + ret); double a2 = 10.5; double b2 = 20.5; double ret2 = add(a2, b2); System.out.println("ret2 = " + ret2); double a3 = 10.5; double b3 = 10.5; double c3 = 20.5; double ret3 = add(a3, b3, c3); System.out.println("ret3 = " + 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; } }
方法的名字都叫 add. 但是有的 add 是计算 int 相加, 有的是 double 相加; 有的计算两个数字相加, 有的是计算三个数 字相加. 同一个方法名字, 提供不同版本的实现, 称为 方法重载
🎲5.1方法重载的识别技巧
只要是同一个类中,方法名称相同、形参列表不同,那么他们就是重载的方法,其他都不管!(如:修饰符,返回值类型都无所谓)
形参列表不同指的是:形参的个数、类型、顺序不同,不关心形参的名称。
补充知识单独使用return关键字单独使用
return; —> 可以立即跳出并结束当前方法的执行; return关键字单独使用可以放在任何地方
总结
以后我们写代码的时候要做到将独立的功能封装成方法,以及熟悉方法的调用和方法重载。
最后的话
各位看官如果觉得文章写得不错,点赞评论关注走一波!谢谢啦!。如果你想变强那么点我点我 牛客网。