脚本宝典收集整理的这篇文章主要介绍了UseOfMethods - 方法的使用 - Java,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
(其实方法就是函数另一个称呼,只不过为了区分 c语言和Java,所以在Java中叫方法,C叫函数,唯一不同的就是两者实现的方式)
打个比方: 方法就好像是 制作面包的磨具,如果你想得到一个这样形状,或者说达到某种效果,你就去使用该磨具。(该函数能完成某一个 功能/任务/效果)
而且,你可以换材料,但你不能用它做其他的东西,这个磨具是专门正对面包的(函数实现的功能,是专门针对某一种情况)
也就是说你做面包要使用材料必须属于面粉这一类的东西,无非即使质量的好坏
(函数接收的参数值是可以改变大小的,类型不能变,否则参数类型不匹配,是无法成功调用函数的功能)
1. 是能够模块化的组织代码(当代码规模比较复杂的时候).
2. 做到代码被重复使用, 一份代码可以在多个位置使用.
3. 让代码更好理解更简单.
4. 直接调用现有方法开发, 不必重复造轮子
public static 返回值 方法名称(形式参数列表){
函数体/方法体;
}
import java.util.Scanner;
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
答案是不用,在Java中 是没有函数声明的概念,它就是要用的时候,直接去调用
另外在普及一个内容,方法的参数叫做形参,;main方法的参数叫实参,形参相当于实参的一份拷贝,这种传参方式被称为 按值传递(传值) 由此引申出一个知识点, 在Java中 是没有 传址 的概念,只有传值,所以我们在调用方法的时候,只需要注重 形参 和 实参 的类型 和 个数 是否匹配(相同)
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,注意圈起来的部分
每个函数,在被调用的时候,都会开辟栈帧(开辟属于自身的内存空间)
1. public 和 static 两个关键字在此处具有特定含义, 我们暂时不讨论, 后面会详细介绍.
2. 方法定义时, 参数可以没有. 每个参数要指定类型
3. 方法定义时, 返回值也可以没有, 如果没有返回值, 则返回值类型应写成 void
4. 方法定义时的参数称为 "形参", 方法调用时的参数称为 "实参".
5. 方法的定义必须在类之中, 代码书写在调用位置的上方或者下方均可.
6. 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(类型匹配)继续往下执行
并且一个方法可以被多次调用.
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
}
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 = a^b^b(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);
}
}
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.可知这样写不会发生任何改变,因为只是交换形参,也就是说 交换的是 swap方法的参数 并不是在交换 main方法的参数,这里的x,y,只是a和b的值的一份拷贝 有人肯定会说像C里面一样,传地址呗! 记住 在Java中,是无法取得栈上变量的地址的,也就是说取不到局部变量的地址( 图 9)
方法的返回值是可选的. 有些时候可以没有的
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
}
}
有些时候我们需要用一个函数同时兼容多种参数的情况, 我们就可以使用到方法重载
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;
}
}
那我们怎么实现呢?
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
方法重载的重点在于函数名要相同,参数个数或者类型要不同。(两者中必有一者不同)
而返回值 不重要,只要你接收返回的值的类型是相匹配的就行,要不然无法进行赋值。
不要写的一摸一样(参数个数和类型都相同),这样相当于 一个变量被重复定义,是会出错的
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
由图我们可以看出这样写也是不行的,正如我前面所说的 返回值,不是重点,参数类型和个数才是重点 只要你参数的类型 和 个数 一模一样,无论你返回值是什么,都算方法的重定义, 程序是会报错的(方法的重定义这是我个人理解)
&ensp
由此我们可以看出 方法的重载 有多么强大。 我们可以根据 参数的类型和个数 来为我们的方法,加载 几个新的方法,具有更多的功能 现在你知道了吧 方法的重载,有多爽!
如果一个类的两个方法(无论是在同一个类中声明,还是都由一个类继承的,或者一个声明和一个继承的【总的来说不一定是同一个类里的】)
具有相同的名称,但签名不是重写等价的,则称该方法名为重载。 (了解即可)
1. 方法名要相同 2. 方法的参数不同(参数个数或者类型,两者选其一,或者都选,反正至少有一个因素是不同的) 3. 方法的返回值类型不影响重载 4. 当两个方法的名字相同, 参数也相同, 但是返回值不同的时候, 不构成重载.
一个方法在执行过程中调用自身, 就称为 "递归".
递归相当于数学上的 "数学归纳法", 有一个起始条件, 然后有一个递推公式
递推公式是递归的重点,推出它,递归就很好写。没推出。就。。。嗯~~~
1. 有一个趋近于终止的条件(停止递归的条件) 2. 自己调用自己(让它自己扇自己,扇疼了再停下来,不要问我为什么我举这个例子!)
public class UseOfMethods {
public static void main(String[] args) {
func();
}
这样写,就不满足 使用递归所需的第一个条件 没有一个终止递归的条件
所以该程序会无限递归死循环,最终导致栈溢出(栈空间不是无限大,是有限,func方法一直调用自己下去,最终肯定是会 爆满/溢出 的)
因为 每次调用 func方法时,都会为其在栈上空间开辟块自己的空间
public static void func(){
func();
}
}// 图17
public class UseOfMethods {
public static void main(String[] args) {
func(3);
}
public static void func(int n){
if(n==1){// 递归的终止的条件,因为 n == 3.每次自己调用自己时,n都会减1,调用 3 次,就结束了
System.out.println(n);
return ;
}
func(n-1);
System.out.println(n);
}
}// 图18
你这样想 假设我们不知道 n 为多少,那我们怎么办?先从初始情况分析呗
当 n =0时,怎么办?
n =1时,怎么办?
大于1又怎么办?
en~,是不是有点懂了,当我们处理递归时,我们可以有两种思维
当我们去思考它的终止条件是什么? 你可能会被套娃,套成zz。
这时候,我们反过来想想 这个值的初始值是多少,满足怎样的条件?(就比如说要大于,小于或等于某个条件)
是不是打开新思路了?‘’
思考递归的时候,横向思考:根据递推公式(个人理解递推公式跟数学的通项公式有点像)去思考
代码执行:纵向执行的(从上往下,一条条执行)
在坐的某些人,经常会自己代入某个数字,然后,拿着数字和代码一个个展开,很烧脑的
虽然我很喜欢这样,但是我只是在我掌握递归规律(递推公式)之后,对代码执行过程的好奇,去展开很小很小的范围。比如1、2、3之类的
太复杂了,对不起,我不玩了。。。
这点不值得提倡,我们需要的是掌握其递归规律,才是重中之重。
求 n的阶乘(n==5)
1! == 1 //这就是我们的起始条件,也是我们的终止条件
2! == 2*1 == 2 * 1!
3! == 3*2*1 == 3 * 2!
4! == 4*3*2*1 == 4 * 3!
5! == 5*4*3*2*1 == 5 * 4!
你发现了 求 5!的值,它是 5 * (5-1)!
而 4! == 4 * (4-1)!
3! == 3 * (3-1)!
2! == 2 * (2-1)!
以此类推 直到遇到 1! 时,他的返回值里不再带其他阶乘,此时 1!是不是很适合作为我们递归的终止条件
由此我们发现了 递推公式为 n * (n-1)!
5! == 5 * 4!== 5 * 4 * 3! == 5 * 4 * 3 * 2! == 5 * 3 * 2 * 1(这里只是帮助你们理解,别学,上面的递推公式才是你们该学的)
import java.util.Scanner;
public class UseOfMethods{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(factorial(n));
sc.close();//关闭输入
}
public static int factorial(int n){
if(1==n){
return 1;
}
return n*factorial(n-1);// n * (n-1)!
// (n-1)! == factorial(n-1); 即 factorial == !
}
}// 图19,不懂没关系,我帮你搬下来,对着看
1! == 1 //这就是我们的起始条件,也是我们的终止条件
2! == 2*1 == 2 * 1!
3! == 3*2*1 == 3 * 2!
4! == 4*3*2*1 == 4 * 3!
5! == 5*4*3*2*1 == 5 * 4!
你发现了 求 5!的值,它是 5 * (5-1)!
而 4! == 4 * (4-1)!
3! == 3 * (3-1)!
2! == 2 * (2-1)!
5! == 5 * 4!== 5 * 4 * 3! == 5 * 4 * 3 * 2! == 5 * 3 * 2 * 1
程序运行 跟我们刚才藏宝殿是一样的,一层一层的抢。从最里面的开始抢
也就从我们终止条件开始
n == 1; return 1;// 这里的返回值 是返回到 调用它的上一层级(藏宝殿核心是第一层吗,抢完了,肯定去抢第二程啊)
n == 2 return 2* factorial(2-1) == 2 * 1 == 2
n == 3; return 3 * 2 == 6
n == 4; return 4 * 6 == 24
n == 5; return 5 * ==
考验你们的时候,在下面评论,看你们到底有没有看懂学会
递归的字面意思
递归 n * factorial(n-1)l n-1 就是它传过去的值,称为递, factorial(n-1)返回的值,称为归
结合称为: 递归。
你赚的钱迟早是有一天会花完的。。。
赶快跟着我一起卷。
import java.util.Scanner;
public class UseOfMethods {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(sumadd(n));// 图 20
sc.colse()// 关闭输入
}
public static int sumadd(int n){
if(n==1){
return 1;
}
return n + sumadd(n-1);
}
}// 自己琢磨,不懂在下方评论,一起探讨。(n 比 n-1 多了1,看似废话,其实是真理)
图 20
import java.util.Scanner;
public class UseOfMethods {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
print(n);
sc.close();//关闭输入
}
public static void print(int n){
if(n<10){
System.out.println(n);
return;
}
print(n/10);// 在调用自身是,将 n/10 的值 作为下个自身函数的形参
// 最终肯定有 剩一位数的时候,一位数(0~9)肯定是小于10的,别问为什么,问就不会!
// 这个也就是我们终止条件
// 假设我们输入的是 1234 , 在调用自身是,将 n/10 的值 作为下个自身函数的形参,那么 剩余的最后一位就是 1.所以从1开始打印
// 其次是2 (12%10)、 3(123%10)、4(1234%10)
System.out.println(n%10);
}// 图 21
}
递归的程序的执行过程不太容易理解, 要想理解清楚递归, 必须先理解清楚 "方法的执行过程", 尤其是 "方法执行结束之后, 回到调用位置继续往下执行“
&ensp;
import java.util.Scanner;
public class UseOfMethods {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(sum(n));
sc.close();
}
public static int sum(int n){
if(n<10){
return n;
}
return n%10+sum(n/10);
}
}// 图 22 ,这题跟上面那题几乎一样,就不讲了,自己琢磨。
1 1 2 3 5 8 13......
从第三位开始,等于自身前两位数相加
import java.util.Scanner;
public class UseOfMethods {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(fibonacci(n));
}
public static int fibonacci(int n){
if(n<3){
return 1;
}
return fibonacci(n-1) + fibonacci(n-2);
}
}// 图23
一个数字重复出现,求 第 n位的斐波那契函数,n越大重复的数字越大 所以我不推荐使用递归去处理斐波那契数,因为面试中,使用该方法求解,你绝对GG
1 1 2 3 5 8 13.....
从第三位开始,等于自身前两位数相加
import java.util.Scanner;
public class UseOfMethods {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
fibonacci(n);
sc.close();
}
public static void fibonacci(int n){
if(n<3) {
System.out.println(1);
}else {
int a =1;
int b =1;
int c = 0;
for(int i=3;i<=n;i++){//从第三位开始,等于自身前两位数相加
c = a+b;
a=b;
b=c;
// 1 1 2 3 5
// a b c
// 1 1 2 3 5
// a b c
// 1 1 2 3 5
// a b c
}
System.out.println(c);
}
}
}// 图 25,只是计算简单加法,效率要高很多
有些问题天然就是使用递归方式定义的(例如斐波那契数列, 二叉树等), 此时使用递归来解就很容易.
有些问题使用递归和使用非递归(循环)都可以解决. 那么此时更推荐使用循环, 相比于递归, 非递归程序更加高效
以上是脚本宝典为你收集整理的UseOfMethods - 方法的使用 - Java全部内容,希望文章能够帮你解决UseOfMethods - 方法的使用 - Java所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。