开发者社区> 美人迟暮> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Kotlin 和 Java EE(Part 3):让 Kotlin 符合使用习惯

简介:
+关注继续查看

本文通过观察 Java EE 和 Kotlin 的关系,探讨如何利用 Kotlin 的运算符、可空性和 Optional 来实现最大的效果。

将 Java EE 应用转换为 Kotlin 始于框架的战斗,我们成功战胜了所有阻碍和过时的标准。在这个过程中,代码充斥着丰富而现代的 Kotlin 特有的结构,变得简洁而又不失安全。

如果还没有读这个系列的前面两篇文章,可以看看:

Kotlin and Java EE: Part One - From Java to Kotlin

Kotlin and Java EE: Part Two - Having Fun with Plugins

先简要回顾一下之前进行的改变,然后再补充一些最后的结果。

边城
边城
翻译于 2周前
0人顶
顶 翻译得不错哦!
我们已经做了什么

前两个部分中的很多结构已经符合 Kotlin 的惯例了。我们来看下 set 的定义:

private final Set<Class<?>> classes =
    new HashSet<>(Arrays.asList(KittenRestService.class));

由于 Java 并不支持简单地通过一些对象构造 Set 或其它集合类型,因此我们需要用 Arrays 类来创建 List (!),然后将其转换为 Set。在 Kotlin 中代码变成了:

private val classes = setOf(KittenRestService::class.java)
我们还把 Java Bean 转换为 Kotlin 数据类(data class),使代码变得更简短。我们去掉了所有 getter 和 setter,并自动获得 equals()、hashCode() 和 toString()。

@Entity
data class KittenEntity private constructor(
        @Id
        var id: Int?,
        override var name: String,
        override var cuteness: Int // set Int.MAX_VALUE for Nermal
) : Kitten {
    constructor(name: String, cuteness: Int) : this(null, name, cuteness)
}

因为有编译器插件,我们可以“假冒”不可变对象而不需要无参数构造函数。

