为有牺牲多壮志,敢教日月换新天。

[Kotlin参考]一、总览-(8)1.1新增功能

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(let_us_code)
➤博主域名:https://www.zengqiang.org
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/12152307.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

热烈欢迎,请直接点击!!!

进入博主App Store主页,下载使用各个作品!!!

注:博主将坚持每月上线一个新app!!!

Kotlin 1.1的新功能

目录

的JavaScript

从Kotlin 1.1开始,JavaScript目标不再被视为实验性的。支持所有语言功能,并且有许多新工具可与前端开发环境集成。请参阅下面的更详细的更改列表。

协程(实验性)

在科特林1.1的主要新功能是协同程序,使支持的asyncawaityield和类似的编程模式。Kotlin设计的关键特征是协程执行的实现是库的一部分,而不是语言的一部分,因此您不必受限于任何特定的编程范例或并发库。

协程实际上是一种轻量级的线程,可以将其挂起并在以后恢复。协程可以通过挂起函数来支持:调用该函数可以潜在地挂起协程,而要启动新的协程,我们通常使用匿名的挂起函数(即,挂起lambda)。

让我们看一下asyncawait,它是在外部库kotlinx.coroutines中实现的

 
 
 
 
 
//在后台线程池中运行代码
有趣的 asyncOverlay()=  异步CommonPool){
    //启动两个异步操作
    val  original  =  asyncLoadImage“ original”
    val  overlay  =  asyncLoadImage“ overlay”
    //然后将叠加层应用于两个结果
    applyOverlay的await(),覆盖的await())
}
//在UI上下文中启动新的协程
启动UI){
    //等待异步叠加完成
    val  image  =  asyncOverlay()。等待()
    //然后在用户界面中显示
    showImageimage
}
 
 
 

在这里,async { ... }启动一个协程,并且当我们使用时await(),协程的执行会在执行正在等待的操作的同时暂停执行,并在等待操作完成后继续执行(可能在其他线程上)。

标准库使用协程来支持带有函数的延迟生成的序列在这样的序列中,返回序列元素的代码块在检索每个元素之后将被挂起,并在请求下一个元素时恢复。这是一个例子:yieldyieldAll

 
 
 
 
 
 
 
val  seq  =  buildSequence {
    i  in  1 .. 5){
        //产生i的平方
        屈服i  *  i
    }
    //产生一个范围
    yieldAll26 .. 28
}
//打印序列
的printlnSEQtoList())
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

运行上面的代码以查看结果。随时对其进行编辑,然后再次运行!

有关更多信息,请参阅协程文档教程

请注意,协程目前被视为实验性功能,这意味着Kotlin团队在最终的1.1版本之后不再致力于支持该功能的向后兼容性。

其他语言功能

类型别名

类型别名使您可以为现有类型定义备用名称。这对于诸如集合之类的通用类型以及函数类型最有用。这是一个例子:

 
 
 
 
 
 
 
typealias  OscarWinners  =  地图< StringString >
有趣的 countLaLaLandoscarWinnersOscarWinners=
        oscarWinners { 价值包含“ La La Land”)}
//请注意,类型名称(初始名称和类型别名)可以互换:
有趣的 checkLaLaLandIsTheBestMovieoscarWinnersMap < StringString >=
        oscarWinners [ “最佳图片” ] ==  “ La La Land”
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

有关更多详细信息,请参见文档KEEP

绑定可调用参考

现在,您可以使用::运算符获取指向特定对象实例的方法或属性的成员引用以前只能用lambda表示。这是一个例子:

 
 
 
 
 
 
 
val  numberRegex  =  “ \\ d +”toRegex()
val  number  =  listOf“ abc”“ 123”“ 456”)。过滤器numberRegex :: 匹配项
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

阅读文档KEEP以获取更多详细信息。

密封和数据类

