前两节笔记分析了属性的定义及构造方法,这次看下修饰方法的关键字fun。
基本使用
fun应该说是kotlin所有关键字中最简单的一个,比var都简单,就是用在方法名前标识这是个方法。kotlin中方法定义的基本结构是:
访问修饰符 fun 方法名(参数名一:类型一, 参数名二:类型二,...):返回类型{
...
return 返回值
}
格式很简单,但还是需要注意几点
- 默认的访问修饰符是public
- 方法默认是final的,不能被子类重写
- 无返回值时返回类型可以不写,与java不同的是不写返回类型时kotlin返回的Unit而不是void
按上面的模版为Person添加方法:
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大多时候都是相同的,那么就可以使用默认参数来定义方法:
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代码如下:
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会不会再多出两个参数,一个用来标识这个参数是否有值,一个用了传值?验证下:
fun introduce(description: String = "我对这份工作非常感兴趣", salary: Int = 50000): String {
return "我叫${name},我今年${age}岁,${description}, 我的期望薪资是${salary}"
}
对于有多个默认参数的方法,可以在调用是直接通过参数名来指定为哪个参数复制:
// 可以在调用是直接指明为哪个参数赋值
person.introduce(salary = 30000)
对应的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个会怎么样,感兴趣的小伙伴可以试下。