{ }codelper

学习 › Java

函数 · 14

函数

给一段工作起名字,接收值并返回结果,还有递归。

函数是有名字的一段代码。
它接收值(参数),并返回结果。
下面的示例定义了一个求平方的函数,和一个调用自己的阶乘函数。

import java.util.Scanner; public class Main {    static int square(int x) {        return x * x;    }     static long factorial(int n) {        if (n <= 1) return 1;        return n * factorial(n - 1);    }     public static void main(String[] args) {        int n = new Scanner(System.in).nextInt();        System.out.println(square(n));        System.out.println(factorial(n));    }}
stdin
4
stdout
16
24

要点

  • 同一个计算要在多处使用,或者想把长的解法拆成小块时,就把代码包成函数。
  • 一执行到 return,函数就当场结束,下面的行不会执行。
  • 传数字时会复制值。
    在函数里写 x = 9,调用方的变量不变。
  • 传列表时共用同一个列表。
    在函数里添加元素,外面也会跟着变(C++ 的 vector 传参时会复制)。
  • 递归就是函数调用自己。
    它把大问题缩小成同样形状的小问题,而且一定要有停止条件(n <= 1 时返回 1)。
  • 没有停止条件或递归太深时,程序会报错停止或直接崩溃,取决于语言。

各语言的写法

Pythondef square(x): 加缩进。
没有 return 时返回 None。
只能在 def 执行之后调用(先调用报 NameError)。
递归默认约 1,000 层时报 RecursionError
JavaScriptfunction square(x) { return x * x; } 或 const square = (x) => x * x;。
没有 return 时返回 undefined。
function 声明可以写在调用处下面。
太深报 RangeError: Maximum call stack size exceeded
TypeScriptJavaScript 加上类型:function square(x: number): number。
参数个数不对时类型检查会提示
Java在类里写 static int square(int x);不返回值写 void。
放在类里任何位置都行。
太深报 StackOverflowError
C#和 Java 一样在类里写 static int Square(int x),不返回值写 void。
递归太深会让整个程序崩溃
C++像 int square(int x) 这样把返回类型写在前面,不返回值写 void。
使用前先在上面定义,或用 int square(int x); 声明。
递归太深程序会崩溃
C和 C++ 一样
Craykon不需要关键字:square(x) { 返回 x * x; }。
可以写在调用处下面。
调用超过几千层会停止,并提示函数调用得太深

常见错误

没有停止条件

def factorial(n):
    return n * factorial(n - 1)

→ 无限调用自己,最后报 RecursionError 停止。其他语言也会栈溢出而停止或崩溃

在最前面放停止条件,比如 if n <= 1: return 1。

调用时漏了参数JavaScript

function square(x) { return x * x; }
console.log(square());

→ NaN — 缺少的 x 被悄悄补成了 undefined

参数个数要对上。
Python(TypeError)、Java、C#、C、C++、TypeScript(编译错误)和 Craykon(“需要 2 个值却只给了 1 个”)都会提示。

在函数里改了,原来的却没变C++

void add(std::vector<int> v) { v.push_back(9); }

std::vector<int> a = {1};
add(a);

→ a 仍然是 {1} — 加到了副本里

要修改原来的,就加 &:std::vector<int>& v。

各语言的差异
阶乘增长得很快。
32 位 int 只能装到 12!(在 Java 中用 int 算 13! 会不报错地得到 1932053504),所以 Java、C#、C、C++ 示例返回 64 位的 long/long long(可到 20!),而 Python 没有大小限制,JavaScript 和 Craykon 超过 2^53 后可能不精确。

练习题