虽然最近 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,以便于花更多的时间进行产品创新和为用户提供更好的体验。
领取专属 10元无门槛券
私享最新 技术干货