public class UseOfMethods {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);// 为输入数据做准备
int n = scanner.nextInt();// 接收一个整型数据,将其赋给 n
sumadd(n);// 调用函数(方法)sumadd,并向 sumadd方法 传参(n)。
}
public static void sumadd(int n){// 这里接收参数,和C语言一样,可以定义一个相同的变量名,来接收传参数。但必须类型和参数个数要相同
int sum =0;// 定义一个求和变量,将其初始化
for(int i =0;i<=n;i++){
sum += i;// 将1~10的每个数值累加起来
}
System.out.println(sum);// 输出累加的结果
}
}// 图1
图 1
不知道你们有没有发现程序中 我们的 sumadd方法没有写在 main方法上面,而是下面,学过C的朋友可能会问 “不需要在前面声明函数吗?”
答案是不用,在Java中 是没有函数声明的概念,它就是要用的时候,直接去调用
另外在普及一个内容,方法的参数叫做形参,main方法的参数叫实参,形参相当于实参的一份拷贝,这种传参方式被称为 按值传递(传值)
由此引申出一个知识点, 在Java中 是没有 传址 的概念,只有传值,所以我们在调用方法的时候,只需要注重 形参 和 实参 的类型 和 个数 是否匹配(相同)
如果你想让方法(函数)返回一个值,就是说带回一个值回到主函数,再对其打印也行
程序实例2(程序实例1的改版)
import java.util.Scanner;
public class UseOfMethods {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);// 为输入数据做准备
int n = scanner.nextInt();// 接收一个整型数据,将其赋给 n
int ret = sumadd(n);// 调用方法(函数)sumadd,并想 sumadd方法 传参(n)。
System.out.println(ret);
}
public static int sumadd(int n){// 这里接收参数,和C语言一样,可以定义一个相同的变量名,来接收传参数。但必须类型和参数个数要相同
int sum =0;// 定义一个求和变量,将其初始化
for(int i =0;i<=n;i++){
sum += i;// 将1~10的每个数值累加起来
}
return sum;
}
}// 图2,注意圈起来的部分
图2
有的人可能会说 我可不可以 不创建一个 与方法的返回值相同类型的变量 来接收它的值,直接输出行吗?
答案是可以的,
写法: System.out.println(sumadd(n));
因为 sumadd 是返回值的,输出语句,只是将它返回来的值给打印了而已。
如果方法的返回值为 void(无返回),那么程序会报错(输出语句会说:我都准备好了,你就给我看这? 就这!)
每个函数,在被调用的时候,都会开辟栈帧(开辟属于自身的内存空间)
函数栈帧图(图3),想了解 c方面的或者想对比一下的,可以看这篇文章函数栈帧销毁与创建(vs2013)- 修改版
-
public 和 static 两个关键字在此处具有特定含义, 我们暂时不讨论, 后面会详细介绍.
-
方法定义时, 参数可以没有. 每个参数要指定类型
-
方法定义时, 返回值也可以没有, 如果没有返回值, 则返回值类型应写成 void
-
方法定义时的参数称为 “形参”, 方法调用时的参数称为 “实参”.
-
方法的定义必须在类之中, 代码书写在调用位置的上方或者下方均可.
-
Java 中没有 “函数声明” 这样的概念
========================================================================
定义方法的时候, 不会执行方法的代码. 只有调用的时候才会执行.
比如:
int b = sumadd();,它在执行该语句时,遇见调用方法的代码,会先去执行调用方法,下面程序它暂时不会去关。
System.out.println(b); 调用方法的代码执行完了之后,才会轮到该语句执行
当方法被调用的时候, 会将实参赋值给形参.(int a = 10; sumadd(a); public static void sumadd(int A); 这里的A,其实就是a值的一份拷贝 )
参数传递完毕后, 就会执行到方法体代码.
当sumadd方法执行完毕之后(遇到 return 语句), 就执行完毕,同时将其值带回main方法中,并将其赋给变量b(类型匹配)继续往下执行
并且一个方法可以被多次调用.
代码示例: 计算 1! + 2! + 3! + 4! + 5!
public class UseOfMethods {
public static void main(String[] args) {
int n =5;
int sum = factorialSum(n);// 调用函数计算 5 的阶乘和是多少,将其赋给sum
System.out.println(sum);
}
public static int factorialSum(int n){
int sum = 0;
int ret = 1;
for(int i = 1;i<=n;i++){
ret *= i;// 每个数字的阶乘
sum+=ret;// 将每个数字的阶乘累计相加
}
return sum;
}// 图 4
}
图4
使用方法的优点也就体现出来了,创建一个专门计算阶乘和的函数,只要我的传参没问题,它就能帮我完成想要的效果。
注意 自定义方法名,要让人看得懂是什么意思,见名知其用。看到名字知道它是用来干什么的,接下看代码,往这个思想靠拢,大大提升代码的阅读性。
=======================================================================
我们先来用常规形式来写
这里是交换实参
public class UseOfMethods {
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("交换前:a = " + a + " b = " + b);
// 1
// int tmp =a;
// a =b;
// b = tmp;// 图 5
//2.异或
a = a^b;
b = a^b;// b = abb(b^b == 0) == 0 ^ a == a
a = b^a;// a = b^a == a(b) ^ a^b(a) == 0 ^ b == b
// 图 6
// 两种方法均可以交换两者数据
System.out.println("交换后:a = " + a + " b = " + b);
}
}
图5
图6
用方法来写
public class UseOfMethods {
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("交换前:a = " + a + " b = " + b);
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;
}
}
图7
图8
由图 7,8.可知这样写不会发生任何改变,因为只是交换形参,也就是说 交换的是 swap方法的参数
并不是在交换 main方法的参数,这里的x,y,只是a和b的值的一份拷贝
有人肯定会说像C里面一样,传地址呗!
记住 在Java中,是无法取得栈上变量的地址的,也就是说取不到局部变量的地址( 图 9)
图9
如果要去做,只能把 a 和 b 的值,放到堆上(动态空间上)。放在堆上的都是对象。
这道题留着 我们讲 对象和类,或者数组的时候,再进行讲解。以我们现在的基础还不足以解决该问题。
=======================================================================
方法的返回值是可选的. 有些时候可以没有的
public class UseOfMethods {
public static void main(String[] args) {
int a = 0;
int b = 1;
sum(a,b);
}
public static void sum(int x,int y){
System.out.println(x+y);
// 我在方法中就已经将我们想打印的结果 图 10,所以不需要返回值
//但是规定 无返回,就不能 return 返回一个值
// return x+y; 图 11,都报错了,就别谈运行
// 但是可以这么写
return ;// 虚晃一枪,你能奈我何?
// 图 12
}
}
图10
图11
图12
====================================================================
有些时候我们需要用一个函数同时兼容多种参数的情况, 我们就可以使用到方法重载
public class UseOfMethods {
public static void main(String[] args) {
int a = 10;
int b = 20;
int ret = add(a, b);
System.out.println("ret = " + ret);
double a2 = 12.5;
double b2 = 18.5;
double ret2 = add(a2, b2);//图 13
System.out.println("ret2 = " + ret2);
}
public static int add(int x,int y){
return x+y;
}
}
图13
那我们怎么实现呢?
代码实例2
public class UseOfMethods {
public static void main(String[] args) {
int a = 10;
int b = 20;
int ret = add(a, b);
System.out.println("ret = " + ret);
double a2 = 12.5;
double b2 = 18.5;
double b3 = 9.0;
double ret2 = add(a2, b2,b3);//图 13
System.out.println("ret2 = " + ret2);
}
public static int add(int x,int y){
return x+y;
}
public static double add(double x,double y,double z){
return (x+y+z);
}
}// 图 14
图14
方法重载的重点在于函数名要相同,参数个数或者类型要不同。(两者中必有一者不同)
而返回值 不重要,只要你接收返回的值的类型是相匹配的就行,要不然无法进行赋值。
不要写的一摸一样(参数个数和类型都相同),这样相当于 一个变量被重复定义,是会出错的
例如:
public static int add(int x,int y){
return x+y;
}
public static int add(int x,int y){
return x+y;
}
再来看一个错误示范
public class UseOfMethods {
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;
}
public static double add(int x,int y){
return (double)(x+y);
}
}// 图 15
图 15
由图我们可以看出这样写也是不行的,正如我前面所说的 返回值,不是重点,参数类型和个数才是重点
只要你参数的类型 和 个数 一模一样,无论你返回值是什么,都算方法的重定义, 程序是会报错的(方法的重定义这是我个人理解)
&ensp
由此我们可以看出 方法的重载 有多么强大。
我们可以根据 参数的类型和个数 来为我们的方法,加载 几个新的方法,具有更多的功能
现在你知道了吧 方法的重载,有多爽!
如果一个类的两个方法(无论是在同一个类中声明,还是都由一个类继承的,或者一个声明和一个继承的【总的来说不一定是同一个类里的】)
具有相同的名称,但签名不是重写等价的,则称该方法名为重载。 (了解即可)
1. 方法名要相同
2. 方法的参数不同(参数个数或者类型,两者选其一,或者都选,反正至少有一个因素是不同的)
3. 方法的返回值类型不影响重载
4. 当两个方法的名字相同, 参数也相同, 但是返回值不同的时候, 不构成重载.
===================================================================
一个方法在执行过程中调用自身, 就称为 “递归”.
递归相当于数学上的 “数学归纳法”, 有一个起始条件, 然后有一个递推公式
递推公式是递归的重点,推出它,递归就很好写。没推出。就。。。嗯~~~
1. 有一个趋近于终止的条件(停止递归的条件)
2. 自己调用自己(让它自己扇自己,扇疼了再停下来,不要问我为什么我举这个例子!)
代码示例
public class UseOfMethods {
public static void main(String[] args) {
func();
}
这样写,就不满足 使用递归所需的第一个条件 没有一个终止递归的条件
所以该程序会无限递归死循环,最终导致栈溢出(栈空间不是无限大,是有限,func方法一直调用自己下去,最终肯定是会 爆满/溢出 的)
因为 每次调用 func方法时,都会为其在栈上空间开辟块自己的空间
public static void func(){
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
最后
笔者已经把面试题和答案整理成了面试专题文档
公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-25qLDgCy-1711793712438)]
[外链图片转存中…(img-A39GcDoy-1711793712438)]
[外链图片转存中…(img-rqHpc3UT-1711793712439)]
[外链图片转存中…(img-TXGWlvzc-1711793712439)]
[外链图片转存中…(img-ZvGZ7HPH-1711793712440)]
[外链图片转存中…(img-YqhuG4Pl-1711793712440)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-2GqYaUiA-1711793712440)]
最后
笔者已经把面试题和答案整理成了面试专题文档
[外链图片转存中…(img-c7RJgJMd-1711793712441)]
[外链图片转存中…(img-Xn0Hxszs-1711793712441)]
[外链图片转存中…(img-8aTT6A17-1711793712441)]
[外链图片转存中…(img-m24csnbP-1711793712442)]
[外链图片转存中…(img-uQp4ho3E-1711793712442)]
[外链图片转存中…(img-00FeMrcS-1711793712442)]