从 Kotlin 开发者的角度来看,Java 缺少了什么?

从 Kotlin 开发者的角度来看,Java 缺少了什么?
文章图片
作者|NicolasFr?nkel译者|弯月出品|CSDN(ID:CSDNnews)我使用Java已近二十年了 。 几年前 , 我开始学习Kotlin 。
虽然Kotlin也会编译成JVM字节码 , 但有时候我还是要写Java 。 每当这时 , 我就会想 , 为什么Java代码不能像Kotlin那样漂亮 。 Java缺少一些关键特性 , 因此代码的可读性、表达性和可维护性都差强人意 。
这篇文章并不是要攻击Java , 只是列出了一些我希望Java拥有的功能 。
从 Kotlin 开发者的角度来看,Java 缺少了什么?
文章图片
不可变引用Java有不可变引用:
类的属性
方法的参数
局部变量
classFoo{finalObjectbar=newObject();①voidbaz(finalObjectqux){②finalvarcorge=newObject();③}}①不能给bar重新赋值
②不能给qux重新赋值
③不能给corge重新赋值
从 Kotlin 开发者的角度来看,Java 缺少了什么?】不可变引用非常有利于避免尴尬的bug 。 有意思的是 , final关键字并没有被广泛使用 , 即使是广为人知的项目也并没有使用太多final 。 例如 , Spring的GenericBean使用了不可变属性 , 但没有使用不可变方法参数 , 也没有使用不可变局部变量;slf4j的DefaultLoggingEventBuilder没有使用上述任何一种 。
尽管Java允许定义不可变引用 , 但并没有强制要求 。 默认情况下 , 引用是可变的 。 大部分Java代码都没有采用不可变引用 。
而Kotlin并没有给你选择:每个属性和局部变量都要定义为val或var 。 而且 , 方法参数不能重新赋值 。
Java的var关键字则有很大的不同 。 首先 , 它只能用于局部变量 。 更重要的是 , Java并没有相应的不可变关键字val 。 你依然需要使用final关键字 , 而很少有人这么做 。
Null安全性在Java中 , 没有办法知道某个变量是否为null 。 为了明确这一点 , Java8引入了Optional类型 。 从Java8以后 , 返回一个Optional意味着底层的值可能为null , 而返回其他类型意味着不可能为null 。
但是 , Optional的开发者只用null作为返回值 。 而方法参数和返回值在Null安全性方面并没有得到语法层面上的支持 。 为了解决这个问题 , 许多库提供了编译时注释:
从 Kotlin 开发者的角度来看,Java 缺少了什么?
文章图片
显然 , 一些库只能用于特定的IDE 。 更糟糕的是 , 这些库之间很难相互兼容 。 所以很多人都在StackOverflow上问 , 这么多的库应该使用哪个 。
最后 , 开发者必须主动使用支持Null安全性的库 。 相反 , Kotlin要求每个类型都必须是允许null或不允许null 。
valnonNullable:String=computeNonNullableString()valnullable:String?=computeNullableString()扩展函数
在Java中 , 扩展类的方法是编写子类:
classFoo{}classBarextendsBar{}子类有两个主要问题 。 首先 , 标记了final的类不允许继承 。 许多广泛应用的JDK类都是final的 , 比如String 。 其次 , 如果一个不属于方法返回了某个类型 , 那么就只能返回那个类型 , 不论其行为是否符合你的要求 。
为了解决这个问题 , Java开发者发明了工具类的概念 , 例如类型XYZ的工具类通常写作XYZUtils 。 工具类就是一堆static方法的集合 , 并且构造函数是private的 , 因此无法创建示例 。 这就相当于一个命名空间 , 因为Java不允许在类外创建方法 。
这样 , 如果一个类型不包含某个方法 , 那么工具类可以提供该方法 , 接受类型作为一个参数 , 并执行指定的行为 。
classStringUtils{①privateStringUtils(){}②staticStringcapitalize(Stringstring){③returnstring.substring(0,1).toUpperCase()+string.substring(1);④}}Stringstring=randomString();⑤StringcapitalizedString=StringUtils.capitalize(string);⑥①工具类