进一步理解函数
admin
2024-02-24 18:47:08
0

函数的定义和基本调用应该是比较容易理解的,但有很多细节可能令初学者困惑,包括参数传递、返回、函数命名、调用过程等,我们逐个介绍。

1.参数传递
有两类特殊类型的参数:数组和可变长度的参数。
(1)数组
数组作为参数与基本类型是不一样的,基本类型不会对调用者中的变量造成任何影响,但数组不是,在函数内修改数组中的元素会修改调用者中的数组内容。我们看个例子:
public static void reset(int[] arr){
    for(int i=0;i
        arr[i] = i;
    }
}
public static void main(String[] args) {
    int[] arr = {10,20,30,40};
    reset(arr);
    for(int i=0;i
        System.out.println(arr[i]);
    }
}
在reset函数内给参数数组元素赋值,在main函数中数组arr的值也会变。
这个其实也容易理解,我们在1.2节介绍过,一个数组变量有两块空间,一块用于存储数组内容本身,另一块用于存储内容的位置,给数组变量赋值不会影响原有的数组内容本身,而只会让数组变量指向一个不同的数组内容空间。
在上例中,函数参数中的数组变量arr和main函数中的数组变量arr存储的都是相同的位置,而数组内容本身只有一份数据,所以,在reset中修改数组元素内容和在main中修改是完全一样的。
(2)可变长度的参数
前面介绍的函数,参数个数都是固定的,但有时候可能希望参数个数不是固定的,比如求若干个数的最大值,可能是两个,也可能是多个。Java支持可变长度的参数,如下例所示:
public static int max(int min, int ... a){
    int max = min;
    for(int i=0;i
        if(max
            max = a[i];
        }
    }
    return max;
}
public static void main(String[] args) {
    System.out.println(max(0));
    System.out.println(max(0,2));
    System.out.println(max(0,2,4));
    System.out.println(max(0,2,4,5));
}这个max函数接受一个最小值,以及可变长度的若干参数,返回其中的最大值。可变长度参数的语法是在数据类型后面加三个点“...”,在函数内,可变长度参数可以看作是数组。可变长度参数必须是参数列表中的最后一个,一个函数也只能有一个可变长度的参数。
可变长度参数实际上会转换为数组参数,也就是说,函数声明max(int min,int...a)实际上会转换为max(int min,int[]a),在main函数调用max(0,2,4,5)的时候,实际上会转换为调用max(0,new int[]{2,4,5}),使用可变长度参数主要是简化了代码书写。

2.理解返回
对初学者,我们强调下return的含义。函数返回值类型为void时,return不是必需的,在没有return的情况下,会执行到函数结尾自动返回。return用于显式结束函数执行,返回调用方。
return可以用于函数内的任意地方,可以在函数结尾,也可以在中间,可以在if语句内,可以在for循环内,用于提前结束函数执行,返回调用方。
函数返回值类型为void也可以使用return,即“return;”,不用带值,含义是返回调用方,只是没有返回值而已。
函数的返回值最多只能有一个,那如果实际情况需要多个返回值呢?比如,计算一个整数数组中的最大的前三个数,需要返回三个结果。这个可以用数组作为返回值,在函数内创建一个包含三个元素的数组,然后将前三个结果赋给对应的数组元素。
如果实际情况需要的返回值是一种复合结果呢?比如,查找一个字符数组中所有重复出现的字符以及重复出现的次数。这个可以用对象作为返回值,我们在第3章介绍类和对象。虽然返回值最多只能有一个,但其实一个也够了。

3.重复的命名
每个函数都有一个名字,这个名字表示这个函数的意义,名字可以重复吗?在不同的类里,答案是肯定的,在同一个类里,要看情况。
同一个类里,函数可以重名,但是参数不能完全一样,即要么参数个数不同,要么参数个数相同但至少有一个参数类型不一样。
同一个类中函数名相同但参数不同的现象,一般称为函数重载
 。为什么需要函数重载呢?一般是因为函数想表达的意义是一样的,但参数个数或类型不一样。比如,求两个数的最大值,在Java的Math库中就定义了4个函数,如下所示:
public static double max(double a, double b)
public static float max(float a, float b)
public static int max(int a, int b)
public static long max(long a, long b)

4.调用的匹配过程
在之前介绍函数调用的时候,我们没有特别说明参数的类型。这里说明一下,参数传递实际上是给参数赋值,调用者传递的数据需要与函数声明的参数类型是匹配的,但不要求完全一样。什么意思呢?Java编译器会自动进行类型转换,并寻找最匹配的函数,比如:
char a = 'a';
char b = 'b';
System.out.println(Math.max(a,b));

参数是字符类型的,但Math并没有定义针对字符类型的max函数,这是因为char其实是一个整数(我们在2.4节会说明),Java会自动将char转换为int,然后调用Math.max(int a,int b),屏幕会输出整数结果98。
如果Math中没有定义针对int类型的max函数呢?调用也会成功,会调用long类型的max函数。如果long也没有呢?会调用float型的max函数。如果float也没有,会调用double型的。Java编译器会自动寻找最匹配的。
在只有一个函数的情况下,即没有重载,只要可以进行类型转换,就会调用该函数,在有函数重载的情况下,会调用最匹配的函数。

