⑴ android启动执行多个runtime
深入理解Android Runtime
申国骏
2022-08-08 12:31·字数:2599·阅读:2340
image.png
上图是Android整体的架构,Android Runtime之于Android而言相当于心脏之于人体,是Android程序加载和运行的环境。这篇文章主要针对Android Runtime部分进行展开,探讨Android Runtime的发展以及目前现状,并介绍应用Profile-Guided Optimization(PGO)技术对应用启动速度进行优化的可行性。转载请注明来源“申国骏”
App运行时演进
JVM
Android原生代码使用Java或者Kotlin编写,这些代码会通过javac或者kotlinc编译成.class文件,在Android之前,这些.class文件会被输入到JVM中执行。JVM可以简单分为三个子系统,分别是Class Loader、Runtime Data Area以及Execution Engine。其中Class Loader主要负责加载类、校验字节码、符号引用链接及对静态变量和静态方法分配内存并初始化。Runtime Data负责存储数据,分为方法区、堆区、栈区、程序计数器以及本地方法栈。Execution Engine负责二进制代码的执行以及垃圾回收。
image.png
Execution Engine中,会采用Interpreter或者JIT执行。其中Interpreter表示在运行的过程中对二进制代码进行解释,每次执行相同的二进制代码都进行解释比较浪费资源,因此对于热区的二进制代码会进行JIT即时编译,对二进制代码编译成机器码,这样相同的二进制代码执行时,就不用再次进行解释。
image.png
DVM(Android 2.1/2.2)
JVM是stack-based的运行环境,在移动设备中对性能和存储空间要求较高,因此Android使用了register-based的Dalvik VM。从JVM转换到DVM我们需要将.class文件转换为.dex文件,从.class转换到.dex的过程需要经过 desugar -> proguard -> dex compiler三个过程,这三个过程后来逐步变成 proguard -> D8(Desugar) 直到演变到今天只需要一步R8(D8(Desugar))。
image.png
我们主要关注Android中Runtime Engine与JVM的区别。在Android早期的版本里面,只存在Interpreter解释器,到了Android2.2版本将JIT引入,这个版本Dalvik与JVM的Runtime Engine区别不大。
image.png
ART-AOT(Android 4.4/5.0)
为了加快应用的启动速度和体验,到了Android4.4,Google提供了一个新的运行时环境ART(Android Runtime),到了Android5.0,ART替换Dalvik成为唯一的运行时环境。
image.png
ART运行时环境中,采用了AOT(Ahead-of-time)编译方式,即在应用安装的时候就将.dex提前编译成机器码,经过AOT编译之后.dex文件会生成.oat文件。这样在应用启动执行的时候,因为不需要进行解释编译,大大加快了启动速度。
image.png
然而AOT带来了以下两个问题:
应用安装时间大幅增加,由于在安装的过程中同时需要编译成机器码,应用安装时间会比较长,特别在系统升级的时候,需要对所有应用进行重新编译,出现了经典的升级等待噩梦。
image.png
应用占用过多的存储空间,由于所有应用都被编译成.oat机器码,应用所占的存储空间大大增加,使得本来并不充裕的存储空间变得雪上加霜。
进一步思考对应用全量进行编译可能是没有必要的,因为用户可能只会用到一个应用的部分常用功能,并且全量编译之后更大的机器码加载会占用IO资源。
ART-PGO(Android 7.0)
从Android7.0开始,Google重新引入了JIT的编译方式,不再对应用进行全量编译,结合AOT、JIT、Interpreter三者的优势提出了PGO(Profile-guided optimization)的编译方式。
在应用执行的过程中,先使用Interpreter直接解释,当某些二进制代码被调用次数较多时,会生成一个Profile文件记录这些方法存储起来,当二进制代码被频繁调用时,则直接进行JIT即时编译并缓存起来。
当应用处于空闲(屏幕关闭且充电)的状态时,编译守护进程会根据Profile文件进行AOT编译。
当应用重新打开时,进行过JIT和AOT编译的代码可以直接执行。
这样就可以在应用安装速度以及应用打开速度之间取得平衡。
image.png
image.png
JIT 工作流程:
image.png
ART-Cloud Profile(Android 9.0)
不过这里还是有一个问题,就是当用户第一次安装应用的时候并没有进行任何的AOT优化,通常会经过用户多次的使用才能使得启动速度得到优化。
image.png
考虑到一个应用通常会有一些用户经常使用执行的代码(例如启动部分以及用户常用功能)并且大多数时候会有先行版本用于收集Profile数据,因此Google考虑将用户生成的Profile文件上传到Google Play中,并在应用安装时同时带上这个Profile文件,在安装的过程中,会根据这个Profile对应用进行部分的AOT编译。这样当用户安装完第一次打开的时候,就能达到较快的启动速度。
image.png
image.png
Profile in cloude 需要系统应用市场支持,在国内市场使用Google Play的占比非常低,因此cloud profile的优化在国内几乎是没有作用的,不过Profile的机制提供了一个可以做启动优化的思路。早在2019年,支付宝就在秒开技术的回应的里面提到过profile-based compile的技术,参考:如何看待今日头条自媒体发布谣言称“支付宝几乎秒开是因为采用华为方舟编译器”?,这也是我们一直研究Profile技术的原因。困扰着我们的一直有两个问题,第一个问题是如何生成Profile文件,第二个问题是怎么使用生成的Profile文件。对于第一个问题的解决相对还是有思路的,因为app运行就会生成profile文件,因此我们手动运行几次app就能在文件系统中收集到这个文件,不过如何以一种较为自动化的手段收集仍然是个问题。第二个问题我们知道Profile文件最终生成的位置,因此我们可以把生成的文件放到相应的系统目录,不过大多数手机和应用都没有权限直接放置这个文件。因此Profile优化技术一直都没有落地,直到Baseline Proflie让我们看到了希望。
Baseline Profile
Baseline Profile是一套生成和使用Profile文件的工具,在2022年一月份开始进入视野,随后在Google I/O 2022随着Jetpack新变化得到广泛关注。其背景是Google Map加快了发版速度,Cloud Profle还没完全收集好就上新版,导致Cloud Proflie失效。还有一个背景是Jetpack Compose 不是系统代码,因此没有完全编译成机器码,而且Jetpack Compose库比较大,因此在Profile生成之前使用了Jetpack Compose的应用启动会产生性能问题。最后Google为了解决这些问题,创造了收集Profile的BaselineProfileRule Macrobenchmark以及使用Profile的ProfileInstaller。
使用Baseline Profile的机制可以在Android7及以上的手机上得到应用的启动加速,因为从上述知道Android7就已经开始有PGO(Profile-guided optimization)的编译方式。生成的Profile文件会打包到apk里面,并且会结合Google Play的Cloud Profile来引导AOT编译。虽然在国内基本上用不了Cloud Profile,不过Baseline Profile是可以独立于Google Play单独使用的。
image.png
在使用了Baseline Proflie之后,有道词典的启动速度从线上统计上看,冷启动时间有15%的提升。
这篇文章主要介绍了Android Runtime的演进以及对于应用启动的影响,下一篇文章我会详细介绍关于Profile&dex文件优化、Baseline Profile工具库原理,以及在实际操作上如何使用的问题,敬请大家期待一下!
⑵ Swift VS Kotlin
Swift和Kotlin作为更加"现代化"的语言,毫无疑问提升了开发原生app的效率,二者旨在与Objective-C和Java互操作,方便"旧"应用的开发进行更新,如果你要从零开始编写一个全新的应用,不要犹豫,选择使用它们,尽情享受它们带来的乐趣。这两个语言有着许多相似之处,让我们来"欣赏"一下吧:
Kotlin有一个称为数据类的东西,该类在编译时将获得诸如hashCode(),toString()和()等方法。可以这样定义:
Swift没有数据类或任何等效类。
Swift具有元组功能,并且可以为元组设定类型别名;
Kotlin具有Pair和Triple工具类,用物散于呈现2元和3元组对象,并且可以通过data class模拟自定义元组。
Swift Struct和Class之间的区别在于,结构体是值类型,而类是引用类型。可将元组视为隐式定义的Struct:
Kotlin没有Struct类型。但是,我们可以通过函数创建一个新引用:
我们可以使用Kotlin数据类和Swift结构体来保存数据。即使一个是引用类型,另一个是值类型。
Swift和Kotlin都有枚举。但是声明和匹配方式有很大的区别:
Kotlint通过密封类可以实现枚举。Kotlin的Sealed Class和Swift的Enum之间的唯一区别是,密封类是引用类型,而Swift的Enum是值类型:
Swift还具有隐式解包功能,它定义了一个可选内容,但告罩宽氏诉编译器可以展开该内容,因为后面它将会被值。Kotlin也可以通过lateinit关键字执行相同的操作。需要注意的是,作为开发人员,应尽可能避免使用隐式解包方式。
协议和接口有相同的功能,只是使用了不同的术语。它们定义了一个类在实现接口时必须遵循的一组函数/变量。Kotlin允许在接口的定义中使用泛型,而Swift则可以通过定义关联类型associatedtype来实现。
高阶函数本质上是接受闭包或函数作为参数并返回新值或另一个函数的函数。使用高阶函数,我们可以对值(例如数组)进行转换,过滤巧衡和迭代。
参考:
⑶ 如何学习Kotlin编程语言
为什么说 Kotlin 是优秀的
本文不会像一碰颂般介绍语言的文章那样,一开头就罗列出语言那些酷炫的特性,我们稍后再来探讨这些内容。
首先我将介绍一些其它的信息,因为2013 年一项研究显示,当开发者评估一种编程语言时生态系统要比语言特性更重要。这符合我个人的经验,下面就让我开始介绍吧:
Kotlin 被编译成 JVM 字节码或者 JavaScript 代码。Java 开发者将会是对它最感兴趣的人,不过对于使用垃圾收集运行时语言亩信的开发者而言它也具有一定的吸引力,比如 Scala、Go、Python、Ruby 和 JavaScript 等语言。
Kotlin 来自业界,而不是学术界。它解决了开发者现今面临的实际问题。例如它的类型系统可以帮助你避免空指针异常。
切换到 Kotlin 无需成本!它是开源的但这不是重点,重点是它提供了一个高质量的一键从 Java 转换到 Kotlin 的工具,并且十分关注 Java 二进制文件的兼容性。你可以将现有 Java 项目的一次性转换成 Kotlin 项目,而该项目仍将可以正常编译,即使这是一个包含上百万行代码的复杂程序。
显然你可以从上文得知,Kotlin 程序能够使用所有现存的 Java 框架和库,甚至那些依赖注解处理的高级框架。它们之间的交互是无缝的,不需要包装或者适配层。Kotlin 可以整合 Maven,Gradle 以及其它构建系统。
它十分平易近人,语法精炼直观,仅仅是阅读语言参考文档几个小时就能学会使用。Kotlin 看起来十分像 Scala 但是更加简洁并且兼顾了可读性。
它不遵循特定的编程哲学,例如极度的函数式编程或者面向对象编程风格。
它不会增加运行时的开销。Kotlin 的标准库十分小巧紧凑:专注于扩展 Java 标准库,编译阶段的大量内联操作意味像 map/filter/rece 等管道结构函数将被编译成类似于命令式语言的代码。
Anko 与 Kovenant 等框架的出现意味着在 Android 开发者中 Kotlin 开始变得流行起来。如果你正在从事 Android 相关的工作,相信你笑耐郑很快就会获得好的工作。你可以阅读这份 Square 公司开发者 JakeWharton 的报告,了解用 Kotlin 进行 Android 开发的体验。
Kotlin 允许你继续使用你的工作效率提升工具。IntelliJ 的 IDE 对 Kotlin 的支持十分完善:你可以对代码进行重构、搜索、导航以及使用自动完成,而且 IDE 充分支持调试、单元测试、性能分析等等功能。
除了 Android,我认为 Kotlin 还非常适用于企业中 Java 的应用场景。如果你的工作是整天埋头于大公司的代码库中,那么当 Kotlin 1.0 版本正式发布时你应该尽快去了解一下:
由知名公司为它提供强大的商业支持。 JetBrains 这家公司 有一个高度称职的大团队致力于该项目,有稳定的商业模式甚至在自己的部分旗舰产品中使用 Kotlin,这表明短期内 Kotlin 不会被放弃。
使用 Kotlin 风险较低:可以由一两个感兴趣的团队成员在项目中小范围的试验 Kotlin,这并不会扰乱你的项目,因为 Kotlin 的类对外提供的 Java API 看起来就与普通的 Java 代码一样。
因为 Kotlin 十分注重语法的可读性,代码审查不会成为问题,对 Kotlin 不熟悉的团队成员仍然能够完成该工作。
Kotlin 基于 Java 6,所以假如你难以在项目中升级使用新版本的 JVM,你可以使用 Kotlin。
今年早些时候我向 Swiss Re 这家瑞士再保险公司的团队(他们使用 Java 和 .NET)展示了 Kotlin。首先我定义了一个简单的 Java 类包含一些字段以及 toString、equals、hashCode 等方法,大概有 50 行代码。然后我将它转换成 Kotlin 代码(大部分是自动完成的),结果仅剩 1 行代码,接着我还演示了其它节省时间的特性。他们看过后对 Kotlin 充满了热情并且认为 Kotlin 是它们项目中 C# 语言的一个潜在竞争对手。
我认为 Kotlin 正中企业 Java 开发者的红心,所以尽管 Kotlin 是免费的,JetBrains 还是能够通过它增加商业版本 IDE 的销售来赚大钱。这将激励他们根据用户的意愿持续改进它。
与此相比,对于那些由不相关产品资助的语言开发者来说,当用户需求与之前的设计理念冲突时,他们很少会因此作出调整。
特性
Kotlin 作为一门新的编程语言能够脱颖而出,是因为它关注生态系统:JetBrains 懂得生产力的高低更多的取决于生态系统而不是便捷的语法。
尽快如此,Kotlin 还是有许多有用的特性能让你编码的过程变得愉快:
我们已经提过 null 安全(可选),它能够让编译器系统的标记潜在的空指针引用。与一些语言不同的是它不涉及 option 类,因此是零开销的,并且还有其它语言特性确保它不会造成不便。
精炼的语法:无处不在的类型推断、简单的函数只需要一行、简单的结构以及 JavaBeans 也只需要一行就能声明、真正的属性——可以在背后自动生成 getFoo/setFoo 方法用于与 Java 进行交互、函数可以独立存在于类之外。
异常均为非检查型。(译者注:感兴趣的可以阅读一下Java 理论与实践: 关于异常的争论)
使用 data class 关键字创建数据类会自动生成通用方法,例如 equals、hashCode、toString 以及 和 componentN(同时声明多个变量时会调用该方法)。这将帮助你在不使用构建器的情况下便捷的获得不变类(immutable classes)。
但如果你需要构造复杂的结构体,借助类型安全的构建器这个特性可以简洁的实现。如果你使用 Google Protocol Buffers 来存储结构化数据, 通过 KBuilders 这个库也能很轻易做到。
支持函数式编程以及零开销的 lambda 表达式,能够在 Java 的集合中做 Map、Filter、Folder 等处理。Kotlin 的类型系统能够自动识别可变或者不可变的集合。
扩展函数特性能够让你在不改动源码的情况下为类添加方法。乍眼一看以为是为了避免写出像 FooUtils 这种风格工具类的语法糖,不过随着使用的加深,你会认识到它不仅能帮你更加容易的通过自动完成使用方法,还能协助你集成现有的 Java API 以及借助其它 Kotlin 特性构建功能强大的扩展。
支持运算符重载,但是不会像 Scala 或者 Perl 那样出现难以理解的代码。运算符被映射成相应名字的方法,通过重写这些方法改变运算符的行为(包括函数调用),但是不能定义新的运算符。这使得程序能够兼顾功能与可读性。
Kotlin 没有宏或者其它的方式来重定义语言,但是通过这些精心设计的特性能够使第三方库自由的对它进行扩展,官方对集合类进行的扩展也只是小试牛刀而已,请看以下例子。
想使用 fibers、actors 和 Go 风格的 channels?一个名为 Quasar 的库已经为你实现了。
使用 Markdown 替代 HTML 来编写 API 文档,这样编写 JavaDocs 可比以前舒适多了。(译者注:JetBrains 提供了相应的文档生成器 Dokka)
更好用的泛型。如果你没有完全掌握泛型参数中 super 以及 extends 的含义,别担心,这不是你的错。Java 的泛型的确令人费解,Kotlin 解决了这个问题。
委托是一个大家都知道的设计模式,Kotlin 原生支持它。
== 运算符的行为符合预期(译者注:简单来说 a == b 相当于 a.equals(b);新增了 === 运算符,用来判断运算符两边是否指向同一个对象)
想快速便捷的进行异步编程吗?当然!
字符串插值“可以使用这样的写法在字符创中直接引用变量 {this.example}”
函数中的参数可以指定默认值、使用可变长度以及通过参数名传参。
还有许多的调整与优化。假如 Java 中有某些让你觉得困扰的问题,我相信 Kotlin 一定已经把它处理好了。
现在就来试用一下!
跟很多现代编程语言一样,Kotlin 可以通过网页浏览器来进行体验。不过跟其他语言不一样的是,Kotlin 的实验网站提供了一个成熟的 IDE,包括响应很快的自动完成,实时的后台编译,甚至还有在线的静态分析!
在线试用一下吧
好了,让我们继续接下来的内容
目前存在哪些问题?
生活中没有什么是完美的,包括 Kotlin。以下是我尝试这门语言时遇到的一些问题。
最大的问题是不够成熟,因为 Kotlin 目前还处于 Beta 阶段,这意味着:
每更新一个版本,语法、ABI 以及标准库就变一次。好消息是这些变化通常比较微小,可以借助 IntelliJ IDE 来自动升级你的代码,所以这个过程并不会太麻烦。
Java-to-Kotlin 的转换工具(J2K)还没有完成。它偶尔会大规模的破坏和默默地擦除 Java 8 中的 Lambdas(修改:2015 年 10 月:M13 版本的转换工具已经可以正确地处理 Java 8 的特性了)。由它转换而成的代码并不总是最好的写法,但是 JetBrains 为这个工具付出了大量努力,它已经是我用过的语言转换工具中最好的了。所以我并不太担心这个问题,这个转换器正在迅速的改进中,变得越来越成熟。
你会遇到编译器错误。尽管我的程序并不大,但还是会发生无法编译的情况,甚至错误的编译结果。诊断这些问题并不难,但终归还是影响了开发的体验。
你会遇到 IDE 内部错误。当这个错误发生时,IntelliJ IDE 会弹出一个悬浮窗口,附带向 JetBrains 报告的选项。大部分错误无需理会,不过依然会使人厌烦。
偶尔会出现无法加载提示文档的错误(修改:M14 版本发布后,这个问题已被修复)
目前 JetBrains 正致力于完善发布 1.0 版本而不是添加新的功能,期待这些问题能够得到修复。
第二个我遇到的比较大的问题是,有时与 Java 的交互会受到局限。
一个典型的 Bug 是 Java 的类型系统无法防止你改变 Map 中 Key 的类型。按理来说,这样操作应该导致编译器报错,例如使用类型错误的 Key 删除元素。有些 JDK 中的集合使用了泛型,它们某些重要方法的泛型参数是 Obejct,所以编译器不会提示。当在 IntelliJ IDE 中编写 Java 代码时会有静态分析的警告,但是目前 Kotlin 环境还没有这个功能。因为 Kotlin 使用的是 Java 的集合框架没有自己实现,所以这导致了一些类型安全方面的问题,我已经遇到好几次了。
(修改:1.0 Beta 版本中这个问题已经解决了,Java 中集合框架的类型安全缺陷在 Kotlin 已经不复存在。哟呵!)
另一个例子是,当调用或使用 Java 代码时 Kotlin 的 Null 安全特性无法发挥作用(可以借助注解弥补)。作为 Kotlin 的初学者,刚开始你可能会写许多调用 Java 库的代码,但是因为以上的问题它们并没有你想象中那么好用。这种情况的改善只能等待 Kotlin 使用人数的增长。JetBrains 一直在尝试使 Null 安全特性能体现在 Java 交互中,这种想法是好的,但有时考虑并太周全。(修改: 从 M13 版本开始,在 Java 代码中将自动以 @NotNull @Nullable 等注解实现 Kotlin 的 Null 安全特性)
虽然有以上的问题存在,但同时也使得我们能更流畅的使用 Java API,我觉得这种权衡是值得的,只是在开发中要注意。
其它需要考虑的问题:
Kotlin 的社区还比较小。虽然目前没有多少 Kotlin 的库可以使用,但是凭借优秀的 Java 交互能力,Kotlin 可以使用现有成熟的 Java 库。
如果你喜欢看书来学习,那么你需要等到今年晚些时候才能看到 Kotlin 开发者写的书(译者注:Kotlin in Action)
纯粹的函数编程风格开发者可能会觉得类型系统中缺乏一些 Scala 或 Haskell 拥有的高级功能。如果你对类型系统一些功能比较看重,那么 Kotlin 可能不适合你。
Kotlin 还能编译成 Javascript 代码,但是比较少用,所以可能会遇到更多的问题,这是我从论坛中得到的印象。(修改: 目前 Kotlin 的开发重心在于完成 1.0 版本并使其稳定运行在 JVM 中,Javascript 方面的问题将会在 1.0 发布后着手解决)
没有标准的编程风格指南,目前 Kotlin 提供了多种语法可供选择。不同人写出来的 Kotlin 代码很可能完全不一样。这与 Go 严格的风格形成了鲜明的对比。(修改: Kotlin 1.0 版本开始,一些灵活的语法已经被移除了,例如现在重载运算符以及定义中缀函数时必须分别使用 operator 和 infix 关键字进行标记)
Kotlin 的编译速度稍稍慢于 Java,以及 IntelliJ IDE 的智能提示反应有点缓慢,不算严重而且比 Scala 快多了。(修改:Kotlin 1.0 开始编译速度有了明显提升)
Kotlin 有一个 Eclipse 插件,但是很明显没有 IntelliJ 的好用。
Kotlin 在某些方面比 Java 要严格。它不会自动将 Int 转换为 Long 类型,需要开发者显示的转换。这是因为 Kotlin 关注正确性和试图解决《Java Puzzlers》一书中提出的问题。JetBrains 声称他们已经搞定一半了。
Kotlin 基于 Java 6,因此会受到它的局限。Kotlin 与 C# 在很多领域都很相似甚至比 C# 做得更好,但是它缺少一些功能,例如 Java 平台尚未支持的某些数据类型。
为什么应该开始考虑使用 JVM
最近一段时间我遇到了很多使用动态脚本语言(JavaScript 或者 Go —— 译者注:Go 应该是静态编译型语言)的创业公司。
我在 Bitcoin Space 工作的时候,使用动态语言是非常痛苦的事情。在这些语言里没有安全性的类型,这已经导致了巨大的货币损失。Go 比较少出错,但是在基础层面上给人的体验依然很差,比如说缺少好的调试工具,快速 GC 机制,稳健的管理器以及可靠的分析工具。
过去 15 年或者更长时间里,Java 变得越来越健壮,越来越冗长,甚至有过度设计的迹象,这些变化很大程度上源于它的声誉。企业级 Java 类的名字 就是例证。在很长一段时间里我没有考虑 JVM,我确信这种环境并不适合我。
最终我因为 Android 被迫回到 Java,发现 Java 的开发环境已经改变了。虽然 XML 仍然不合时宜的频繁出现在各种场合,但是一些基础功能十分完善,令人印象深刻。 IntelliJ 是比 Eclipse 更快并且更智能的 IDE。Maven 一出现就得到了迅速的发展,拥有许多原本我想要其它构建 / 依赖系统增加的功能。较新的 Web 框架像 Ninja 和 Play 从类似 Ruby on Rails 的框架中学到了轻量简洁。有大量的库可供使用。硬件性能变得更高以及 JVM 变得更有效率,等等转变。
没有真正改变的是语言本身,Java 代码写起来依然是令人不快的冗长。
现在有了 Kotlin,完全无需承受离开 Java 现有的生态系统的疼苦。你可以编写更富有表现力的代码,但是却比脚本语言更简洁,同时拥有更好的性能和更少的错误。
如果你喜欢 JavaScript,可以尝试 Kotlin 的 JS 后端,或者在 Nashorn JS 引擎里运行你现有的代码。
最后,如果你喜欢 Go 语言是因为它可以编译独立运行的程序,那么试试 javapackager 工具。Kotlin 在本地为每个平台创建了捆绑包,这意味着在 linux 上不需要 JRE 的依赖就可以独立自主的获取 DEBs(linux 的安装包)或者压缩包。当然,它拆包之后不是单个文件而是单个目录,从部署的角度来看并不难操作。
简而言之:如果你之前因为看 Java 不顺眼而忽略了 JVM 的生态系统,那么你应该借着 Kotlin 这门新语言进入这个世界瞧瞧。
⑷ Kotlin——数组
Kotlin为数组增加了一个Array类。为元素是基本类型的数组增加了XxxArray类(其中Xxx可以是Byte、Short、Int等基本类型)
Kotlin自己提供了一套集合体系,Kotlin的集合体系抛弃了Java集合体系中的Queue集合,Kotlin集合体系中增加了可变集合和不可变集合。
Kotlin的数组使用Array<T>来代表,Kotlin的数组就是一个Array类的实例,因此Kotlin数组是引用类型
访问数组是通过在数组的索引后跟一郑中个[]来实现,方括号中的值是数组元素的索引值。kotlin中的[]运算值其实是get(index)、set(index,value)方法,使用[]访问数组元素,调用的其实就是get(index)方法,使用[]为数组元素赋值,调用的其实就是set(index,value)方法
上面的两种方式本质是一样的,在经过编译器编译优化后,会转换成根据数组的内存地址来访问数组元素,性能不会有任何损失
所有的数组都有 size 属性,通过这个属性可以访问到数组的长度。
for-in 循环可以自动遍判乱历数组的每个元素
对数组使用for-in循环会被编译成使用基于索引的循环,并不会创建迭代器。因此具有良好的性能
kotlin数组提供了一个indices属性,这个属性可返回数组的索引区间
这种通过索引区间遍历的实现具有更好的性能,kotlin将会在底层掘丛档将其编译成根据内存地址来访问元素,不需要额外创建区间对象
Kotlin还为数组提供了一个lastIndex属性,该属性用于返回数组最后一个元素的索引,size-1
如果需要同时访问数组的索引和元素,可以使用数组的 withIndex() ,该方法返回一个Iterable对象,该对象的所有元素都是IndexedValue.
⑸ Kotlin & 'onConfigurationChanged' overrides nothing
编译项目报错:
但是这个方法是根据 AndroidStudio 自动补全功能,直接自动补全的
原因还是 Java 转 Kotlin 的类型转化导致知陪的,由于Kotlin 版本兼容问题,平台类型转为可空类型时出错。
去掉 可空类型符号 ? 就好了。
同轮猛升理,遇腊老到类似问题,可以去掉或者添加 可空类型符号 ? ,看问题能否解决。
⑹ kotlin—lazy及其原理
lazy是属性委托的一种,是有kotlin标准库实现。它是属性懒加载的一种实现方式,在对属性使用时才对属性进行初始化,并且支持对属性初始化的操作时进行加锁,使属性的初始化在多线程环境下线程安全。lazy默认是线程安全的。
lazy既然是属性委托的一种,那么其语法也遵循属性委托的语法:
对应的lazy 的语法为:
由于lazy为函数,其最后一个参数是函数,那么可以使用lamda的语法代替最后一个函数参数:
通过2中的语法,我们知道lazy是kotlin标准库中的重载函数,我们先从标准库lazy的函数的分析其原理:
lazy函数默认情况下是同步安全锁模式,其可以指定线程同步模式、线程公有模式、非线程安全模式,也在同步模式时指定使用的锁对象,lazy函数会创建懒加载类的实现类,通过懒加载类的实现类实现不同模式的懒加载。
我们依次分析SynchronizedLazyImpl、SafePublicationLazyImpl、UnsafeLazyImpl这三种模式是怎么实现懒加载的:
SynchronizedLazyImpl是同步模式的懒加载,它是lazy的默认实现,其在多线程环境下进行初始化是线程安全的,我们看看其源码实现:
同步模式的懒加载SynchronizedLazyImpl的实现原理其实是使用两个属性,一个是公有属性value—对外代表属性的值,一个是私有属性_value——是真正的值。value的get内部对_value进行初始化,如仔纳果_value已纳局初始化则直接返回,如果没有初始化过则加锁并调用初始化函数把返回值赋值给_value。
SafePublicationLazyImpl是多线程环境下的公共线程安全模式,我们从其源码分析其原理:
公共线程安全模式SafePublicationLazyImpl与同步模式SynchronizedLazyImpl的区别在于,SafePublicationLazyImpl使用自旋锁进行初始化操作,而SynchronizedLazyImpl是要同步锁的方式进行初始化操作,其他与SynchronizedLazyImpl的实现一样。
SafePublicationLazyImpl是非线程安全的懒加载实现模式,在单线程下进行初始化是没啥问题,但是多线程下是进行初始化是不安全的,我们从其源码分析其原理:
SafePublicationLazyImpl与前面的两种模式的实现方式不一样就是初始化时没有加任何锁,其它是一样的。
上面分析了使用lazy函数之后返回了不同的懒加载实现类及各懒加载实现类的原理,所以lazy的语句最终语句念茄没的是:
val propertyName by [SynchronizedLazyImpl | SafePublicationLazyImpl | UnsafeLazyImpl]
但具体是怎么个懒加载实现类的value的get方法呢?——下面我们举例,然后通过编译后的字节码分析器实现原理:
举例:
编译后的字节码文件:
通过对生成的字节码的分析,lazy的原理:
注意lazy实现了懒加载,达到在使用时才进行初始化的目的,但是也为此增加了一个懒加载类,如果一个类的初始化操作不耗时却使用lazy进行懒加载是不明智的,lazy的适合场景是类的初始化操作比较耗时占资源。
⑺ Kotlin的延迟初始化
Kotlin中有两种延迟首虚初始化的方式。一种 lateinit var ,一种 by lazy
在AS中Tools—>Kotlin—>show Kotlin Bytecode—>Decompile反编译Kotlin字节码得到
可以看到:我们在引用变量的时候会进行判断,如果为空(也就是未初始化),就会抛出异常。
by是属性委托关键字
注释:使用指定的初始化函数[initializer]来创建一个[Lazy]类型的对象,默认的线程模型是[LazyThreadSafetyMode.SYNCHRONIZED]。默认返回了SynchronizedLazyImpl对象:
我们反编译Kotlin字节码得到
可以看到,生成了一者磨燃个getter方法,return一个(String)var1.getValue(),也就是获取str会通过getValue。而SynchronizedLazyImpl实现了Lazy的value方法, 调用getValue方法返回_value, _value默认值是UNINITIALIZED_VALUE,表示为初始化,就会调用传入的initializer进行初始化,并把值赋给 _value,以后每次调用直接返回。
lateinit var和游猛by lazy都可以推迟初始化,lateinit var只是在编译期忽略对属性未初始化进行检查,何时初始化还需开发者自行决定。而by lazy在被第一次调用的时候能自动初始化,做到了真正的延迟初始化的行为。
⑻ 编程时选用的程序设计语言,对软件的开发与维护的影响
【CSDN 编者按】“如果我们把人类文明想象成汽车的话,那么软件开发行业就相当于汽车的引擎,编程语言就像引擎的燃料。”作为一名开发者,需跟随技术潮流的发展来学习新技术。2020年,你有计划新学一门编程语言吗?
本文作者从一名架构师的角度,详细分析了7种现代编程语言的优点与功能,你对哪门语言最感兴趣呢?
作者 | Md Kamaruzzaman,软件架构师
译者 | 弯月,责编 | 伍杏玲
封图| CSDN 下载于视觉中国
出品 | CSDN(ID:CSDNnews)
以下为译文:
如果我们把人类文明想象成汽车的话,那么软件开发行业就相当于汽车的引擎,而编程语言就像引擎的燃料。作为一名开发者,今年你应该学习哪种编程语言呢?
学习一种新的编程语言无疑是时间、精力和智力上的巨大投资, 但是学习一种新的编程语言可以提升你的软件开发技术力,促进你的职业发展。
在这里,我将献上一份现代编程语言的列表,这些语言不仅有助于提高你的生产力,而且还可以促进你的职业发展,并让你成长为更优秀的开发人员。这份列表还涵盖了非常广泛的领域:系统编程、应用程序开发、Web开发、科学计算等。
什么是现代编程语言?
“现代编程语言”这个说法本身就很含糊。许多人认为Python和JavaScript等语言是现代编程语言,还认为Java是一种古老的编程语言。实际上,这几种语言大约在同一时间出现:1995年。
大多数主流编程语言是上个世纪开发的:七十年代(如C)、八十年代(如C ++)、九十年代(如Java、Python、JavaScript)。这些语言在设计上并没有考虑现代软件开发生态系统:多核CPU、GPU、快速的互联网、移动设备、容器和云等。尽管许多语言中的许多功能都已进行一些改进,如并发等,而且在不断调整自己以适应时代,但它们依然保留了向后兼容性,无法抛弃那些过时的旧功能。
在这方面,Python就做得很好(某种意义上也未必是好事),Python 2和Python 3两者之间有明确的分界线。很多语言常常会为解决同一个问题提供十余种的方法,同时又没有顾及到开发人员的感受。根据StackOverflow的开发人员调查,大多数旧时的主流编程语言在“最可怕的语言”排名都名列前茅:
如果非要在新旧编程语言之间划个界限的话,那么应该是2007年6月29日,也就是第晌扮埋一台iPhone发行的时候。在这之后,编程语言界发生了很大变化。因此,在本文的列表中,我只考虑2007年以后的编程语言。
为什么要学习新语言?
首先,现代编程语言充分利用现代计算机硬件(多核CPU、GPU、TPU)、移动设备、大量数据、高速互联网、容器和云的优势。大多数现代编程语言会关注开发人员的体验,比如:
简洁明了的代码(减少样板代码)
内置的并发支持
空指针安全
类型推断
简洁的功能集
降低学习难度
融合所有编程范例的最佳功能
通过所有权和借用概念提供内存安全和并发安全。
内存安全和并发安全在编译时确保,即如果程序代码可以宴蚂编译,那么内存既安全又没有数据竞争。这是Rust最吸引人的功能。
它还提供了Haskell中元编程的表现力。凭借不可变的数据结构和功能编程功能,Rust提供了功能并发和数据并发。
Rust的速度非常快,纯Rust的性能甚至优于纯C。
在没有运行时的情况下,Rust可以完全控制现代硬件(TPU、GPU、多核CPU)。
Rust具有LLVM支持。因此,Rust提供一流的与WebAssembly的互操作性,而且Web代码也非常快。
系统编程
Serverless 计算
商业应用
C
C++
Go
Swift
Go具有一流的并发支持。Go不通过线程和锁提供“共享内存”并发性,因为编程难度太大。相反,它提供了基于CSP的消息传递并发性(基于Tony Hoare的论文)。Go使用“ Goroutine”(轻量级绿色线程)和“ Channel”进行消息传递。
Go最大的杀手级功能是:简单,它是最简单的系统编程语言。新手软件开发人员只需几天就可以编写高效的代码,就像Python一样。有些大规模的云原生项目(如Kubernetes、Docker)都是用Go编写的。
Go还内置了垃圾收集器,这意味着开发人员无需担心C/C++中的内存管理问题。
Google投入了大量资金打造Go。因此Go拥有大量的工具支持。新手Go开发人员拥有大量的工具生态系统。
一般,开发人员80%的时间都花在了维护现有代码上,用于编写新代码的时间只占20%。由于其简单性,Go在语言维护方面表现出色。如今,Go在业务应用程序中大量使用。
系统编程
Serverless 计算
商业应用
云原生开发
C
C++
Rust
Python
Java
Kotlin的主要卖点在于其语言设计。我总是将Kotlin视为JVM上的Go/Python,因为它简洁明了的代码。因此,Kotlin的生产力很高。
与许多其他现代语言一样,Kotlin提供了Null指针、安全性、类型推断等功能。
由于Kotlin也运行在JVM中,因此现有Java库庞大的生态系统都可供使用。
Kotlin是一流的Android应用开发语言,并且已经超过Java,成为开发Android应用的首选。
Kotlin得到了JetBrains和Open Source的支持,因此具有出色的工具支持。
Kotlin有两个有趣的项目:Kotlin Native(将Kotlin编译为原生代码)和kotlin.js(Kotlin到JavaScript)。如果成功,则可以在JVM外部使用Kotlin。
Kotlin还提供了一种简单的方式来编写DSL(域特定语言)。
企业应用程序
主要竞争对手:
TypeScript
JavaScript是一门优秀的编程语言,在2015年之前,JavaScript有很多缺点。着名的软件工程师Douglas Crockford写了一本书名为《JavaScript: The Good Parts》,暗示了JavaScript有很糟的部分。无模块化,还有“回调地狱”,因此开发人员都不喜欢维护特别大的JavaScript项目。
Google甚至还开发了一个平台,可将Java代码反编译为JavaScript代码(GWT)。许多公司和个人都曾尝试开发更好的JavaScript,例如CoffeeScript、Flow、ClojureScript。最终,微软的TypeScript取得了成功。
微软的一队工程师在着名的Anders Hejlsberg的带领下,创建了JavaScript的静态类型、模块化超集——TypeScript。
TypeScript可以编译为JavaScript。于2014年首次发布后,TypeScript很快引起了社区的关注。Google当时还计划开发JavaScript的静态类型超集。Google对TypeScript青睐有加,以至于他们没有开发新的语言,而是选择与微软合作改进TypeScript。
Google选择TypeScript作为其SPA框架Angular 2+的主要编程语言。此外,流行的SPA框架React也提供对TypeScript的支持。另一个流行的JavaScript框架Vue.js也宣布将使用TypeScript开发新的Vue.js 3:
另外,node.js的创建者Ryan Dahl已决定使用TypeScript来开发安全的Node.js替代品Deno。
主要特征:
流行度:
开发人员喜欢TypeScript的优雅语言设计。在StackOverFlow最受欢迎的语言类别的调查中,TypeScript与Python并列第二名:
根据GitHub的排名,TypeScript是增长最快的编程语言之一,排名第五:
从GitHub的贡献度来看,TypeScript排名第七,打进了前十:
Google的趋势表明,在过去的几年中,TypeScript的热度越来越高:
主要用途:
主要竞争对手:
Swift
当初乔布斯拒绝在iOS中支持Java(和JVM),他认为Java不再是主流编程语言。如今我们发现乔布斯当初的估计是错的,虽然iOS仍然不支持Java。苹果选择了Objective-C作为iOS中的首选编程语言。Objective-C是一门很难掌握的语言,它不支持现代编程语言所要求的高生产力。
后来,苹果的Chris Lattner和其他人开发了一种多范例、通用的、编译编程语言——Swift,来替代Objective-C。Swift的第一个稳定版本于2014年发布。Swift还支持LLVM编译器工具链(也由Chris Lattner开发)。Swift与Objective-C代码库具有出色的互操作性,并且已确立为iOS应用开发中的主要编程语言。
主要特征:
流行度:
开发人员对Swift的喜爱不亚于许多其他现代编程语言。根据StackOverflow的调查,Swift在最受欢迎的编程语言中排名第六:
2019年,在TIOBE的编程语言排名中,Swift的排名上升到了第10名。鉴于这种编程语言只有5年的历史,可以说是成绩斐然:
Google的趋势表明,在过去的几年中,Swift的热度出现了激增:
主要用途:
主要竞争对手:
Dart
Dart是Google出品的第二大编程语言。Google是Web和Android领域的巨头,因此Google在Web和应用领域开发自己的编程语言也不足为奇。在丹麦软件工程师Lars Bak(领导Chrome的 JavaScript V8引擎开发)的带领下,Google于2013年发布了Dart。
Dart是一种通用编程语言,支持“强类型”和“面向对象”编程。Dart也可以转编译为JavaScript,凡是JavaScript可以运行的任何地方(例如Web、移动、服务器)几乎都可以运行 Dart。
主要特征:
流行度:
根据GitHub Octoverse数据显示,Dart是2019年增长最快的编程语言,去年它的流行度增长了五倍:
根据TIOBE指数显示,Dart排名第23,仅用了4年时间就超过了很多其他的现代编程语言:
根据StackOverflow的调查,Dart在最受欢迎的编程语言中排名第12:
受Flutter的影响,Google的趋势表明,在过去的两年中,Dart的热度急剧上升:
主要用途:
主要竞争对手:
Julia
本文提及的大多数编程语言都是由大型公司开发的,但Julia是个例外。科技计算领域通常都会使用动态语言,例如Python、Matlab。虽然这些语言提供易于使用的语法,但不适用于大规模的科技计算。他们需要使用C/C ++库执行CPU密集型任务,因此这就产生了着名的“两种语言”的问题,因为他们需要粘合代码来绑定两种语言。由于编写的代码需要在两种语言之间来回切换,因此总是会损失部分性能。
为了解决这个问题,麻省理工学院的一队研究人员计划从头开始创建一种新的语言,这种语言既可以利用现代硬件的优势,而且还结合其他语言的优势。于是,Julia诞生了。
Julia是一种动态的高级编程语言,提供一流的并发、并行和分布式计算支持。Julia的第一个稳定版本于2018年发布,并很快受到社区和行业的关注。Julia可用于科学计算、人工智能和许多其他领域,而且还可以解决“两种语言”的问题。
主要特征:
流行度:
Julia在许多领域主要与Python竞争。由于Python是最流行的编程语言之一,因此Julia想晋升主流还需要几年的时间。
虽然Julia非常新(只有一岁),但仍在TIOBE指数中排到第43名:
Google趋势显示,在过去的一年中,Julia的热度在稳步增长:
但是考虑到Julia的功能集,以及NSF、DARPA、NASA、因特尔等公司的推动,相信Julia取得突破的进展只是时间的问题。
主要用途:
主要竞争对手:
原文链接:https://towardsdatascience.com/top-7-modern-programming-language-to-learn-now-156863bd1eec
本文为 CSDN 翻译,转载请注明来源出处。
【End】
Python
Matlab
科学计算
高性能计算
数据科学
可视化
与Rust一样,Julia的主要特征在于语言的设计。这种语言在不牺牲性能的情况下,将高性能和科学计算中现有编程语言的一些功能结合在一起。就目前的情况来看,Julia出色地完成了这项任务。
Julia是一种动态编程语言,支持类型系统但类型不是必须的。因此,Julia这种编程语言很容易学习,生产力很高。
Julia的核心是多调度编程范例。
Julia内部支持并发、并行和分布式计算。
Julia为I/O密集型任务提供异步I/O。
Julia的运行速度非常快,可用于需要数百万个线程的科学计算。
JavaScript
TypeScript
应用开发
UI开发
与Go一样,Dart也非常注重开发人员的工作效率。由于Dart简洁的语法,以及高效的生产力,受到开发人员的喜爱。
Dart还提供“强类型”和“面向对象”编程。
Dart是少数同时支持JIT编译(运行时编译)和AOT编译(创建时编译)的编程语言之一。因此,Dart可以针对JavaScript运行时(V8引擎),并且Dart可以编译为快速的原生代码(AOT编译)。
跨平台原生应用程序开发平台Flutter选择了Dart作为开发iOS和Android应用的编程语言。从那以后,Dart的流行度越来越高。
与Goog的Go编程语言一样,Dart也具有出色的工具支持和庞大的Flutter生态系统。Flutter的日益普及也会推动Dart的采用率升高。
Objective-C
Rust
Go
iOS应用开发
系统编程
客户端开发(通过WebAssembly)
Swift的杀手级功能之一是其语言设计。语言本身很简单,语法简洁,比Objective-C更高效。
Swift还提供了现代程序语言的功能:null安全。此外,它还提供了语法糖来避免“厄运金字塔”。
作为一种编译语言,Swift和C++一样快。
Swift支持LLVM编译器工具链。因此,我们可以在服务器端编程,甚至浏览器编程(使用WebAssembly)中使用Swift。
Swift提供了自动引用计数(ARC)支持,可抑制内存管理的不善。
JavaScript
Dart
Web UI开发
服务器端开发
与Go或Kotlin同样,TypeScript的主要特征也是语言设计。TypeScript凭借其简洁明快的代码,成为了目前最优雅的编程语言之一。就开发人员的生产力而言,它与JVM或Go/Python上的Kotlin并驾齐驱。TypeScript是生产力最高的JavaScript超集。
TypeScript是JavaScript的强类型超集,特别适合大型项目,而且可以称为“可扩展的JavaScript”。
单页应用程序框架的“三巨头”(Angular、React、Vue.js)为TypeScript提供了出色的支持。在Angular中,TypeScript是首选的编程语言。在React和Vue.js中,TypeScript越来越受欢迎。
最大的两家技术巨头:微软和Google正在合作开发由活跃的开源社区支持的TypeScript。因此,TypeScript拥有最好的工具支持。
由于TypeScript是JavaScript的超集,因此凡是可以运行JavaScript的任何地方都可以运行TypeScript,包括浏览器、服务器、移动设备、物联网设备和云。
Java
Scala
Python
Go
本文列表的许多编程语言都带有革命性地变化,并将永久地改变软件行业缺扒。一些已成为主流编程语言,还有一些则有望取得突破。因此选择这些语言作为第二种编程语言是明智的做法。
Rust
一直以来,系统编程语言环境主要由靠近硬件的语言(如C、C ++等)主导。尽管它们可以完全控制程序和硬件,但是它们缺乏内存安全性。即使它们支持并发,使用C/C ++编写并发程序也很困难,因为没有并发安全性。还有一些流行的编程语言是解释性语言,例如Java、Python、Haskell。这些语言具备安全性,但需要庞大的运行时或虚拟机。由于它们的运行时间长,因此Java等语言不适合于系统编程。
许多人曾尝试将C/C ++的功能与Java、Haskell的安全性相结合。然而,Rust才是第一个成功实现了这一点的编程语言。
Graydon Hoare在业余项目中开发出了Rust,他的灵感来自研究编程语言Cyclone。Rust是开源的,由Mozilla与许多其他公司和社区一起领导这门语言的开发。Rust于2015年首次发布,并很快引起了社区的关注。
主要特征:
流行度:
自2015年首次亮相以来,Rust已被开发人员广泛接受,并在StackOverflow开发人员调查中连续四年(2016、2017、2018、2019)被评选为最受欢迎的语言:
根据GitHub Octoverse的调查,Rust是运行速度第二快的语言,仅次于Dart:
此外,根据编程语言流行度排名网站PyPl的数据,Rust排名第18位,并呈上升趋势:
对比Rust提供的功能集,我们就会明白为什么微软、亚马逊、Google等科技巨头相继宣布投资Rust作为一种长期的系统编程语言。
根据Google统计的趋势,在过去的5年中,Rust的热度每年都在增加。
主要用途:
主要竞争对手:
Go
在本世纪初,Google面临两个扩展问题:开发扩展和应用程序扩展。开发扩展问题指的是他们不能仅通过投入开发人员的方式来添加更多功能。应用程序扩展问题则指他们无法开发出一款能够扩展到Google级别的计算机集群的应用程序。
所以在2007年左右,Google创建了一种新的编程语言,用于解决这两个扩展问题。两位才华横溢的Google软件工程师Rob Pike(UTF-8)和Ken Thompson(UNIX OS)创建了一种新语言。
2012年,Google正式发布了第一版的Go编程语言。Go是一种系统编程语言,但与Rust不同,它还具有Runtime和垃圾收集器(几兆字节)。但是与Java或Python不同,这个Runtime包含了生成的代码。最后,Go生成了一个本地的二进制代码,可以在没有附加依赖项或运行时的情况下在计算机中运行。
主要特征:
流行度:
Go一问世就受到了软件开发社区热烈的欢迎。2009年-2018年,Go一直在TIOBE编程语言排行榜上徘徊。Go的成功为Rust等新一代编程语言铺平了道路。
如今,Go已是主流编程语言。最近,Go团队宣布了有关“Go 2”的消息,这门编程语言的发展会更加稳固。
几乎在所有的流行编程语言排行榜中,Go的排名都很高,已超过许多现有的语言。自2019年12月以来,在TIOBE指数排名中,Go名列第15位:
根据StackOverFlow的调查,十大最受喜爱的编程语言中,Go也位列其中:
此外,根据GitHub的数据,Go也是十大发展最迅速的语言之一:
Google趋势显示,在过去的5年中,Go的热度每年都在增加。
主要用途:
主要竞争对手:
Kotlin
Java 是企业软件开发领域无可争议的王者。近年来,Java受到了一些负面评论:过于冗长,大量样板代码,容易出现意外的复杂性。但是,关于Java虚拟机(JVM)的争论却很少。JVM是软件工程的杰作,经过了时间的考验,提供了硬核的runtime。
多年来,Scala等JVM语言一直在努力克服Java的缺点,想成为更好的Java,但他们都失败了。最终,这场提升Java的探索以Kotlin的诞生结束。Jet Brains(流行的IDE IntelliJ背后的公司)开发了Kotlin,它可以在JVM上运行,克服了Java的很多缺点,提供许多现代功能。
与Scala不同的是,Kotlin比Java更简单,还可在JVM中提供与Go或Python开发人员同等的生产力。
Google宣布Kotlin是一流的Android应用开发语言,因此Kotlin在社区中的接受度得到了大幅提高。自2017年以来,同样受欢迎的Java Enterprise框架Spring也开始支持Kotlin。我曾尝试结合Kotlin与Reactive Spring使用,体验非常棒。
主要特征:
流行度:
自2015年首次发布以来,Kotlin的知名度不断飙升。根据Stack Overflow,Kotlin是2019年第四大最受欢迎的编程语言:
Kotlin还是增长最快的编程语言之一,排名第四:
在流行编程语言排名网站PyPl的排名中,Kotlin名列第十二名,并具有较高的上升趋势:
自从Google宣布Kotlin是一流的Android应用开发语言以来,Kotlin的流行趋势出现了大幅上涨,如下所示:
主要用途:
⑼ SpringBoot到Kotlin血泪史
如果原先有 @Bean(name="xxx") 直接用方法名即可(我原先的 name 和方法名不一样洞段就很尴尬)
hashedCredentialsMatcher 中的内容可以直接 new ,所以不需要注入
如果SpringBoot的版本从 1.5.x 变成了 2.0.x , shiroDialect 或者 shiroFilter 可能会报如下错误
把 thymeleaf-extras-shiro 的版本号改成 2.0.0 即可(原先是 1.2.1 )
在 SpringBoot 版本中,在 Realm 中注入 Service 时,为了启用缓存,需要在前面加上 @Lazy 注解,如下
在 Kotlin 版本中我不知道发了啥疯就把它去掉了(可能是看到前面类型是 lateinit var ,自以为是的觉得可以代替 @Lazy ),然后改成了改成如下形式
拷贝完整个丛滚项目之后,测试功能的时候,发现缓存没了……然后就开始疯狂DEBUG,从版本问题,到 jar 包冲突问题,经历了很漫长的一段时间后,我定位到了 ShiroConfiguration ,只要把 shiro aop 注解关闭就可以开启缓存了
WHAT??
疯狂谷纳郑誉歌一个小时无果(因为一直以为是 Kotlin 不兼容啥的,或者是 shiro 在 boot2.x 之后需要修改相应的配置)
然后又疯狂DEBUG,把 Kotlin 版和 springboot 版进行对比,最后。定位到了 @Lazy (还好只是改成了注释,没把它给直接删了)
果然。加了 @Lazy ,整个天都亮了
最后顺便提一句 Realm 认证超级管理员的问题,可以直接在 Realm 中加上超级管理员的特别认证,就不用去方法级别上区分这个权限可以超级管理和XX管理员都可用了
⑽ Kotlin介绍系列(三)高级用法之DataClass
经常会需要创建一些类除了保存数据不干其他事情,比如我们腊凳野解析网络请求下轮喊来的数据。Kotlin就提供了一个非常方便的class—— data class
我们知道在Kotlin中,声明类的同时可以方便的直接声明构造方法等参数,鉴于data class只是存放数据,那么只一个构造方法足矣,所以连类的body也就不需要了。是不是很清爽?
编译器会根据我们在构造函数里声明的属性自动导出下列成员:
经常会遇到我们只需要替换一个对象的个别属性,而其他属性保留的情况。这就是data class中生成的函数的作用了。
本文已开始的例子类,它的生成的默认函数是下面粗和这样的:
fun (name: String = this.name, age: Int = this.age) = User(name, age)
这就运训我们这样写:
data class的生成的component方法给我们的结构化声明及使用提供了可能
Kotlin介绍系列(三)高级用法之object
Kotlin介绍系列(三)高级用法之Delegation