问题的历史:
在Kotlin中,访问属性是通过getter和setter方法进行的。为了提高性能,开发者为访问器添加了inline修饰符,使JVM能够在编译时优化调用,通过将get/set的主体直接插入到调用代码中。
问题:
普通的访问器方法为每个属性创建,这会增加调用的开销(尤其是在频繁访问时)。有时开发者会将逻辑抽离到单独的get/set中,但又希望避免函数调用的开销。
解决方案:
如果getter或setter的实现很短且没有重逻辑,请使用inline修饰符。这可以降低开销,特别是在热点路径中。请注意——内联仅适用于顶级属性和伴生对象或对象对象中的属性,而不适用于普通类中的属性,原因在于JVM继承原则。
代码示例:
inline var Int.asHex: String get() = Integer.toHexString(this) set(value) {} inline val String.firstUpperCase: String get() = if (isEmpty()) this else this[0].uppercase() + substring(1)
关键特点:
可以在普通类属性中使用inline get/set吗?
不可以,getter和setter的内联只允许在顶级或对象(包括伴生对象)属性中使用,而不能在类内的属性中使用,以避免继承问题。
在inline访问器中是否可以访问backing field(支持字段)?
不可以,inline访问器没有backing field,尝试访问会导致编译错误。
内联访问器是否总会影响字节码?
内联仅提示编译器可以内嵌代码。JIT编译器在某些情况下可能会忽略此提示。此外,如果访问器包含重逻辑,最终效果可能会相反。
在项目中,将一个大型属性声明为inline,但在getter中处理了在循环中使用的重转换。结果是最终的字节码膨胀,JIT禁用内联,性能下降。
优点:
缺点:
为将数字转换为字符串声明了inline val。getter在UI代码中频繁调用。性能保持高效,字节码紧凑。
优点:
缺点: