rokevin
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
  • 函数签名 Function Signature

  • 一、先看直观例子(Kotlin)
    • 1. 相同签名的函数(编译器会认为是同一个函数,报错)
    • 2. 不同签名的函数(合法的重载)
  • 二、函数签名的核心应用场景
    • 1. 函数重载(Overload)
    • 2. 函数类型匹配(和你之前问的“函数类型/函数式接口”强相关)
    • 3. 函数式接口的 SAM 转换
  • 三、补充:Kotlin vs Java 签名规则的小差异
  • 四、总结

函数签名 Function Signature

函数签名是用来唯一标识一个函数的核心特征集合,你可以把它理解成函数的“身份证”——编译器/编程语言通过这些特征区分不同的函数,核心作用是“识别函数、判断函数是否匹配”。

在 Kotlin/Java 等主流语言中,函数签名的核心组成是:

  1. 函数名
  2. 参数列表(参数的数量、类型、顺序)
  3. (部分场景)返回值类型(Kotlin/Java 中方法重载不看返回值,但函数类型匹配、接口抽象方法匹配会看)

注意:函数签名不包含函数体、参数名、访问修饰符(public/private)、注解等“非核心特征”。


一、先看直观例子(Kotlin)

1. 相同签名的函数(编译器会认为是同一个函数,报错)

// 函数1
fun calculate(a: Int, b: Int): Int {
    return a + b
}

// 函数2:仅参数名变了,签名和函数1完全一样 → 编译报错(重复定义)
fun calculate(x: Int, y: Int): Int { // ❌ 重复函数
    return x * y
}

// 函数3:仅返回值类型变了,Java 中算同签名,但 Kotlin 函数类型匹配时算不同
fun calculate(a: Int, b: Int): String { // Java 中编译报错,Kotlin 中允许(但重载无意义)
    return "${a + b}"
}

2. 不同签名的函数(合法的重载)

// 函数1:参数 (Int, Int)
fun calculate(a: Int, b: Int): Int {
    return a + b
}

// 函数2:参数 (Int, Int, Int) → 签名不同(参数数量变了)
fun calculate(a: Int, b: Int, c: Int): Int {
    return a + b + c
}

// 函数3:参数 (Int, String) → 签名不同(参数类型/顺序变了)
fun calculate(a: Int, b: String): Int {
    return a + b.toInt()
}

二、函数签名的核心应用场景

1. 函数重载(Overload)

只有签名不同的函数才能同名(重载),这是最基础的应用:

// 重载:签名分别是 (Int)、(String)、(Int, Int) → 合法
fun printValue(value: Int) { println("Int: $value") }
fun printValue(value: String) { println("String: $value") }
fun printValue(a: Int, b: Int) { println("Int+Int: ${a+b}") }

2. 函数类型匹配(和你之前问的“函数类型/函数式接口”强相关)

Kotlin 中判断“函数类型是否和函数式接口的抽象方法匹配”,核心就是对比签名:

// 函数式接口:抽象方法签名是 (String) -> Boolean
fun interface Validator {
    fun validate(input: String): Boolean
}

// 函数类型:签名 (String) -> Boolean → 和接口抽象方法签名完全匹配 → 可自动转换
val checkLength: (String) -> Boolean = { it.length > 6 }
val validator: Validator = checkLength // ✅ 签名匹配,转换成功

// 函数类型:签名 (Int) -> Boolean → 签名不匹配 → 编译报错
val checkAge: (Int) -> Boolean = { it > 18 }
val validator2: Validator = checkAge // ❌ 类型不匹配

3. 函数式接口的 SAM 转换

SAM 转换能生效的前提是:lambda 的签名和接口抽象方法的签名完全一致:

// 接口抽象方法签名:(Int, Int) -> Int
fun interface Calculator {
    fun compute(a: Int, b: Int): Int
}

// lambda 签名:(Int, Int) -> Int → 匹配 → SAM 转换生效
val add = Calculator { a, b -> a + b } // ✅

// lambda 签名:(Int) -> Int → 不匹配 → 编译报错
val double = Calculator { a -> a * 2 } // ❌ 参数数量不匹配

三、补充:Kotlin vs Java 签名规则的小差异

规则JavaKotlin
返回值是否算签名不算(仅参数列表+函数名)函数重载时不算,但函数类型匹配时算
参数顺序是否算签名算((Int,String)≠(String,Int))算(和 Java 一致)
参数名是否算签名不算不算

四、总结

  1. 核心定义:函数签名是函数的“身份证”,核心包含函数名 + 参数列表(数量/类型/顺序),部分场景包含返回值类型。
  2. 核心作用:区分不同函数(重载)、判断函数类型/接口方法是否匹配(SAM 转换/函数类型转换)。
  3. 关键特征:参数名、修饰符、函数体等不算签名,参数类型/数量/顺序是核心。

简单记:看函数“长什么样”,不看“叫什么名字(参数名)”、不看“做什么事(函数体)”,就是函数签名。

最近更新:: 2026/4/2 20:07
Contributors: luokaiwen