Kotlin 1.1消除了Kotlin 1.0中对密封和数据类的某些限制。现在,您可以在同一文件中的顶级上定义顶级密封类的子类,而不仅仅是密封类的嵌套类。数据类现在可以扩展其他类。这可以用来清晰地定义表达式类的层次结构:

 
 
 
 
 
 
 
密封  Expr
数据  Constval  numberDouble):Expr()
数据  Sumval  e1Exprval  e2Expr):Expr()
对象 NotANumberExpr()
fun  evalexprExpr):Double  =  whenexpr){
     Const-  >  expr
     萨姆 - >  的evalexpr中E1+  的evalexpr中E2
    NotANumber-  >  DoubleN
}
val  e  =  evalSumConst1.0),Const2.0)))
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

阅读文档或 密封类和 数据类 KEEP以获取更多详细信息。

在lambdas中进行销毁

现在,您可以使用解构声明语法来解压缩传递给lambda的参数。这是一个例子:

 
 
 
 
 
 
 
val  map  =  mapOf1  表示 “ 1”2  表示 “ 2”
//之前
的println地图mapValues { 条目 - >
  valkeyvalue=  条目
  “ $ key-> $ value!”
})
//现在
的println地图mapValues {(- >  “$键- > $值!” })
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

阅读文档KEEP以获取更多详细信息。

下划线表示未使用的参数

对于具有多个参数的lambda,您可以使用_字符替换不使用的参数名称:

 
 
 
 
 
 
 
地图forEach { _ ->  println“ $ value!”)}
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

这也适用于销毁声明

 
 
 
 
 
 
 
val_status=  getResult()
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

阅读KEEP了解更多详细信息。

数字文字下划线

与Java 8一样,Kotlin现在允许在数字文字中使用下划线来分隔数字组:

 
 
 
 
 
 
 
VAL  oneMillion  =  1_000_000
val  hexBytes  =  0xFF_EC_DE_5E
val  字节 =  0b11010010_01101001_10010100_10010010
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

阅读KEEP了解更多详细信息。

属性的较短语法

对于将getter定义为表达式主体的属性,现在可以省略属性类型:

 
 
 
 
 
 
 
    数据  VAL  字符串VAL  年龄诠释){
    val  isAdult  get()=  age  > =  20  //属性类型推断为“布尔”
}
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

内联属性访问器

现在,inline如果属性没有后备字段,则可以使用修饰符标记属性访问器。此类访问器的编译方式与内联函数相同

 
 
 
 
 
 
 
public  val  < T >  列表< T >lastIndexInt
    内联 get()=  this大小 -  1
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

您也可以将整个属性标记为inline-,然后将修饰符应用于两个访问器。

阅读文档KEEP以获取更多详细信息。

本地委托属性

现在,您可以将委托属性语法与局部变量一起使用。一种可能的用途是定义一个惰性计算的局部变量:

 
 
 
 
 
 
 
val  answer  by  lazy {
    println“正在计算答案...”
    42
}
ifneedAnswer()){                      //返回随机值
    println“答案是$ answer。”//答案是在此时计算的
}
其他 {
    println“有时没有答案就是答案...”
}
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

阅读KEEP了解更多详细信息。

拦截委派的属性绑定

对于委托的属性,现在可以使用provideDelegate运算符截取委托到属性的绑定 例如,如果我们想在绑定之前检查属性名称,我们可以这样写:

 
 
 
 
 
 
 ResourceLoader < T >idResourceID < T >){
    操作者 的乐趣 provideDelegatethisRefMyUIKProperty <*> ):ReadOnlyProperty < MyUIŤ > {
        checkPropertythisRef道具
        ... //属性创建
    }
    私人 乐趣 checkPropertythisRefMyUI名称String){...}
}
fun  < T >  bindResourceidResourceID < T >):ResourceLoader < T > {...}
 MyUI {
    VAL  图像 通过 bindResource的ResourceIDimage_id
    VAL  文本  bindResource资源IDtext_id
}
 
 
 

