68 lines
5.9 KiB
Markdown
68 lines
5.9 KiB
Markdown
---
|
||
title: Kotlin中“Unresolved reference”的解决经验
|
||
date: 2021-04-10 17:56:04
|
||
tags: [JVM, Kotlin, Unresolved reference, Exception, Error]
|
||
categories:
|
||
- [JVM, Kotlin]
|
||
---
|
||
在Kotlin的使用过程中常常会出现“Unresolved reference: XXX”的错误,这个错误的出现归根结底是Kotlin编译器没有找到代码中所使用的库、类或者方法。<!--more-->出现这个错误的时候请不要慌张,也不要尝试去寻找编译器所给出的具体提示,在多次解决这个问题的过程中,已经有很多经验表明,Kotlin编译器甚至是Gradle等构建工具所给出的错误提示和栈跟踪信息,都没什么卵用。
|
||
|
||
Kotlin是一门JVM语言,可以自由的调用Java中的所有库功能,这虽然为Kotlin的使用提供了极大的便利,但是也增加了Kotlin在使用的时候配置功能的复杂性。
|
||
|
||
从网上的许多博客和帖子中搜到的解决方案基本上都是针对Android开发过程中遇到的这个问题,而且这个问题的确也是在使用Gradle构建时常常发生的,而且在使用IntelliJ IDEA开发的时候出现的可能会更加频繁一些。但是出现“Unresolved Reference”问题在大部分情况下与IDE无关,但是有可能与IDE中的设置有关。
|
||
|
||
> 不代表使用Maven就可以偷着乐了,Maven一样会出现这个问题。
|
||
|
||
## 配置,一切都是配置的错
|
||
|
||
当运行`./gradlew run`或者在IntelliJ IDEA中点击Run看到“Unresolved reference”以后,你的第一反应一定是:“我X,我代码里少写啥了。”但是,亲,这个错误真不是你代码里少写什么了,而是你的项目配置和项目构建文件里少写啥了,或者写错啥了。
|
||
|
||
### JDK版本配置错误
|
||
|
||
在使用Gradle构建Kotlin JVM项目的时候,你所面临的JDK设置实际上有两个:一个是系统中的`JAVA_HOME`,一个是`build.grade`中的`kotlinOptions.jvmTarget`,而如果在IntelliJ IDEA中使用Gradle,IDE针对Gradle运行环境的配置也会产生影响,但是这个影响基本上与在系统中设置`JAVA_HOME`的效果差不多。
|
||
|
||
先来看一个编译示例。
|
||
|
||
{% oss_image kotlin-unresolve-reference/error-prompt.png CAEQDxiBgIDvldfdyRciIDZiZGVmMDIzMjZhODQwZDRhOTViMGRjNzg3ZDc1ODcz 编译示例 450 %}
|
||
|
||
一个项目在使用`./gradlew run`构建运行的时候报出了`Unresovled reference: readString`错误。这个`readString`是调用的`java.nio.file.Files.readString()`方法。可是为什么会报这个方法没有找到呢?先来看一下这个方法的文档信息。
|
||
|
||
{% oss_image kotlin-unresolve-reference/file-docs.png CAEQDxiBgMDMlNfdyRciIGZlM2M5OTY3NTQ0NzRhZTNiMmY2N2FmNGVhYjcyYTdk 文档信息 450 %}
|
||
|
||
好吧,有点儿长,但是似乎看不出什么端倪来。这里要注意了,这个方法是在Java 11引入的,那我们来看看项目的构建配置。
|
||
|
||
{% oss_image kotlin-unresolve-reference/gradle-file.png CAEQDxiBgMDSk9fdyRciIGIyMGExYWE5YWVmYzRiZjVhYzM2ZGVlMTI1OTI0ZjIw Gradle构建配置 300 %}
|
||
|
||
Kotlin的编译目标看起来也没有什么问题,同样是面向Java 11编译的,理论上使用这个新引入的方法完全没有问题。那么,再来看看IDE中的项目配置。
|
||
|
||
{% oss_image kotlin-unresolve-reference/ide-setting.png CAEQDxiBgMDXk9fdyRciIDkyZGMwODRmYjJiMjQyYjBhMTZhZDQyZGI2Mzc4ZWY5 IDE项目配置 450 %}
|
||
|
||
好,项目配置这里依旧没有问题。那么Gradle构建Kotlin项目所所涉及到的两个JDK版本问题就已经确认了一个了。那么我们来看另一个JDK配置。
|
||
|
||
{% oss_image kotlin-unresolve-reference/system-setting.png CAEQDxiBgMCLlNfdyRciIDQxYzZmMTA1MGU5NTQzMzI5YmNlN2Q3ZmNhODkwOTc0 系统JDK 450 %}
|
||
|
||
呃,好吧,我机器上的Java是通过SDKMan安装的,这里安利一下,真的很好用,Windows用户就暂时不要想了。不过`JAVA_HOME`也是Java 11,这就尴尬了好不。不过不用急,能够影响Gradle所使用的JVM的还有一处位置,那就是用户家目录下的`.gradle`目录,这是Gradle保存全局配置的目录,这个目录里有一个用于配置Gradle的`gradle.properties`文件。
|
||
|
||
{% oss_image kotlin-unresolve-reference/gradle-setting.png CAEQDxiBgICBltfdyRciIGNkYWQwMWRjMWQ3NjQ3ZjJiNDQ3YjY5M2ZiNDZkY2I0 'Gradle JDK' 500 %}
|
||
|
||
看起来我们似乎找到了问题的源头,Gradle没有在使用环境变量中配置的`JAVA_HOME`,而是使用了`.gradle/grade.properties`中另行指定的JDK目录。那么修改它一下试试。
|
||
|
||
{% oss_image kotlin-unresolve-reference/gradle-setting-modified.png CAEQDxiBgMCHlNfdyRciIDI4OGIxYjZjYjIxODQxZjU5MWMxNzllNjlkOTlmODhh 'Gradle JDK 修改后' 500 %}
|
||
|
||
现在我们再来试一下吧。
|
||
|
||
{% oss_image kotlin-unresolve-reference/second-test-run.png CAEQDxiBgID7ldfdyRciIGEzYmUwNjk5MmJiYzQ3NjM5MzhlZmMyOTgxYmE4MzA4 第二次实验运行 350 %}
|
||
|
||
呃,看起来依旧好尴尬,问题依旧。那么能够配置Gradle所使用的JVM的位置还有没有呢?这个位置还真的还有一个,那就是IDE中的配置。
|
||
|
||
{% oss_image kotlin-unresolve-reference/ide-gradle-setting.png CAEQDxiBgMDXk9fdyRciIDkyZGMwODRmYjJiMjQyYjBhMTZhZDQyZGI2Mzc4ZWY5 修改IDE中的Gradle配置 450 %}
|
||
|
||
IDE中配置Gradle使用的是Java 8,那么把这里也修改成Java 11试试看。
|
||
|
||
{% oss_image kotlin-unresolve-reference/third-test-run.png CAEQDxiBgIDLk9fdyRciIGQyMDJiZDNkY2RmYjRlNDFiZjFiOGQzOWMyOTYzYjJi 成功运行 350 %}
|
||
|
||
至此,由于Gradle所使用的JVM配置错误而导致Kotlin发生“Unresolved reference”的问题已经全部解决。这个问题是由于Gradle使用的JVM是Java 8,其中并不带有项目中所使用的Java 11的内容,而Gradle所使用的JVM又是项目编译所要使用的JVM,这就导致了Kotlin报出“Unresolved reference”错误。
|
||
|
||
> 如果使用高版本的JVM来编译使用低版本JDK的项目,也同样可能会出现这个问题,此时就要注意项目中是否使用了已经被高版本JVM废弃的内容。编译项目所使用的JVM版本尽量要与项目所依赖的JDK版本相同。
|
||
|