进一步理解函数
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

相关内容

热门资讯

原创 王... 说起王家卫的作品,很多人都会不自觉地想到那种说不清、道不明的独特气质。每次看他的电影或电视剧,总感觉...
中国工商银行发布风险提示 2月1日,中国工商银行股份有限公司发布“关于进一步做好贵金属市场风险防范的提示”。 工行表示,近期国...
美国纳斯达克上市条件和费用详解 美国纳斯达克是全球最大的科技股交易市场之一,吸引了众多企业的关注和追逐。但是,想要在纳斯达克上市并不...
原创 全... 鲁网2月2日讯 近日,青岛市首只完成注册备案并取得实质性投资的AIC(金融资产投资公司)股权投资基金...
港股异动 | 神州控股早盘一度... 2月2日早盘,神州控股一度涨超48%;截至9时47分,该股涨36.47%,报3.63港元/股。 上...
印尼股市暴跌引发连锁反应 多名... 印度尼西亚综合股价指数近期出现剧烈震荡,并引发一系列连锁反应。印尼证券交易所、印尼金融服务管理局等机...
甲减怕冷没力气?北京融科甲状腺... 寒冬来临,不少甲减患者又陷入了“畏寒怕冷、浑身乏力”的困境:穿得比别人厚几倍仍手脚冰凉,稍微活动就疲...
有色金属概念股走弱,矿业、有色... 有色金属概念股走弱,山东黄金、中金黄金跌停,北方稀土跌超5%,紫金矿业、洛阳钼业、中国铝业跌超4%。...
太拼!米粉为集9色车模试驾9次... 快科技2月2日消息,昨日晚间,小米创办人,董事长兼CEO雷军在小米汽车试验室进行直播,揭秘新一代SU...
福石控股:实控人被留置 将持续... 来源:每日经济新闻 2月1日晚间,福石控股(300071)公告称,公司近日收到国家某监察委员会签发...
李亚鹏,一夜卖了1.6亿元茶叶... 1月30日,李亚鹏时隔一周再开播,平台带货总榜再度登顶,断崖式领先“与辉同行”,在线人数10万+。李...
原创 李... 想想李嘉诚当年那番话,现在看来真准。 早在2017年,他就说香港和内地房价会面临大调整,因为前几年需...
一天蒸发6.5万亿美元!全球抛... 在美国总统特朗普宣布提名凯文·沃什为下一任美联储主席后,再加之中东地缘政治局势影响,全球加密货币市场...
全明星替补阵容:詹姆斯领衔 华... 搜狐体育消息,北京时间2月2日,NBA官方公布了全明星的替补阵容。 西部全明星替补:爱德华兹(森林狼...
委员风采丨陈荣熙:向海图强 助... 向海图强 助力港口“吞吐”新未来 县政协委员 陈荣熙 “二期码头已进入尾声,计划2026年投产,预...
开年以来多家A股公司更新赴港I... 来源:证券日报 进入2026年,A股公司赴港上市持续活跃,截至目前,已有3家A股公司成功在港上市。同...
小米汽车1月交付量下降,雷军:... 2月1日晚,小米创办人,董事长兼CEO雷军在直播中回应“小米汽车交付量被指环比下降”,雷军表示这是一...
雷军:新一代小米SU7已结束研... 快科技2月2日消息,小米创始人雷军日前开启了一场科普直播,主要在小米汽车工厂实验室揭秘新一代SU7的...