例子
以下定义了String的扩展函数isContainA,用于判断字符串是否包含字母a;
//扩展函数
fun String.isContainA(): Boolean {
return this.contains("a")
}
//扩展属性
val String.isContainB: Boolean
get() {
return this.contains("b")
}
反编译
//扩展函数反编译
public static final boolean isContainA(@NotNull String value) {
Intrinsics.checkNotNullParameter(value, "value");
return StringsKt.contains$default((CharSequence)value, (CharSequence)"a", false, 2, (Object)null);
}
//扩展属性反编译
public static final boolean isContainB(@NotNull String $this$isContainB) {
Intrinsics.checkNotNullParameter($this$isContainB, "$this$isContainB");//1
return StringsKt.contains$default((CharSequence)$this$isContainB, (CharSequence)"b", false, 2, (Object)null);//2
}
发现扩展函数、属性并没有对String类进行修改,只是定义了一个静态函数,函数名就是我们扩展的函数或属性,参数类型为是String。
- 注释1:判断value是否为空,为空则抛空指针异常,对应扩展函数的接收者为String,为不是String?;
- 注释2:在StringsKt文件中,增加了定义的扩展函数;
String.isContainA()和String?.isContainA()有区别吗?
fun String.isContainA(): Boolean {
return this.contains("a")
}
fun String?.isContainA(): Boolean {
return this?.contains("a") ?: false
}
- 后者需要考虑空的情况;
反编译
public static final boolean isContainA(@NotNull String value) {
Intrinsics.checkNotNullParameter(value, "value");
return StringsKt.contains$default((CharSequence)value, (CharSequence)"a", false, 2, (Object)null);
}
public static final boolean isContainA(@Nullable String value) {
return value != null ? StringsKt.contains$default((CharSequence)value, (CharSequence)"a", false, 2, (Object)null) : false;
}
- 如果字符串为空,那么前者会抛出空指针异常,后者正常返回false,这种情况是发生在调用方为Java,因为Java缺少空校验。
Java访问扩展函数\属性;
public void test(){
AKt.isContainB("");//访问扩展属性,AKt是扩展函数所在的文件名
AKt.isContainA("");//访问扩展函数,AKt是扩展函数所在的文件名
}
使用场景
- 定义工具类或数据结构无法直接修改,都可以用扩展的方式来实现;
注意事项
- 扩展的访问权限,扩展定在文件中,则为顶级扩展,那么所有类都可以访问,如果定义在类中,访问就控制在类内部;
- 顶级扩展是无法访问接收者的private或者protected属性、方法的;
- 扩展函数无法被重写;
- 扩展属性无法保存状态或者数据,就是无法执行 field= value;
以上分析有不对的地方,请指出,互相学习,谢谢哦!
网友评论