5.递归函数
函数大部分情况下都是被别的函数调用的,但其实函数也可以调用它自己,调用自己的函数就叫递归函数
 。为什么需要自己调用自己呢?我们来看一个例子,求一个数的阶乘,数学中一个数n的阶乘,表示为n!,它的值定义是这样的:
0!=1
n!=(n-1)!×n
0的阶乘是1,n的阶乘的值是n-1的阶乘的值乘以n,这个定义是一个递归的定义,为求n的值,需先求n-1的值,直到0,然后依次往回退。用递归表达的计算用递归函数容易实现,代码如下:
public static long factorial(int n){
    if(n==0){
        return 1;
    }else{
        return n*factorial(n-1);
    }
}
看上去应该是比较容易理解的,和数学定义类似。递归函数形式上往往比较简单,但递归其实是有开销的,而且使用不当,可能会出现意外的结果,比如说这个调用:
System.out.println(factorial(100000));

系统并不会给出任何结果,而会抛出异常。异常我们在第6章介绍,此处理解为系统错误就可以了。异常类型为java.lang.StackOverflowError,这是什么意思呢?这表示栈溢出错误,要理解这个错误,我们需要理解函数调用的实现原理,我们1.7节介绍。
那递归不可行的情况下怎么办呢?递归函数经常可以转换为非递归的形式,通过循环实现。比如,求阶乘的例子,其非递归形式的定义是:
n!=1×2×3×…×n
这个可以用循环来实现,代码如下:
public static long factorial(int n){
    long result = 1;
    for(int i=1; i<=n; i++){
        result=result*i;
    }
    return result;
}

想要了解更多Java基础知识,可以点击评论区链接和小编一起学习java吧,此视频教程为初学者而著,零基础入门篇!给同学们带来全新的Java300集课程啦!java零基础小白自学Java必备优质教程_手把手图解学习Java,让学习成为一种享受_哔哩哔哩_bilibili

相关内容

热门资讯

四川银行获批收购都江堰金都村镇... 北京商报讯(记者 宋亦桐)7月7日,四川金融监管局发布《关于四川银行股份有限公司收购都江堰金都村镇银...
2026 电商核定征收新政落地... 2026 年 7 月 17 日电商网店核定征收政策正式实施,全品类、全店铺主体均可适配,针对小微、中...
股权溢价约三倍,40日收益差修... 7月7日,A股三大指数呈震荡调整态势,中证红利ETF招商(515080)低位盘整,但成份股中不乏亮点...
微软裁员4800人,Xbox部... 来源:环球市场播报 核心要点 微软在推出自愿退休计划后,本轮整体裁员 4800 人。 旗下 X...
黄金突然跳水!4200美元关口... 周一(7月6日),现货黄金延续整理走势。此前金价从逾7个月低点3941美元反弹,但在美元走强以及温和...
别再靠感觉炒股!把交易纪律“喂... 最近的市场让不少老股民直呼“难做”。 上半年资金极致抱团AI算力、CPO、存储芯片等科技成长赛道,进...
上港集团董事长与江苏省港口集团... 双方就深化合资合作、业务协同、智慧绿色港口建设等话题,进行深入交流。 7月6日,上港集团党委书记、董...
美国22个州反对联邦政府加征关... 新华社北京7月7日电 美国22个州的总检察长6日联合反对美国联邦政府以所谓“未禁止进口强迫劳动产品”...
沈阳一保洁把偷来的50克黄金首... “我出去买点东西 这间屋不用收拾 其他的屋打扫干净……” “这屋不用收拾 屋里到底有啥啊?” “我的...
部分酒庄游,面临订单变小、赊货... 今年以来,国内外葡萄酒产区和酒庄针对渠道商组织的酒庄游活动依然丰富,但部分效果相比往年却大打折扣。如...
全视通智慧医院解决方案:构建数... 我们印象中的医院是怎样的?是挂号窗口前的长龙,是诊室门口焦急的等待,是穿梭于不同楼层寻找检查室的迷茫...
2025年财报封神,今年一季度... 来源|深氪新消费 朱末 一边是创下历史纪录的年度盈利,一边是造车业务单季31亿巨额亏损,不过短短数月...
国泰基金非货ETF规模跃升,“... 2026年上半年,国内ETF市场经历了一场深刻而剧烈的结构性重塑——宽基ETF遭遇万亿级资金流出,行...
半两财经|财政部拟发行300亿... 7月7日,财政部发布公告,拟发行2026年超长期特别国债(五期)。本期国债为20年期固定利率附息债。...
摩根大通、美国银行等多家金融机... 当地时间7月6日,《华尔街日报》援引消息人士的话透露,包括摩根大通、美国银行、富国银行和PNC金融服...
软银、Altimeter与D1... 来源:环球市场播报 繁荣资本(Thrive Capital)创始人乔希・库什纳 多家重仓 Open...
原创 自... 谁也没有想到,曾经依靠中国数百亿美元资金投入、先进冶炼技术以及完整产业链支持,一步步打造出全球镍产业...
A股收评:近4800只个股飘绿... 7日,A股三大指数集体低开,随后震荡下行。截至收盘,沪指跌1.26%,失守4000点;深证成指跌1....
小猿淘金APP非法期货交易骗局...   小猿淘金等平台在多个网络渠道投放广告,以“5元即可投资”等低门槛宣传吸引投资者开户操作。然而,经...