Kotlin -1.5中的新功能预览

文章目录[x]
  1. 1:内联类
  2. 1.1:更改Java调用的JVM函数的名称
  3. 1.2:初始化块
  4. 1.3:内联值类
  5. 1.4:Value类
  6. 2:JVM Record支持
  7. 3:密封接口和密封类的改进
  8. 4:如何使用1.5版本新功能

Jetbrains在接下来的Kotlin 1.5中添加新的语言功能,并且可以在Kotlin 1.4.30中试用。主要添加的功能如下:

  • 内联类
  • JVM Record支持
  • 密封接口和密封类的改进

内联类

Kotlin 1.3就已经提供了内联类的Alpha版本,并在1.4.30中将其升级为Beta。从Kotlin 1.5起稳定了内联类的概念,使它成为更通用的功能的一部分。

有时,业务逻辑有必要围绕某种类型创建包装类。但是,由于额外的堆分配,它引入了运行时开销。而且,如果包装的类型是原始类型,那么性能损失将是很可怕的,因为原始类型通常在运行时进行了严重的优化,而它们的包装类并不会得到任何特殊的处理。

为了解决此类问题,Kotlin引入了一种称为内联类的特殊。内联类是基于值的类的子集。

inline class Color(val color:Int){

fun printColor(){
print(color)
}
}

fun doSomething(color:Color){
//do something
}

fun main(){
val color = Color(255)
//作为静态函数调用
color.printColor()

doSomething(color)
}

内联类的构造函数只能是一个原始类型或任何引用类型(如String)。在执行doSomething函数时编译器会用Color中的Int的值替换内联类实例:

int color = Color.constructor-impl(255);
 Color.printColor-impl(color);
 doSomething-YuIBNpY(color);//调用方法时没有分配额外的对象

更改Java调用的JVM函数的名称

Kotlin1.4.30开始,可以使用内联类作为参数来更改函数的JVM名称,以使其可从Java使用。可以使用注解@JvmName来修饰函数,它将在字节码中更改此函数的名称,并使其可以从Java调用并直接传递值:

// 定义内联函数
inline class Timeout(val millis: Long)

val Int.millis get() = Timeout(this.toLong())
val Int.seconds get() = Timeout(this * 1000L)

@JvmName("greetAfterTimeoutMillis")
fun greetAfterTimeout(timeout: Timeout)

// Kotlin调用
greetAfterTimeout(2.seconds)

// Java调用
greetAfterTimeoutMillis(2000);

初始化块

Kotlin 1.4.30中内联类的另一个改进是,现在可以在init块中定义初始化逻辑:

inline class Name(val s: String) {
 init {
 require(s.isNotEmpty())
 }
}

内联值类

Kotlin 1.5稳定了内联类的概念,并使它成为更通用的功能的一部分:value class

到目前为止,内联类已构成一种独立的语言功能,但现在它们已成为具有一个参数的值类的特定JVM优化。值类代表了一个更笼统的概念,将支持不同的优化:现在是内联类,而在项目Valhalla可用时,将来将是Valhalla基本类。

目前唯一是语法。由于内联类是优化的值类,因此必须以与以前不同的方式声明它:

@JvmInline
value class Color(val rgb: Int)

可以使用一个构造函数参数定义一个值类,并使用对其进行注释@JvmInline。我们应该从Kotlin 1.5开始就使用这种新语法。旧语法inline class将继续工作一段时间。在Kotlin 1.5中将有不推荐使用该定义方式的警告。

Value类

一个value类表示具有数据不可变的实体。目前,一个value类只能包含一个属性来支持旧内联类的用例。

在将来的Kotlin版本完全支持此功能,将可以定义具有许多属性的值类别。所有值都应为只读val

value class Point(val x: Int, val y: Int)

值类完全由存储的数据定义,并且不允许对其进行===检查。==检查会自动比较基础数据。

JVM Record支持

JDK15中引入了record,JVM生态系统中的另一个即将到来的改进是Java record。它们类似于Kotlin data类,并且主要是简单的数据持有者。

Java record不遵循JavaBeans约定,它们具有x()和y()方法,而不是熟悉的getX()和getY()。

与Java的互操作性一直是Kotlin的并且仍然是优先考虑的事项。因此,Kotlin代码兼容了新的Java record,并将它们视为具有Kotlin属性的类。这类似于遵循JavaBeans约定的常规Java类的工作方式:

// Java
record Point(int x, int y) { }
// Kotlin
fun foo(point: Point) {
 point.x // seen as property
 point.x() // also works
}

出于互操作性的原因,还可以对data类进行注解:@JvmRecord以生成新的JVM record方法:

@JvmRecord
data class Point(val x:Int,val y:Int)

@JvmRecord注解使编译器生成x()y()方法,而不是标准getX()getY()方法。

密封接口和密封类的改进

使类密封时,它将层次结构限制为已定义的子类,从而可以在when分支中进行详尽的检查。在Kotlin 1.4中,密封的类层次结构具有两个约束。首先,顶级类不能是密封的接口,它应该是一个类。其次,所有子类应位于同一文件中。

Kotlin 1.5消除了两个约束:现在可以使接口密封。子类(包括密封类和密封接口)应与父类位于同一编译单元和同一包中,但现在可以位于不同文件中。

sealed interface Expr
data class Const(val number: Double) : Expr
data class Sum(val e1: Expr, val e2: Expr) : Expr
object NotANumber : Expr

fun eval(expr: Expr): Double = when(expr) {
is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
}

如何使用1.5版本新功能

需要使用Kotlin 1.4.30来指定语言版本1.5以启用新功能:

compileKotlin {
 kotlinOptions {
 languageVersion = "1.5"
 apiVersion = "1.5"
 }
}
点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像

Title - Artist
0:00