@Path("kitten")
class KittenRestService 
    @Inject constructor(private val kittenBusinessService: KittenBusinessService) {

lateinit 关键字让框架可以更方便地处理值的初始化,还可以避免不必要的空检查:

@Stateless
class KittenBusinessService {
    @PersistenceContext
    private lateinit var entityManager: EntityManager
    ...

再来看看我们还可以改进什么。

边城
边城
翻译于 2周前
0人顶
顶 翻译得不错哦!
Null 还是 Optional?

这是一个相当棘手的问题。Kotlin 对可空值的支持已经很好了,尤其是在使用第三方库的时候会有很大的帮助。问题是当你有机会进行选择的时候你会选择哪一个?下面是原来我们生成和使用 Optional 的代码:

fun find(id: Int): Optional<KittenEntity> =
    Optional.ofNullable(entityManager.find(KittenEntity::class.java, id))
fun find(id: Int): KittenRest = 
    kittenBusinessService
        .find(id)
        .map { kittenEntity -> KittenRest(kittenEntity.name, kittenEntity.cuteness) }
        .orElseThrow { NotFoundException("ID $id not found") }

惯用的 Kotlin 解决方案会使用空值,像这样:

fun find(id: Int): KittenEntity? =
    entityManager.find(KittenEntity::class.java, id)
fun find(id: Int) = 
    kittenBusinessService.find(id)
        ?.let { KittenRest(it.name, it.cuteness) }
        ?: throw NotFoundException("ID $id not found")

可空值会出现在调用链的每个节点上,所以你必须使用问号来进行调用。它虽然解决了空值问题,但并不好看。

然而,如果返回类型是 Optional,而结果是 Optional.empty,后面的所有单独调用(monadic calls)都会被简单的跳过,结果直接变成 Optional.empty。对于我来说这是个很简洁的解决方案,如果想从 Java 调用 Kotlin 代码这也更安全, 对于 Java 互操作,优先使用 Optional 来处理可空值。

边城
边城
翻译于 2周前
0人顶
顶 翻译得不错哦!
运算符!

find、add 和 delete 都是完全有效的方法名称,但用运算符代替它们不是很好吗?

运算符!
screenshot

我发现运算符不只是更短,可读性也更强,因为代码不再是一大堆方法调用。但要小心使用大家都知道或理解的运算符,否则你会遇到和 Scala 库类似的大麻烦,然后就得有一个运算符表来解释。在使用数据仓库的情况下,类似 MutableMap 的接口工作良好。注意,我使用“赋值加”(+=) 运算符来保存一个实体,因为原来的集包含了已经拥有的元素,又另外增加了一个元素。

这是声明:

operator fun plusAssign(kitten: KittenEntity) = 
    entityManager.persist(kitten)
operator fun get(id: Int): KittenEntity? = 
    entityManager.find(KittenEntity::class.java, id)

你可能想保留原来的方法,同时使用运算符来对它们进行包装,因为原来的方法可以返回值,而某些运算符却不能。其它可选用运算符的操作包括“remove” 和 “contains” 方法,因为它们可以用“赋值减”(-=)和Kotlin 的 in 运算符。剩下的请你充分发挥自己的想像。

边城
边城
翻译于 2周前
0人顶
顶 翻译得不错哦!
结论

以符合使用习惯的方式书写,目的是使代码更具可读性以及更安全,我希望展示的例子能够成功地实现这一目标。 该系列仅显示了几种方法来改进 Java 版本的代码,同时使某些地方保持不变。一些值得探索的功能是:扩展函数,以及 if,when,try/catch 功能。去探索吧,找到对你有用的功能。

完整的代码可以在这里找到。

文章转载自 开源中国社区 [http://www.oschina.net]

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Android Sqlite数据库升级——kotlin
对于android开发同学来说,数据库相关操作是我们日常操作之一,相应的数据库的升级操作就必不可少了。这里我总结下数据库升级时需要注意的事项。 Android中数据库操作的核心类是SqliteOpenHelper,这个类有两个方法,onCreate和onUpgrade。onCreate方法只会调用一次,onUpgrade方法会在版本号增加之后触发。 数据库升级的操作过程中,我们需要处理的情况有两种,第一种是数据库从低版本升级上来的,第二种是新安装app的用户。
0 0
Kotlin学历之Android MVP架构实战
Kotlin学历之Android MVP架构实战
0 0
Kotlin | 使用Kotlin改造Android Gradle
Gradle5.0+已经支持了Kotlin,但碍于Android Studio目前适配并不是很好,所以并不建议开发使用,至于为什么,在文章末尾也给出了具体原因。
0 0
Android 蓝牙开发(扫描设备、绑定、解绑)Kotlin版
Android 蓝牙开发(扫描设备、绑定、解绑)Kotlin版
0 0
在Android Studio中使用Kotlin
在Android Studio中使用Kotlin
0 0
当Android的Kotlin出现了Unresolved reference:***(设置的控件id)
这几天学习Kotlin,在看郭霖老师的《第一行代码》第三版这本书,这里一段程序,同样得样例,自己敲会报错(入图),很疑惑,自己手动解决了。 这里出现了Unresolved reference: recyclerView,我前面activity_main.xml设置了一个id 解决这问题,要在MainActivity加入包 import kotlinx.android.synthetic.main.activity_main.* 如果kotlinx 报红了,要在app的build.gradle文件中
0 0
Android Studio 制作聊天界面实践(Kotlin版)
Android Studio 制作聊天界面实践(Kotlin版)
0 0
【Kotlin 初学者】Android Studio 运行 main 函数报错解决
目录 Andorid Studio 运行 main 函数报错: Gradle构建问题 New Project问题 运行成功 IntelliJ IDEA 其他问题 kotlin-gradle-plugin Failed to find Build Tools revision 31.0.0 解决方案1:移除buildToolsVersion版本 解决方案2:降低buildToolsVersion
0 0
使用Kotlin开发Android应用
Kotlin是一门基于JVM的编程语言,它正成长为Android开发中用于替代Java语言的继承者。Java是世界上使用最多的编程语言之一,当其他编程语言为更加便于开发者使用而不断进化时,Java并没有像预期那样及时跟进。
0 0
+关注
美人迟暮
Nothing for nothing.
文章
问答
文章排行榜
最热
最新
相关电子书
更多
Java 8 简明教程
立即下载
《Java开发手册》2019最新版发布!
立即下载
Java基础入门(四)-泛型、反射、注解
立即下载