provideDelegate在创建MyUI实例期间,将为每个属性调用方法,并且可以立即执行必要的验证。

阅读文档以获取更多详细信息。

通用枚举值访问

现在可以以通用方式枚举枚举类的值。

 
 
 
 
 
 
 
枚举  RGB { 绿 }
直列 乐趣 < 物化 Ť枚举< Ť >>  printAllValues(){
    打印enumValues < Ť >()。joinToString { 名称 })
}
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

DSL中隐式接收器的范围控制

@DslMarker注释允许限制在DSL背景下使用的接收器从外部范围。考虑规范的HTML构建器示例

 
 
 
 
 
 {
    tr {
        td { +  “文字” }
    }
}
 
 
 

在Kotlin 1.0中,传递给lambda的代码可以td访问三个隐式接收器:一个传递给table,to tr 和to td这使您可以调用在上下文中没有意义的方法,例如在tr内部调用td,从而将<tr>标记放入<td>

在Kotlin 1.1中,您可以对此进行限制,以便td 在传递给的lambda内只有在隐式接收器上定义的方法才可用td为此,您可以定义带有@DslMarker元注释的注释并将其应用于标签类的基类。

阅读文档KEEP以获取更多详细信息。

rem 算子

mod现在不推荐使用运算符,rem而是使用它。看到这个问题的动机。

标准库

字符串到数字的转换

String类上有很多新扩展,可以将其转换为数字,而不会在无效数字上抛出异常: String.toIntOrNull(): Int?String.toDoubleOrNull(): Double?等等。

 
 
 
 
 
val  port  =  系统getenv“ PORT”toIntOrNull()80
 
 
 

也整数转换功能,如Int.toString()String.toInt()String.toIntOrNull(),各得到了与过载radix参数,该参数允许指定转换的(2到36)的基极。

在各个()

onEach是用于集合和序列的小型但有用的扩展函数,它允许在一系列操作中对集合/序列的每个元素执行某些操作,可能会有副作用。在可迭代对象上,它的行为类似于,forEach但还会进一步返回可迭代实例。然后在序列上返回一个包装序列,该序列在元素被迭代时会延迟应用给定的动作。

 
 
 
 
 
inputDir步行()
过滤 { isFile  &&  名字结尾于“ .txt”)}
onEach { println“将$ it移至$ outputDir”)}
的forEach { moveFile文件outputDirtoRelativeStringinputDir)))}
 
 
 

Also(),takeIf()和takeUnless()

这是三个适用于任何接收器的通用扩展功能。

also就像apply:它接收接收者,对其执行一些操作,然后返回该接收者。区别在于,在apply接收器内部的块中可以将其用作this,而在接收器内部块中可以将其also用作it(并且如果需要,可以给它起另一个名字)。当您不想this从外部范围阴影时,这很方便

 
 
 
 
 
 
 
好玩的 复制()=  ()。 {
    内容 =  这个内容
}
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

takeIf就像filter单个值一样。它检查接收方是否满足谓词,并返回接收方(如果满足)或null不满足。与Elvis运算符和早期返回结合使用,可以编写以下结构:

 
 
 
 
 
VAL  outDirFile  =  文件outputDir路径)。takeIf { 存在()} 吗?返回 
//使用现有的outDirFile做一些事情
 
 
 
 
 
 
 
 
 
 
val  index  =  输入indexOf关键字)。takeIf { it  > =  0 } 吗?错误“未找到关键字”
//在找到输入关键词的情况下对关键词进行索引
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

takeUnless与相同takeIf,但它采用倒置谓词。如果不符合谓词,null返回接收者否则返回。因此,可以使用takeUnless以下示例重写以上示例之一

 
 
 
 
 
val  index  =  输入indexOf关键字)。takeUnless { it  <  0 } 吗?错误“未找到关键字”
 
 
 

