android studio Java项目转kotlin问题总结
起因
忙里偷闲想学一下kotlin,于是在看了一些kotlin基础以后,把项目拉了个分支,想将Java项目一步一步改成kotlin。这里记录一下自己在转换过程中遇到的问题。目前遇到的问题有如下几类:
1、崩溃问题
2、部分类Java 和kotlin api存在差异导致编译时报错。
3、其他问题
崩溃问题
其实在转换过程中最先遇到的是第二类、第三类问题。这里就不按顺序来总结了。
- java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter savedInstanceState
出现场景:将application类转换成kotlin时,运行应用时崩溃
原因分析:kotlin自带空检测,应用启动时bundle为空,所以有此问题。
错误定位:根据堆栈信息定位(非常重要)
参考链接:知乎大佬的解释
注意:崩溃时一定要仔细看堆栈信息。大多数情况下都能精确到对应行。但是,笔者这次遇到情况却发现崩溃信息指向了 unknown source,所以此时错误信息就显得尤为重要。
解决:根据错误信息自己定位出错行,发现自动转换kotlin代码中 bundle为非空值,应在变量后加“ ?”
部分类Java 和kotlin api存在差异导致编译时报错
1、类的静态方法无法找到
出现场景:将公共方法类转为kotlin后发现项目中某个方法报错。仔细查看后发现两个参数个数不同的同名方法只找到一个。一脸懵逼
原因分析:自动转换的代码中该方法缺少@JVMstatic 注解,导致无法找到。kotlin语法中 没有@jvmstatic 注解标识的方法无法成为类的静态方法,但可以使用classname.Companion.methodname()
表示
错误定位:仔细查看转换后的程序代码
解决:增加@jvmstatic 注解
2、Java和kotlin类方法参数差异(String.split
方法变更)
Java中的split
public String[] split(String regex, int limit) {
// BEGIN Android-changed: Replace custom fast-path with use of new Pattern.fastSplit method.
// Try fast splitting without allocating Pattern object
String[] fast = Pattern.fastSplit(regex, this, limit);
if (fast != null) {
return fast;
}
// END Android-changed: Replace custom fast-path with use of new Pattern.fastSplit method.
return Pattern.compile(regex).split(this, limit);
}
kotlin中的split
/**
* Splits this char sequence to a list of strings around occurrences of the specified [delimiters].
*
* @param delimiters One or more characters to be used as delimiters.
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
* @param limit The maximum number of substrings to return.
*/
public fun CharSequence.split(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): List<String> {
if (delimiters.size == 1) {
return split(delimiters[0].toString(), ignoreCase, limit)
}
return rangesDelimitedBy(delimiters, ignoreCase = ignoreCase, limit = limit).asIterable().map {
substring(it) }
}