0%

Kotlin 和 Java 的细微差异与坑 (持续更新)

前言

Kotlin 在使用过程中和 Java 的一些细微差异及一些坑

差异

for 循环最后的值

  • java
1
2
3
4
5
6
7
8
int i = 3;
for (; i >= 0; i--) {
// 这里创造一种使整个循环退出的一种条件
if (i == 100) {
break;
}
}
System.out.println("i == " + i);

最后结果

1
i == -1

通过上述循环,我们可以知道这个 for 循环之所以结束,是因为 i 最后变成了 -1 。

  • kotlin
1
2
3
4
5
var i = 100
for (i in 3 downTo 1) {
// just test
}
println("i == $i")

最后结果

1
i == 100

可以看到,在 Kotlin 中for 循环中变量 i 的作用域仅仅在 for 循环内,外部定义的同名变量不会被覆盖,也无法影响他。因此,这种情况下 java 中某些算法,会在这种场景下失效,尤其是后续逻辑执行依赖 i 的情况下

== 和 ===

表示相等性

  • 在Java中,可以使用 == 运算符来比较基本数据类型和引用类型。如果应
    用在基本数据类型上,Java的 == 比较的是值,然而在引用类型上==比较的是引用。因此,在Java中,众所周知的实践是总是调用 equals,如果忘记了这样做当然也会导致众所周知的问题。
  • 在 Kotiin,== 运算符是比较两个对象的默认方式:本质上说它就是通过
    调用 equals来比较两个值的。因此,如果 equals在你的类中被重写了,你能够很安全地使用==来比较实例。要想进行引用比较,可以使用===运算符,
    这与Java中的==比较对象引用的效果一模一样。

不要随意改变参数类型

假设现有 Java 接口

1
2
3
4
5
6
7
8
9
```
然后在 Kotlin 中有实现

```kotlin
class SimpleProcessor : StringProcessor {
override fun proce(input: String?): String {
return "nothing"
}
}

如果用 IDE 默认帮你生成的话, 在 Kotlin 中参数 input 的可空性,默认是可以空的。但是如果你的实现中没有用到这个参数,然后你觉得这个参数空不空无所谓,把多余的问号删掉了

1
proce(input: String)

当然,如果是在 Kotlin 中调用这个方法,那么IDE 会帮你检查参数的合法性。但是在 Java 中就做不到了,假设某个调用方,传递了 null 值。

1
2
StringProcessor simple = new SimpleProcessor();
simple.proce(null);

当然这个 null 肯定不是刻意传的,但是这个情况是有可能发生的。这个时候,就会发生

1
java.lang.IllegalArgumentException: Parameter specified as non-null is null: method com.test.SimpleProcessor.proce, parameter input

即便你从来都没有用过这个参数,但是编译器对这个非空参数是做了断言的,这个时候传 null,就悲剧了。

总结

从 Java 迁移到 Kotlin 整体上是比较简单的,但任有一些差异需要我们在日常开发中注意。

加个鸡腿呗.