当您有一个可调用的引用而不是lambda时,使用起来也很方便:

 
 
 
 
 
 
 
val  结果 =  字符串takeUnless字符串 :: isEmpty
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

groupingBy()

该API可用于按键对集合进行分组,并同时折叠每个组。例如,它可以用于计算以每个字母开头的单词数:

 
 
 
 
 
 
 
val  频率 =  单词通过 { it第一()}。eachCount()
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

Map.toMap()和Map.toMutableMap()

这些功能可用于轻松复制地图:

 
 
 
 
 
class  ImmutablePropertyBagmapMap < StringAny >){
    私有 val  mapCopy  =  maptoMap()
}
 
 
 

Map.minus(key)

运算符plus提供了一种将键值对添加到生成新图的只读图的方法,但是没有相反的简单方法:从图中删除键,您必须减少使用喜欢Map.filter()喜欢的直截了当的方式Map.filterKeys()现在,操作员minus填补了这一空白。有4种重载可用:用于删除单个键,键集合,键序列和键数组。

 
 
 
 
 
 
 
val  map  =  mapOf“ key”  to  42
val  emptyMap  =  地图 -  “键”
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

minOf()和maxOf()

这些函数可用于查找两个或三个给定值中的最小和最大值,其中值是原始数字或Comparable对象。Comparator如果您要比较本身不具有可比性的对象,则每个函数还有一个额外的实例需要重载

 
 
 
 
 
 
 
val  list1  =  listOf“ a”“ b”
val  list2  =  listOf“ x”“ y”“ z”
VAL  minSize属性 =  minOflist1的大小列表2大小
VAL  longestList  =  maxOflist1的list2中compareBy { 大小 })
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

类数组列表实例化函数

Array构造函数类似,现在有一些函数可以通过调用lambda 来创建ListMutableList实例并初始化每个元素:

 
 
 
 
 
 
 
val  squares  =  List10){ 索引 ->  索引 *  索引 }
val  mutable  =  MutableList10){ 0 }
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

Map.getValue()

该扩展名on Map返回与给定键相对应的现有值,或引发异常,并提及未找到哪个键。如果使用生成地图withDefault,则此函数将返回默认值,而不是引发异常。

 
 
 
 
 
 
 
val  map  =  mapOf“ key”  to  42
//返回不可为空的Int值42
val  Int  =  mapgetValue“ key”
val  mapWithDefault  =  mapwithDefault { k-  >  k长度 }
//返回4
val  value2  =  mapWithDefaultgetValue“ key2”
// map.getValue(“ anotherKey”)// <-这将引发NoSuchElementException
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

抽象收藏

在实现Kotlin集合类时,可以将这些抽象类用作基类。为了实现只读集合有AbstractCollectionAbstractListAbstractSetAbstractMap,以及可变集合有AbstractMutableCollectionAbstractMutableListAbstractMutableSetAbstractMutableMap在JVM上,这些抽象可变集合从JDK的抽象集合继承了大多数功能。

数组操作功能

现在,标准库为数组的逐个元素操作提供了一组函数:比较(contentEqualscontentDeepEquals),哈希码计算(contentHashCodecontentDeepHashCode)以及转换为字符串(contentToStringcontentDeepToString)。JVM(在其中用作相应功能的别名java.util.Arrays)和JS(在Kotlin标准库中提供实现)都支持它们。

 
 
 
 
 
 
 
val  array  =  arrayOf“ a”“ b”“ c”
的println阵列的toString())   // JVM实现:类型和散列乱码
的println阵列contentToString())   //很好地格式化为列表
 
 
 
目标平台:JVM 。运行在科特林v 61年3月1日

JVM后端

Java 8字节码支持

Kotlin现在可以选择生成Java 8字节码(-jvm-target 1.8命令行选项或Ant / Maven / Gradle中的相应选项)。目前,这不会改变字节码的语义(特别是,接口和lambda中的默认方法的生成与Kotlin 1.0中的完全相同),但是我们计划稍后再使用它。

