Kotlin 1.5 宣布了一个重磅特性 value class,这是一个非常实用的特性,提高代码的可读性同时,还可以提高性能,因为编译器会对它进行更深层次的优化,减少对象的创建。
内联类的 inline 修饰符已弃用,该用value关键修饰,然后在类上添加@jvmInline
- 内联类是对某一个类型的包装
- 内联类是类似于Java装箱类型的一种类型
- 编译器会尽可能使用被包装的类型进行优化
1
| value class Password(private val s:String)
|
内联类必须含有唯一的一个属性在主构造函数,在运行时,将使用这个唯一属性来表示内联类的实例。
1 2 3
|
val securePassword =Password("Don`t try this in production)
|
这就是内联类的主要特性,它灵感来源inline这个名称;类的数据被内敛到该类是使用的地方(类似于内联函数中的代码被内联到该函数调用的地方)。
成员
内联类支持普通类的一些功能,特别是,内联类可以声明属性与函数以及init代码块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @JvmInline value class Name(private val s: String) { init { require(s.isNotEmpty()) }
val length: Int get() = s.length
fun greet() { println("Hello, $s") } }
fun main() { val name = Name("Kotlin") name.greet() println(name.length) println(name) }
|
main使用方法在编译成对应的Java代码:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public static final void main() { String name = Name.constructor-impl("Kotlin"); Name.greet-impl(name); int var1 = Name.getLength-impl(name); boolean var2 = false; System.out.println(var1); Name var3 = Name.box-impl(name); var2 = false; System.out.println(var3); }
|
模拟枚举类
在移动端开发的过程中出于对内存考虑,大家都尽量避免使用枚举类。所以在java中经常使用@StringDef和@IntDef,如果不清楚可自行查阅使用。但是在kotlin中虽然能使用,但是在IDE失去的了提示效果,就无法限定输入类型。具体如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER) @Retention(AnnotationRetention.SOURCE) @StringDef(SOUTH, NORTH) annotation class FilterType { companion object { const val NORTH = "NORTH" const val SOUTH = "SOUTH" } }
fun setFileType(@FilterType type: String) { println("type====$type") }
fun main() { setFileType("MMMM") }
|
如果遇到这个问题,可以考虑用内联类代替,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| inline class Color(val value: UInt) { companion object { val Red = Color(0xFFFF0000u) val Green = Color(0xFF00FF00u) val Blue = Color(0xFF0000FFu) }
fun values() = arrayOf(Red, Green, Blue)
val name: String get() = when (this) { Red -> "Red" Green -> "Green" Blue -> "Blue" else -> throw IllegalArgumentException() } } fun setColor(color: Color){ println(color.name) } fun main() { setColor(Color.BLUE) }
|
在setColor中限定了类型为color,直接使用Color伴生对象现成的定义