Pinterest官方博客:其实Java能做的,Kotlin都能做的更好

虽然最近 Kotlin变得越来越火,但你也许会好奇为啥Kotlin就火了呢?难道Kotlin能做什么Java不能做的吗?

对于新技术保持理性审慎的态度是一种很好的习惯。虽然两者能做的事没有本质的区别,但确实有些方面Kotlin更出色。Kotlin能实现的大部分功能都可以通过一些编程技巧用Java实现,而且很多应用程序的开发都没有使用Kotlin,开发起来也很顺利。事实上,Kotlin比Java做得更好的其实是通过简化代码和易于阅读来加快开发速度,同时免去写一些格式化的代码。

这篇文章中我们将关注两个点:Kotlin的属性和为空性(Nullability)。

属性

让我们从新应用程序创建一个常见的模型(用户模型)开始。这个用户模型有两个字段,一个电子邮件地址(字符串型)和一个用户的年龄(整数型)。在Java中,开发人员可能习惯于自己把它实现出来或者使用IDE自动生成。下面是一个Java的例子:

public final class User {

@NotNull

private final String email;

private final int age;

public User(@NotNull String email, int age) {

if (email == null) {

throw new RuntimeException("Email can't be null");

}

super();

this.email = email;

this.age = age;

}

@NotNull

public final String getEmail() {

return this.email;

}

public final int getAge() {

return this.age;

}

public String toString() {

return "User(email=" + this.email + ", age=" + this.age + ")";

}

public int hashCode() {

}

@NotNull

public final User copy(@NotNull String email, int age) {

Intrinsics.checkParameterIsNotNull(email, "email");

return new User(email, age);

}

public boolean equals(Object otherObject) {

if(this != otherObject) {

if(otherObject instanceof User) {

User otherUser = (User)otherObject;

return true;

}

}

return false;

} else {

return true;

}

}

}

这段大约50行的代码用来创建用户模型所需的getter,setter和equal方法。现在,让我们来看看Kotlin是怎么做的:

data class User(val email: String, val age: Int)

只有一行代码,请注意这并没有任何错误,也不是VimGolf。这就是Kotlin,简洁就是它的优势之一。在功能上,这一行Kotlin代码与Java那50行左右的代码完全相同。从技术上讲,这并不是完全正确的,因为Kotlin还可以保证开发人员在编译时不会向电子邮件这一参数传递Null。

为空性

现在让我们深入一下Kotlin的为空性(或者称为“空值判断”)特性。Kotlin将Null内置到类型系统中。这意味着在Kotlin中定义一个对象时,必须指定是否允许它为Null,因为默认情况下,对象都是不能为Null的。

比如,我们用Java写一个简单的事件记录类,它需要用户的电子邮件来记录事件:

public class LoggingClass {

private final User myUser;

public LoggingClass(User myUser) {

this.myUser = myUser;

}

public void logEvent(String eventName) {

String userEmail = myUser.getEmail();

AnalyticsClient.logEvent(eventName, userEmail);

}

}

上面这段Java代码的问题是:如果myUser为Null,对logEvent的调用可能会抛出NullPointerException的异常,最终导致程序崩溃,所以通过加上空值判断来改进代码:

public class LoggingClass {

private final User myUser;

public LoggingClass(User myUser) {

this.myUser = myUser;

}

public void logEvent(String eventName) {

if (myUser != null) {

String userEmail = myUser.getEmail();

AnalyticsClient.logEvent(eventName, userEmail);

}

}

}

这是的确是一个常见的“拆东墙补西墙”的做法。确实不会出现最初可能出现的异常,但事实上只是把问题拖到了后面,并且还出现了副作用,即我们不能正确地记录事件,这可能后续可能需要漫长的调试才能找出原因。现在来看看 Kotlin 的实现:

class LoggingClass(private val myUser: User) {

fun logEvent(eventName: String) {

val userEmail = myUser.email

AnalyticsClient.logEvent(eventName, userEmail)

}

}

在本例中,如果传递给应用程序的用户模型可能为Null,那么(在正常情况下)不可能让应用程序正常编译。编译的时候,Kotlin编译器将在这里返回一个报错,而不是在运行的时候才抛出NullPointerException。

如上所示,编译器不允许我们将可能为Null的用户传递到日志记录器中。这意味着开发人员不必担心用户对象为Null。通过保护Null值,您可以编写日志类,而不必担心用户模型的状态(是否为Null)。

那么,Kotlin是怎么让一个不能为空的值成立的呢?让我们来反编译Kotlin代码。Kotlin除了有编译时检查,还增加了运行时检查:

public LoggingClass(@NotNull User myUser) {

Intrinsics.checkParameterIsNotNull(myUser, “myUser”);

super();

this.myUser = myUser;

}

Java中,可以创建自定义的util类,进行运行时检查,并使用一些编程技巧编写一个linter来进行编译时检查。或许不需要那么麻烦,直接使用Kotlin就可以轻松且免费实现这两点。

总结

Kotlin使开发人员能够编写更少的代码,从而减少bug、节省时间和减少压力。开发人员也可以花更少的时间编写格式化代码或修复NullPointerException,以便于花更多的时间进行产品创新和为用户提供更好的体验。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180716G02B0Y00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码关注腾讯云开发者

领取腾讯云代金券