第七天(函数)

函数

huan? han? 这两个读音早就搞不清楚了,怪不得函数也搞不清楚。

 

讲函数之前感觉十分有必要先对这个东西进行一个浅显易懂的认识。

额 刚去百度了下,答案十分统一都是怎么说的呢?

函数主要解决的是那些重复的且具有独立功能的代码段......巴拉巴拉一大堆,也没有说是举个栗子,就比较难。

4.1 函数的定义

函数存在的意义(一句一句来)

函数主要解决的是那些重复的且具有独立功能的代码段

将这些具有独立功能的代码可以进行再次封装 封装出来的东西就成为是函数

(什么意思呢?也就是说你写的程序里出现很多功能重复的代码,只不过就是这些代码解决的问题是不一样的,但是功能相同,举个栗子,你想要在一段代码里求一个绝对值,然后你巴拉巴拉写下一大堆,这个问题解决了,但是你一看题发下需要你再求一个函数的绝对值,然后你又巴拉巴拉写下一大堆,麻不麻烦?冗余不冗余?当时胖胖老师讲的时候我就真想说不麻烦,但后来慢慢的理解了,确实是有点麻烦,只不过从主函数到其他函数有点不太理解而已,慢慢的熟练了就好了。)

上面的这个例子刚好承上启下,怎么硕呢?这样写的优点是什么呢

  1. 降低了代码冗余,复用函数即可。
  2. 降低了主函数的代码量,将主函数进行适当的拆分,以便内存优化

 (这个又怎么理解呢?现在解决的都是比较小的问题,那么一旦这是一个特别大的问题,你的主函数就好长好长,这个时候编译报错,即便你知道错误是啥,你找也得好长时间,因为你得从头向下找,但是如果有函数,你就可以把主函数拆分成好多个部分,这个时候你找问题就可以在主函数里找,然后对应的去实现这个功能的函数里找问题,是不是方便多了。)

函数的格式

  • 访问权限

指的就是函数的使用范围(内部和外部) 

就好比你的东西有权限,比如你的钱包是你的隐私,你的外套是公用的!!!(因为我突然想起上高中那会,你要是穿个好看的衣服,和你一起的那些小伙子们就要穿。。。这个栗子有点故事),这些权限就是,protect,public,private。还有一种就是默认不写就自动的认为是private,就比如你的好多东西没给其他人说这些是什么权限,但是别人都会默认这些东西是你自己的隐私呗。

  • 函数类型

指的就是函数类型分类,说的就是函数的具体使用场景和场合

static 静态函数 abstract 抽象函数 native 本地函数 synchronized 同步函数,先不说这几个,因为我也不知道

后边碰到了再说

  • 函数名

就是程序员给这一段代码自定义的名称(标识符)

(虽然这么说,但是人家国际上早就有固定的函数名,咦,比如主函数,人家说main是标识符,但是你好意思改吗,就算好意思,你早就把public static void main背的滚瓜烂熟了)

  • 参数列表

参数列表有若干个 参数类型,参数名... 组成 主要用于接收外界传递给函数的一些数据

(就是一个函数后边跟一个(),构造函数的意思,你比如说你的括号里是int那么这个int代表的是你的参数列表允许接收外界传来的int类型的值,如果不是int的话就报错了)

  • 函数体

就是那些具有独立功能的代码块

(这不扯犊子吗,函数体不就是大括号里边的东西么)

  • return

仅仅表示结束当前函数,如果有返回值,则函数结束前将返回值返回给调用者

(以前学c的时候不管有没有返回值结尾总要跟个return现在,乍一看java中的主函数后边一般都没有,实际上,只是隐藏了不是默认没有,其他函数在实现的时候就会出现这个return,这个return就是将返回值返回调运这个函数的那个变量吧(应该是变量,反正就是调用这个函数的东西))

  • 返回值

指的就是这一具有独立功能的代码块的计算结果,需要传递给外界 配合return

(这没啥说的,意思就是你要返回的值么)

  • 返回值类型

就是返回值的数据类型(可兼容)

 

4.2 函数的分类

按照有无返回值和有无参数把函数分为了四部分

有返回值的函数,参与运算、输出、赋值    无返回值的函数,仅仅调用(怎么通俗易懂的说呢,就是说有返回值的能干实在事,无返回值好比是废物)看他有没有用主要就是看他有没有返回值,就好比参数列表是你食的俸禄,而返回值就是你做的事情,你无参数无返回值 这就是无业游民,有参数无返回值就是贪官,无参数有返回值这是为人民服务,有参数有返回值这叫拿一份钱干一份事。

  • 有返回值有参数

  • 有返回值无参数

  • 无返回值有参数

  • 无返回值无参数

4.3 函数传参

实参和形参的区别(摘自百度用户:“从头再来好风彩”)

一、函数中使用:

形参出现在函数定义中,在整个函数体内都可以使用, 离开该函数则不能使用。

实参出现在主调函数中,进入被调函数后,实参变量也不能使用。 

二、调用

形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。

实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值。

三、不是指针类型在内存中位置不同:

当形参和实参不是指针类型时,在该函数运行时,形参和实参是不同的变量,他们在内存中位于不同的位置,形参将实参的内容复制一份,在该函数运行结束的时候形参被释放,而实参内容不会改变。

在一般传值调用的机制中只能把实参传送给形参,而不能把形参的值反向地传送给实参。(就是说形参这个人比较自私,实参把东西分享给形参,形参一辈子都不会把值分享给实参)因此在函数调用过程中,形参值发生改变,而实参中的值不会变化。(越想越气,原来形参还是一个如此多变的一个人,看看人家实参多老实)

实际参数-实参