Java 8标准库支持

现在,标准库有单独的版本,支持Java 7和8中添加的新JDK API。如果需要访问新API,请使用kotlin-stdlib-jre7kotlin-stdlib-jre8Maven构件,而不是standard kotlin-stdlib这些工件是kotlin-stdlib它们之上的微小扩展,它们作为传递依赖项将其带入您的项目。

字节码中的参数名称

Kotlin现在支持在字节码中存储参数名称。可以使用-java-parameters命令行选项启用

恒定内联

现在,编译器将const val属性值内联到使用它们的位置。

可变的关闭变量

用于捕获lambda中的可变闭包变量的box类不再具有volatile字段。此更改可以提高性能,但在某些罕见的使用情况下可能导致新的竞争状况。如果您受此影响,则需要提供自己的同步来访问变量。

javax.script支持

Kotlin现在与javax.script API(JSR-223)集成该API允许在运行时评估代码段:

 
 
 
 
 
val  engine  =  ScriptEngineManager()。getEngineByExtension“ kts”
引擎评估“ val x = 3”
的println发动机EVAL“X + 2” ))   //打印出5
 
 
 

有关 使用API​​的大型示例项目,请参见此处

全反射

为了准备对Java 9的支持kotlin-reflect.jar库中的扩展功能和属性已移至程序包kotlin.reflect.full旧软件包(kotlin.reflect)中的名称已弃用,并将在Kotlin 1.2中删除。请注意,核心反射接口(例如KClass)是Kotlin标准库的一部分,不是kotlin-reflect,并且不受此举动的影响。

JavaScript后端

统一标准库

现在,可以将Kotlin标准库的很大一部分用于编译为JavaScript的代码。具体地,键类,如集合(ArrayListHashMap等),异常(IllegalArgumentException等)和其他一些(StringBuilderComparator)现在将在限定的kotlin包。在JVM上,名称是相应JDK类的类型别名,在JS上,这些类在Kotlin标准库中实现。

更好的代码生成

现在,JavaScript后端可以生成更多可静态检查的代码,这比缩小器,优化器,棉绒等JS代码处理工具更友好。

external修改

如果您需要以类型安全的方式从Kotlin访问用JavaScript实现的类,则可以使用external修饰符编写Kotlin声明(在Kotlin 1.0中,使用了@native注释。)与JVM目标不同,JS允许使用带有类和属性的外部修饰符。例如,以下是声明DOM Node类的方法:

 
 
 
 
 
外部  Node {
    val  firstChild节点
    fun  appendChildchildNode):节点
    fun  removeChildchildNode):节点
    //等
}
 
 
 

改进的进口处理

现在,您可以描述应从JavaScript模块更精确地导入的声明。如果@JsModule("<module-name>")在外部声明上添加注释,则在编译期间会将其正确导入到模块系统(CommonJS或AMD)。例如,对于CommonJS,声明将通过require(...)函数导入此外,如果要将声明作为模块或全局JavaScript对象导入,则可以使用@JsNonModule注释。

例如,以下是将JQuery导入Kotlin模块的方法:

 
 
 
 
 
外部 接口 JQuery {
    有趣的 切换durationInt  =  defineExternally):jQuery
    有趣的 点击handler:(Event->  Unit):JQuery
}
@JsModule“ jquery”
@JsNonModule
@JsName“ $”
外部 有趣的 jQuery选择器字符串):JQuery
 
 
 

在这种情况下,JQuery将作为名为的模块导入jquery另外,它可以用作$对象,具体取决于Kotlin编译器配置使用的模块系统。

您可以像下面这样在应用程序中使用这些声明:

 
 
 
 
 
fun  mainargsArray < String >){
    jQuery“ .toggle-button”)。点击 {
        jQuery“ .toggle-panel”)。拨动300
    }
}
 
 
posted @ 2020-01-05 14:09  为敢技术  阅读(275)  评论(0编辑  收藏  举报