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 都是完全有效的方法名称,但用运算符代替它们不是很好吗?

运算符!

我发现运算符不只是更短,可读性也更强,因为代码不再是一大堆方法调用。但要小心使用大家都知道或理解的运算符,否则你会遇到和 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]

时间: 2024-11-10 00:46:02

Kotlin 和 Java EE(Part 3):让 Kotlin 符合使用习惯的相关文章

Kotlin和Java EE系列之—— 如何让Kotlin类对Java EE友好

Kotlin 和 Java 都是 JVM 语言,所以它们之间相互转换很容易,是这样吗?不完全是,让 Kotlin 的类对 JEE 友好还需要一点工作. Kotlin 的主要优势之一就是能很好地集成 Java.事实上 Java 很容易转换为 Kotlin,看起来用 Kotlin 写 Java EE 应用似乎不需要动什么脑筋.然而,两者之间存在一些微妙的差别,使得转换并不那么顺畅: 大多数框架要求非 final 的类,而 Kotlin 的类是 final 的. 注入会引入大量不必要的空检查. 上述两

Java EE开发四大常用框架

对Java EE中常用的四个框架做一下系统的归纳 Struts     Struts是一个基于Sun Java EE平台的MVC框架,主要是采用Servlet和JSP技术来实现的.     Struts框架可分为以下四个主要部分,其中三个就和MVC模式紧密相关:     1.模型 (Model),本质上来说在Struts中Model是一个Action类(这个会在后面详细讨论),开发者通过其实现商业逻辑,同时用户请求通过控制器(Controller)向Action的转发过程是基于由struts-c

Kotlin与Java之争 究竟谁更好?

Kotlin Kotlin 是一门相对比较新的 JVM 语言,JetBrains 自 2011 年以来一直在积极地开发. 多年来,该语言在 Android 社区受到的关注度越来越高,并在 Google IO 2017 大会之后成为 Android 开发领域最热门的话题.这次大会宣布,Android 正式支持 Kotlin. 遗憾的是,虽然已经有许多关于 Kotlin 的文章,但并没有多少客观信息,许多开发人员仍然在苦思冥想,迁移到 Kotlin 是否是一条正确的道路. 在本文的剩余部分,我将尝试

Kotlin的互操作——Kotlin与Java互相调用

互操作就是在Kotlin中可以调用其他编程语言的接口,只要它们开放了接口,Kotlin就可以调用其成员属性和成员方法,这是其他编程语言所无法比拟的.同时,在进行Java编程时也可以调用Kotlin中的API接口. Kotlin与Java互操作 1 Kotlin调用Java Kotlin在设计时就考虑了与Java的互操作性.可以从Kotlin中自然地调用现有的Java代码,在Java代码中也可以很顺利地调用Kotlin代码. [例1]在Kotlin中调用Java的Util的list库. packa

Kotlin VS Java:编译速度大比拼,到底谁更快?

把一个Java应用程序转换为Kotlin,编译时间要多久? 这是关于Kotlin的一系列文章.分为三个部分. 第一部分讨论了从Java转换到Kotlin.第二部分是我对Kotlin的看法. 在前面的文章中, 我讨论了把Android 应用从Java 100%转换为Kotlin . Kotlin代码比Java的简洁,更易于维护,所以我认为转换是值得的. 但有些人不想试用Kotlin,因为他们担心它编译可能没有Java快. 这个关注点绝对是正确的,如果变得编译很慢,没有人愿意转换他们的代码. 所以,

方便 Ajax 与 Java EE 的集成

随着 Ajax 的兴起,对于消解这个热门技术的谜团并有针对性地处理在它的使用中出现的问题的需求出现了.高级 IT 专家 Patrick Gan 利用这个机会,研究了在 Java EE Web 应用程序中引入 Ajax 对整个开发生命周期可能产生的影响.对采纳 Ajax 基于异步通信的模式会存在的问题保持清醒,有助于踏上有效集成 Ajax 的正确道路. Asynchronous JavaScript + XML (Ajax)是个相当新的术语(有些人说它是旧酒装新瓶),在不同的 Web 开发社区中,

图片-java ee中的EJB出现错误:

问题描述 java ee中的EJB出现错误: 解决方案 看异常貌似是jdbc/MysqlDB_pm 这个数据源配置的问题

在Java EE环境下使用Kodo EJB

Kodo EJB是一个支持对象/关系映射的框架,根据EJB3规范的要求,Kodo EJB除了支持在普通Java应用中提供轻量级的持久层框架之外,也支持在JAVA EE容器中使用满足重量级企业应用的需求,充分利用JAVA EE容器中提供的优越特性如容器管理事务.远程(Remote)访问. 基于Kodo EJB开发的应用支持使用EJB或者JCA标准接入到JAVA EE环境中: JCA Kodo EJB支持JCA1.0标准,因此基于Kodo EJB开发的应用可以和其他JCA资源一样轻松的发布到JAVA

避免Java EE项目评估中的常见错误

错误|项目 摘要: 软件开发项目评估是软件开发周期中关键又具备挑战性的一步,它是计划,进度,人员以及其他相关步骤的基础.项目低估会带来紧张的进度,高度压力的工作环境,未可预料的资源紧缺,低质量,项目实施延误等风险, 可以最大限度的破坏客户的生意以及公司的信誉:而另一方面,带有过多不合理泡沫的评估也会导致无效率的资源浪费以及引起客户和公司之间的不信任.评估企业Java项目因为技术的更新成了一个难题,本文通过几个方面透视提供了评估企业Java项目时应该考虑的问题 假如你是一个重要软件项目的项目经理,