就是在调用函数的时候,给函数传递的数据(常量,变量)叫做实参

(举个栗子,int a=4;a就是实参)

形式参数-形参

就是定义函数的时候,参数列表当中的数据,叫做形参

就是等待老实人形参传值的就是形参

实参是将什么东西传递给了形参呢

前边学习变量的时候就是知道了,传的是地址,地址也有两种一是常量在常量池中的地址,二是对象在堆内存中的地址

局部变量

但凡是在函数中创建的变量 称之为是局部变量 局部变量的作用域仅仅在当前的函数当中,所以形参一定是局部变量。

也不一定都是在其他函数里才有局部变量,比如在for循环里定义的一个变量,出了循环就不能被识别了。

4.4 函数栈

函数的运行是基于栈内存的

栈是啥玩意呢?通俗的来说栈可以是一个量筒也就是一个容器,所谓先进后出是啥意思呢,好比你给量筒里放乒乓球,第一个放进去的一定是最后一个出来的,这就是所谓的栈(一个先进后出的容器结构),每一个乒乓球就是(函数栈或者是栈帧),位于栈顶即量筒的顶部的函数帧是优先运行的。

最重要的是主函数永远是第一个进栈的,什么时候结束呢?当且仅当return结束了当前函数后,该函数弹栈(即出栈)

4.5 函数的重载

函数的重载指的就是同一个类中出现的同名函数

什么意思呢?看代码

class Test01{
    public static void main(String[] args){
        int a=3;
        int b=4;
        System.out.println(add(a,b));
        double d=3.14;
        double e=5.44;
        System.out.println(add(d,e));
        System.out.println(add(3,3.14));
        System.out.println(add(3.13,9));
    }
    //对两个小数进行加法运算
    // public static double add(double c,double d){
    //     return c+d;
    // }
    public static String add(String a,String b){
        System.out.println("String+String");
        return a+b;
    }
    // public static double add(int a,double b){
    //     System.out.println("int+double");
    //     return a+b;
    // }
    // public static double add(double a,int b){
    //     System.out.println("double+int");
    //     return a+b;
    // }
    public static double add(double a,double b){
        System.out.println("double+double");
        return a+b;
    }
    //对两个整数进行加法运算
    // public static int add(int a,int b){
    //     System.out.println("int+int");
    //     return a+b;
    // }
}

这段代码中定义了两个整形参数两个浮点型的参数

且调用了相同的函数add()只不过add的参数列表和函数类型不一样,会不会觉得多此一举呢?我们可以编译试一下,当求两个浮点型的变量的和时调用了int类型的函数且参数列表的传参列表也是整形,这个时候会出现编译报错,(意思是从double转int会有损失,和我们前边学的变量之间的转化一样的),这就解释了为什么会有同名函数,函数的重载与权限没关系,与返回值类型没关系,与参数名没关系,只有和参数类型的排列组合有关系(注意一下参数类型的向下兼容问题)。

那么重载有什么好处呢?直接写一个double不就得了?然而重载的好处就在于我们可以扩展函数的功能(函数重名,但是参数类型不一样,执行内容也可以不一样)同样的,怎么寻找适当的函数流程呢?

寻找适当函数的流程
1.看是否有确切的参数定义 int+int 查看是否有(int,int)
2.看是否有可兼容的参数定义 int+int 查看是否有(double,double)
3.如果可兼容的参数定义有多个int+int,(double,int)或(int,double) 此时报错 引用不明确

4.6 函数的递归调用

递归的体现就是函数自身调用函数自身

那么用for循环不好吗?(迭代)为什么还要搞得这么麻烦

一般而言,但凡能够被迭代(循环)解决的问题,递归都可以,但是递归解决的问题,迭代就不一定了。

递归其实是分治法的一种实现方式(一种实现思路)所谓分治法即:

分治法是一种算法思想,分治法主要解决的问题是将大问题,进行拆分,拆分成若干个小的问题进行求解,最终将每个小问题的解进行合并。其实,分治法就是一种暴力破解法(穷举),也是一种搜索最优答案的算法

递归就是函数在进栈,进栈的次数多了,势必会占内存,无法避免的(也就是说,相同的问题迭代和递归同时解决,所用的时间迭代是比递归要短的,而递归虽然代码量不多,但是递归因为占内存,所以时间会很长)
在某些问题上,递归所写的代码要比迭代写的代码少,在某些问题上,迭代是写不出来的,所以只能用递归。

递归:先递,后归(就是把大问题变成许许多多的小问题)而递归之所以慢是因为递归的时间复杂度高(关于时间复杂度,后边说)

前进段:指的就是讲问题从大化小

结束段:问题无法再继续化小,则处理当前的问题

返回段:将小问题处理完毕之后,向上返回(有些问题是不需要返回的)


        问题1:计算1+2+3+4+5+...+98+99+100
        f(n) 是求1~n的累加
        f(100)就是我们当前最大的问题
        写递归时,一定要先写它的end!
        ↓ 递
        f(n)=f(n-1)+n
        f(100)=f(99)+100    return 1+2+3+..+99 +100
        f(99)=f(98)+99      return 1+2+...+98 +99
        ...
        f(4)=f(3)+4         return 1+2+3+4
        f(3)=f(2)+3         return 1+2+3
        f(2)=f(1)+2         return 1+2
        f(1)=1              return 1
        → end               ↑ 归
       

这就是利用递归去解决前100项和的思想

class Test02{
    public static void main(String[] args){
        System.out.println(f(10));
    }
    public static int f(int n){
        if(n==1){
            return 1;
        }
        return f(n-1)+n;
    }
}

4.7 常用函数

具体参照 

JavaTM Platform Standard Edition 6
API 规范

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

                

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值