函数

函数对于我们大家而言都不陌生,无论是在数学还是物理的学习中我们都接触过函数这个概念,但是在Java语言中函数是非常复杂的,因为它不仅要定义自己本身的功能,还要根据当前代码环境进行适当的变换,每一个函数在不同的代码环境中都是不同的,即使是相同的函数在不同的代码环境中都有可能表示不同的功能。

函数的定义

那什么是函数呢?函数是定义在类中的具有特定功能的一段独立小程序,函数也称之为方法。

那设定函数的作用是什么呢?为了提高代码的复用性,对代码进行抽取。将这个部分定义成一个独立的功能,进行再次封装,以便再次或多次使用。 java中对功能的定义通过函数来实现的。

相比于其他方法,设定函数有什么优势?通过下图我们可以发现,函数可以将代码进行适当的拆分,这样就降低了主函数的代码量,并且复用函数可以大大降低代码冗余,以便内存优化。

常规方法:

class Demo01{
    public static void main(String[] args){
        int a=1;
        int b=2;
        int c=3;
        System.out.println(a+b);
        System.out.println(a+c);
        System.out.println(b+c);
    }
}

 调用函数:

import java.util.Scanner;
class Demo01{
    public static void main(String[] args){
        Scanner scanner=new Scanner(System.in);
        int a=scanner.nextInt();
        int b=scanner.nextInt();
        System.out.println(add(a,b));
    }
    public static int add(int a,int b){
        int sum=a+b;
        return sum;
    }
}

注:虽然看起来调用函数所写的代码更多,但是它的含义是你输入任何两个值,它都会将两个数值求和,可谓是一劳永逸。

函数的格式

访问权限 函数类型 返回值类型 函数名(参数列表){
    函数体
    return 返回值;
}

上面就是函数的格式,第一眼看到这个因为类型太多可能有些萌,那我就来举一个很普遍的例子,也是目前为止我们见得最多的一个函数:

public static void main(String[] args){
    System.out.pringtln("来了老弟~");
}

那我们就来按照函数的格式详细分析一下上述代码:

  • 访问权限:指的就是函数的使用范围(内部和外部)
  • 函数类型:指的就是函数类型分类,说的就是函数的具体使用场景和场合
  • 函数名:就是程序员给这一段代码自定义的名称(标识符)
  • 参数列表:参数列表有若干个 参数类型,参数名... 组成 主要用于接收外界传递给函数的一些数据
  • 函数体:就是那些具有独立功能的代码块
  • return:仅仅表示结束当前函数,如果有返回值,则函数结束前将返回值返回给调用者
  • 返回值:指的就是这一具有独立功能的代码块的计算结果,需要传递给外界 配合return
  • 返回值类型:就是返回值的数据类型(可兼容)

那为什么上面展示的代码没有return呢?那是因为主函数main的返回值类型(void)是无返回值类型的,也就是说实际上它是有return的,但是由于没有返回值,因此return没有实际意义,所以在主函数main中,return就自动省略了。

函数的分类

  1. 有返回值有参数
  2. 有返回值无参数
  3. 无返回值有参数
  4. 无返回值无参数

注意:有返回值的函数,返回值会参与运算、输出、赋值;没有返回值的函数,仅仅是调用。例如前面举到的例子,add就是有返回值的函数,那么它的返回值sum就会参与运算与输出。

函数传参

函数传参很容易理解,就是给函数传递参数。函数中的参数分为两种,实参和形参。

  • 实参:就是实际参数,在调用函数的时候,给函数传递的数据(常量、变量)叫做实参
  • 形参:就是形式参数,在定义函数的时候,参数列表中的数据,叫做形参

实参表面上是将一个数据常量传递给了形参,其实不是,而是将常量在常量池中的地址(常量的地址)传递给了形参,还有一种是将对象在堆内存中的地址传递给了形参。那什么是堆内存呢?这个之后总结面向对象的时候会总结到。

既然是函数,那么肯定会有变量,在函数中创建的变量我们就叫做局部变量。局部变量只在当前函数中起作用。形式参数一定是局部变量,但是局部变量不一定都是形式参数。

我在这里举一个例子,并且用图解来表示一下函数传参的简单流程:

main(){
    int a=4;
    int b=4;
    double c=pow(a,b);
}

pow(a,b){
    ...
    return sum;
)

函数传参的流程图:

java中有析构函数吗 java解析函数_java

函数栈

栈是Java语言中非常重要的一个知识点,为什么这么说呢?因为函数的运行都是基于栈内存的。那到底什么是栈呢?栈其实很简单,说白了我们可以将栈比作一个先进后出的容器,系统运行代码,根据Java的规则,将函数按流程放到栈内存中,然后再根据栈内存中函数的顺序依次运行函数。(运行函数时,优先读取主函数)

那函数放到栈内存以及在栈内存中运行函数的流程顺序到底是怎样的呢?就例如将子弹放到弹夹里面,最先放进去的就在弹夹的最下面,自然也就时最后一个发射出去的,栈就是如此。那么函数中的return自然就相当于将子弹发射出去,也就是我们说的函数运行完后返回函数值,然后此函数弹出栈内存——弹栈。

下面是函数栈运行的流程图解:

java中有析构函数吗 java解析函数_栈内存_02

 

函数的重载

函数的重载就是指在同一个类中出现了同名的函数。那有些伙计就会问道:既然函数能够重复调用,那为什么还会出翔同名的函数呢?其实原因很简单,在我们的认知里,一种函数只是代表了一种算数方法而已,但是兄弟们仔细想想,计算机语言是非常严谨的,它非常在意数据的类型,也就是说即使是同一个函数,里面的数据类型不兼容也有可能产生编译错误或者运行错误的问题。这就要使用函数的重载了。

根据以上的内容,我们可以总结一下几点:

  • 重载与函数的权限无关、与函数的返回值无关、与参数名无关,只和参数类型和排列顺序有关
  • 重载的好处就是我们可以拓展函数的功能(通过改变同一函数的参数类型来执行不同的内容,但是算法一样)

下面就用一篇代码来解释一样函数的重载:

class chongzai{
    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));
    }
    public static String add(String a,String b){   // //String型,用于字符串连接
        System.out.println("String+String");
        return a+b;
    }
    public static String add(double a,double b){
        System.out.println("double+double");
        return a+b;
    }
    public static String add(int a,int b){
        System.out.println("int+int");
        return a+b;
}