Kotlin关键字三——fun与方法

前两节笔记分析了属性的定义构造方法,这次看下修饰方法的关键字fun。

基本使用

fun应该说是kotlin所有关键字中最简单的一个,比var都简单,就是用在方法名前标识这是个方法。kotlin中方法定义的基本结构是:

kotlin 复制代码
访问修饰符 fun 方法名(参数名一:类型一, 参数名二:类型二,...):返回类型{
	...
    return 返回值
}

格式很简单,但还是需要注意几点

  • 默认的访问修饰符是public
  • 方法默认是final的,不能被子类重写
  • 无返回值时返回类型可以不写,与java不同的是不写返回类型时kotlin返回的Unit而不是void

按上面的模版为Person添加方法:

kotlin 复制代码
class Person(var name: String, var age: Int) {
    fun introduce(description: String): String {
        return "我叫${name},我今年${age}岁,${description}"
    }
}

// 调用
val person = Person("张三",28)
val introduce = person.introduce("我对这份工作非常感兴趣")
// 会输出: 我叫张三,我今年28岁,我对这份工作非常感兴趣
println(introduce)

默认参数

在上面introduce方法中,如果参数description大多时候都是相同的,那么就可以使用默认参数来定义方法:

kotlin 复制代码
class Person(var name: String, var age: Int) {
    fun introduce(description: String = "我对这份工作非常感兴趣"): String {
        return "我叫${name},我今年${age}岁,${description}"
    }
}

// 调用
val person = Person("张三",28)
val introduce = person.introduce()
// 同样会输出: 我叫张三,我今年28岁,我对这份工作非常感兴趣
println(introduce)

通过设置默认值在一定程度上方便了我们的调用。而在java中可以通过方法重载实现该功能。而java中方法重载需要我们写两个方法,而kotlin中的默认参数只需要写一个方法。

实现原理

转换成java代码如下:

java 复制代码
public final class Person {
    public final String introduce(@NotNull String description) {
      return "我叫" + this.name + ",我今年" + this.age + "岁," + description;
   }

   public static String introduce$default(Person var0, String var1, int var2, Object var3) {
      if ((var2 & 1) != 0) {
         var1 = "我对这份工作非常感兴趣";
      }
      return var0.introduce(var1);
   }
}

public final void main() {
   Person person = new Person("张三", 18);
   Person.introduce$default(person, (String)null, 1, (Object)null);
}

可以看到会多生成一个静态方法Person.introduce$default , main方法中调用的实际上也是这个静态方法。

这个静态方法中一共有4个参数

参数名 作用
var0 对象的具体实例
var1 对应introduce放在中的description参数
var2 &1来判断是否传入了description的值
var3 方法中没有使用,不知道它的作用,有知道的小伙伴可以在留意,感谢!!!

推测下,如果再定义一个默认参数,Person.introduce$default会不会再多出两个参数,一个用来标识这个参数是否有值,一个用了传值?验证下:

kotlin 复制代码
fun introduce(description: String = "我对这份工作非常感兴趣", salary: Int = 50000): String {
        return "我叫${name},我今年${age}岁,${description}, 我的期望薪资是${salary}"
}

对于有多个默认参数的方法,可以在调用是直接通过参数名来指定为哪个参数复制:

kotlin 复制代码
// 可以在调用是直接指明为哪个参数赋值
person.introduce(salary = 30000)

对应的java代码

java 复制代码
public static String introduce$default(Person var0, String var1, int var2, int var3, Object var4) {
  if ((var3 & 1) != 0) {
       var1 = "我对这份工作非常感兴趣";
    }

    if ((var3 & 2) != 0) {
       var2 = 50000;
    }
    return var0.introduce(var1, var2);
}

可以看到与之前相比只增加了一个参数,分别用&1和&2来标识第一默认参数和第二个默认参数是否有值

看到有朋友这么描述此时的var3:与有默认参数在静态方法参数的index做&操作,不等于表示参数没有传值,使用默认参数。如果为0表示有传值直接调用实例的具体方法实现。 这个说法是错误的,&的并不是索引,而是二进制的位数对应的值。

用一个int类型变量,它的二进制数从低到高依次对应每一个默认参数,0代表无值,1代表有值

疑问?int是32位的,如果默认参数超过32个会怎么样,感兴趣的小伙伴可以试下。

相关推荐
冬奇Lab1 小时前
Camera2 API架构基础:Android视频系统的大门
android·音视频开发·源码阅读
hnlgzb1 小时前
安卓app kotlin语法,Hilt是什么东西?
android·开发语言·kotlin
Android系统攻城狮3 小时前
Android tinyalsa深度解析之pcm_params_get_periods_min调用流程与实战(一百七十三)
android·pcm·tinyalsa·音频进阶手册
Xempastissimo4 小时前
Android常见界面控件
android
法欧特斯卡雷特4 小时前
从 Kotlin 编译器 API 的变化开始: 2.3.20
android·后端·开源
词元Max5 小时前
1.5 Harness 架构深度解析:Claude Code 为什么强?
android·架构
yy55275 小时前
Mysql 主从复制与读写分离
android·数据库·mysql
zhenxin01226 小时前
万字详解 MySQL MGR 高可用集群搭建
android·mysql·adb
做萤石二次开发的哈哈6 小时前
萤石云硬件接入如何完成云对讲套件低代码集成?
android·低代码·rxjava
simplepeng7 小时前
Kotlin 协程桥接(suspendCoroutine):将任意基于回调的 Android API 转换为挂起函数
kotlin