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个会怎么样,感兴趣的小伙伴可以试下。

相关推荐
帅得不敢出门7 小时前
安卓设备adb执行AT指令控制电话卡
android·adb·sim卡·at指令·电话卡
我又来搬代码了8 小时前
【Android】使用productFlavors构建多个变体
android
德育处主任10 小时前
Mac和安卓手机互传文件(ADB)
android·macos
芦半山10 小时前
Android“引用们”的底层原理
android·java
迃-幵11 小时前
力扣:225 用队列实现栈
android·javascript·leetcode
大风起兮云飞扬丶11 小时前
Android——从相机/相册获取图片
android
Rverdoser11 小时前
Android Studio 多工程公用module引用
android·ide·android studio
aaajj11 小时前
[Android]从FLAG_SECURE禁止截屏看surface
android
@OuYang11 小时前
android10 蓝牙(二)配对源码解析
android
Liknana11 小时前
Android 网易游戏面经
android·面试