
大概每个从 Java 或 Python 转到 Android 开发的人都经历过这么一幕照着教程用 Android Studio 新建了一个项目顺手写了个 Kotlin 文件里面就一个 main 函数想在 IDE 里单独跑一下验证点语法结果右键菜单里死活找不到 Run 这一项。我当年第一次遇到这个问题时也愣了半天网上搜了一圈答案也是各种绕有的说要装命令行工具有的说要新建 IntelliJ 项目没有一个能直接在 Android Studio 里解决的。这篇就来把这个问题彻底说透。我会先讲清楚为什么 Android Studio 默认不给 Kotlin 单文件提供运行入口然后给出一个最实用的解法在 Android Studio 里新建一个纯 JVM 模块当作“运行沙箱”让单个 Kotlin 文件像在 IntelliJ 里一样直接跑 main 函数。顺带也会介绍 Kotlin REPL、命令行编译这两个备用方案最后把常见报错和排查思路整理成清单。适合刚开始学 Kotlin、用 Android Studio 但不想每次验证语法都建一个完整 Android 项目的人也适合想把 Android Studio 当成普通 JVM 开发工具用的朋友。1. 为什么 Android Studio 不能直接“运行”一个 Kotlin 文件1.1 根本原因AS 的运行模型和模块强绑定要搞明白为什么不显示 Run得先理解 Android Studio 的运行模型。它虽然是 IDE但背后是 Gradle 在驱动一切。IDE 不是简单地把当前打开的文件丢给编译器而是先判断这个文件属于哪个 Gradle 模块再用这个模块的依赖、代码路径、编译配置去生成一个可运行的入口。当你右键一个文件时IDE 会做两件事第一判断这个文件是否在某个模块的 source 目录里第二扫描文件内容里有没有可作为入口的方法。Android 项目默认只有两个模块app 模块Android Application和根项目本身。app 模块的入口由 AndroidManifest 里的 Activity 或 Application 决定不是普通 Java/Kotlin 里的 main。所以就算你在 app/src/main/java 下放了一个带 main 函数的 Kotlin 文件AS 也经常不显示 Run 入口即便显示了跑起来也会先触发 Android Gradle Plugin 的一堆任务又慢又容易出错。还有一个很多人不知道的细节如果你直接新建一个 .kt 文件但它没有落在任何一个模块的 source set 里比如被放在项目根目录或者随便一个文件夹这个文件对 Gradle 来说根本不存在IDE 自然无法编译运行。我说的“没有 Run”大部分情况就是这么来的。1.2 Java/Kotlin 模块和 Android 模块的差别Android 模块和纯 JVM 模块在编译和运行层面有本质区别。Android 模块需要 Android SDK编译时要做资源打包、Manifest 合并、Dex 转换、签名等一系列操作。它运行时的宿主是 Android 系统没有 Activity 生命周期就没有入口。而纯 Java/Kotlin 模块只依赖 JDK编译产物就是普通的 .class 文件或 jar 包运行入口就是标准的 main 函数。在 Android Studio 里新建一个 Java Library 或 Kotlin Library 模块等于给 Kotlin 文件一个“合法身份”。它不依赖 Android SDKGradle 同步一次之后增量编译非常快单文件运行基本一两秒就出结果你还可以正常打断点、看变量、用调试器体验和完整项目几乎一样。1.3 一个容易混淆的概念Kotlin 不是只能在 Android 里跑很多刚开始接触 Android 的人有个错觉觉得 Kotlin 是“Android 专用语言”。其实 Kotlin 是一门基于 JVM 的通用语言它和 Java 一样先编译成 .class 字节码再在 JVM 上运行。Google 只是把 Kotlin 定为 Android 官方推荐语言但 Kotlin 在服务端、桌面端、脚本领域都很常见。所以这里的关键认知是在 Android Studio 里运行单个 Kotlin 文件本质上是“用 Kotlin 编译器编译它并交给 JVM 执行”跟 Android 运行时没有关系。理解这一点后答案就很清晰了你需要的不是一个 Android 应用模块而是一个纯 JVM 模块。2. 最实用的方案在 AS 里新建“沙箱模块”来运行单文件2.1 为什么选 Java Library 而不是 Android Library有人会问新建模块的时候为什么选 Java Library而不是 Android Library因为我们要运行的代码不需要 Android 环境而 Android Library 模块会默认被 Android Gradle Plugin 接管要求配置 compileSdk、minSdk还会触发资源合并等任务。对于一个只想验证 5 行 Kotlin 语法的人来说这些开销完全是多余的。选 Java Library新版本里叫 Java or Kotlin Library有两个好处一是模块类型最轻编译链路短二是它天然不依赖 Android SDK在配置较低的老电脑上也能快速同步。很多练习代码用到的 Kotlin 标准库、集合操作、IO、协程在这个模块里都能直接跑。你需要做的只是手动给这个模块加上 Kotlin 插件因为 Android Studio 的模板不会默认帮你加。2.2 完整操作步骤老版本和新版本的向导怎么填先讲经典做法这套在 Android Studio 4.x、2021 到 2023 的版本上都适用。打开项目后按顺序操作菜单栏点击 File - New - New Module。在弹出的窗口左侧选择 Java Library有的版本显示为 Java or Kotlin Library。右侧的 Module name 填一个专门用于练习的名字比如 kotlin-sandbox 或 kotlin-practice。包名可以随便填建议写 com.example.sandbox 这种和主项目不冲突的。点 Finish等待 Gradle sync 完成。打开新模块的 build.gradle在 plugins 块里追加 Kotlin JVM 插件。新版 Android Studio比如 Koala、Ladybug 之后的版本菜单布局有些调整。File - New - New Module 还是老位置但模块类型列表里可能会直接出现 Java or Kotlin Library语言选项里有 Java 和 Kotlin 两个下拉选项。如果选了 Kotlin向导会自动帮你加 Kotlin 插件省一步如果没有这个选项选 Java Library 也没关系后面手动加插件就行效果完全一样。这里有个容易踩的点新模块生成后build.gradle 里的 plugins 块通常只有 java-library 这一行。你需要把它改成plugins { id java-library id org.jetbrains.kotlin.jvm }改完之后Android Studio 右上角会弹出 Sync Now点击同步。如果不点后面运行的时候会报各种“找不到 Kotlin 编译器”之类的错。2.3 build.gradle 里的关键配置一次讲清同步完成后打开该模块的 build.gradle正常情况下内容类似plugins { id java-library id org.jetbrains.kotlin.jvm } java { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } kotlin { jvmToolchain(17) } dependencies { implementation org.jetbrains.kotlin:kotlin-stdlib }这几个配置分别是什么意思java 块里的 sourceCompatibility 和 targetCompatibility 指定编译用的 Java 版本用你本机 JDK 主版本就好。Android Studio 新版内置的 JDK 一般是 17所以填 17 通常没问题如果老项目用的 JDK 8可以改成 VERSION_1_8。kotlin 块里的 jvmToolchain(17) 是告诉 Kotlin 编译器也用同样的 JDK 版本保持两边一致能避免很多莫名其妙的报错。dependencies 里的 kotlin-stdlib 是 Kotlin 标准库。实际上 Kotlin JVM 插件会自动引入标准库这行不写通常也能跑但显式写出来更保险尤其在你后面要引入协程等依赖时至少知道这个模块的依赖体系是完整的。需要注意的是Kotlin 插件本身不需要在模块的 build.gradle 里写版本号版本号由根项目的 build.gradle 统一管理。如果你打开根项目根部的 build.gradle会看到 plugins 块里有一行类似 id org.jetbrains.kotlin.android version 1.9.24 apply false 的配置新加模块时你还要手动补一行 kotlin.jvm 的插件声明吗其实不需要。Android Studio 会自动为新增的 Java/Kotlin Library 模块匹配一个可用的 Kotlin 版本。只有在极老版本或手动修改过根配置的项目中才需要手动加遇到再处理不迟。2.4 让 main 函数跑起来运行入口和 Run Configuration模块建好、配置同步完成之后接下来就是新建一个 Kotlin 文件了。在左侧 Project 面板里展开新模块的 src/main/java 目录右键 - New - Kotlin File/Class文件名随便取一个比如 Main。如果右键菜单里没有 Kotlin File/Class说明当前项目里 Kotlin 插件没有正常工作去 Preferences/Settings 的 Plugin 市场确认 Kotlin 插件已安装并启用也可以直接右键 - New - File手动输入 Main.kt效果一样。在文件里写最标准的顶层 main 函数fun main() { val message hello from kotlin println(message) }写完之后在代码区任意位置右键或者在左侧行号栏找绿色三角形图标点 Run MainKt控制台就会开始构建并执行。第一次跑可能稍慢之后因为 Gradle 有增量编译基本就是秒开。顺便说一下 Run MainKt 这个名字的来历。Kotlin 编译时会把文件名转成类名Main.kt 编译后对应的类就是 MainKtmain 函数是这个类的静态方法。这个知识在你想引用顶层函数的时候很有用比如在同一个包的其他文件里调用这个 main要用 MainKt.main() 这种语法。现在不理解也没关系先知道右键菜单上那个带 Kt 后缀的选项就是当前文件就行。如果要给 main 传递命令行参数可以写成fun main(args: ArrayString) { args.forEachIndexed { index, arg - println(arg[$index] $arg) } }然后在菜单栏 Run - Edit Configurations 里选中刚才自动生成的 MainKt 配置在 Program arguments 一栏填入参数比如 a b c再点运行就能在控制台看到输出。这种方式在验证一些字符串处理或算法逻辑时非常方便。3. 两个备用手段Kotlin REPL 和命令行编译3.1 IDE 内置 Kotlin REPL适合一行式验证有时候你只想快速验证一个表达式比如某个字符串 API 怎么用、某个集合转换的结果是什么不想新建文件、不想跑整个编译流程这时候 Kotlin REPL 是个不错的选择。打开路径是 Tools - Kotlin - Kotlin REPL。它会弹出一个交互式面板输入代码按回车就能立即看到结果。比如你输入 listOf(1, 2, 3).map { it * 2 }它会立刻输出 [2, 4, 6]。这对学习集合操作、练习 lambda 表达式非常友好不需要任何工程环境。但 REPL 的局限性也很明显它不适合定义多个类、多行逻辑或者有依赖的代码。它的运行环境默认只是项目当前的 classpath如果你在某个模块里写了一个自定义类想在 REPL 里 import 进来使用经常会出现找不到类的报错。此外 REPL 里没法打断点、没法调试本质上只是个语法实验壳子。所以我把它定位成“一行式验证工具”而不是正式的练习环境。3.2 用 kotlinc 在命令行编译运行摆脱 IDE 依赖如果你不想开 IDE或者所在的机器上没有安装 Android Studio也可以直接用 Kotlin 官方命令行编译器。安装方式不多啰嗦常见的是 macOS 上用 brew install kotlinWindows 上可以用 winget install --idJetBrains.Kotlin 或通过 SDKMAN 安装Linux 用 SDKMAN 最省事。安装完成后在终端里写一个 Hello.ktfun main() { println(hello from command line) }然后执行kotlinc Hello.kt -include-runtime -d hello.jar java -jar hello.jar第一行命令是编译-include-runtime 的意思是把 Kotlin 标准库一起打进 hello.jar这样生成的 jar 可以直接用 java -jar 运行如果不加这个参数运行 java -jar 时会报找不到 kotlin 标准库的错。第二行就是正常执行 jar 包。命令行方案适合自动化脚本、CI 验证、或者只是想在终端里快速跑一段代码的场合。缺点是没有 IDE 的断点调试和代码提示遇到复杂一点的逻辑排查起来比较费劲。我个人建议还是优先用模块法命令行方案作为补充知识了解即可。3.3 三个方案怎么选场景对比表使用场景推荐方案优点缺点学习 Kotlin跑完整 main 逻辑模块沙箱法可调试、编译快、接近真实项目体验需要先配置一次模块验证一行表达式、看 API 返回Kotlin REPL零成本、立刻出结果不能调试、依赖项目 classpath服务器/CI/临时脚本环境kotlinc 命令行不依赖 IDE、可写入流水线无调试工具、语法提示弱你最初的诉求是“在 Android Studio 里单独编译运行一个 Kotlin 文件”最贴合这个诉求的就是模块沙箱法。我建议先照着第 2 节把沙箱模块搭好以后所有语法练习、算法测试都往里面放REPL 和命令行只作为特殊情况下的补充。4. 常见坑位与排查记录4.1 右键怎么都没有 Run从三个维度检查这是出现频率最高的问题。如果右键文件后看不到 Run依次检查这三件事第一文件是否真的在模块的 source 目录下。这个最容易被忽略。新建模块后默认代码目录是 src/main/java你的 .kt 文件必须放在这个目录里或它的子包下。如果你把 .kt 文件放到了模块根目录比如 kotlin-sandbox/Test.ktIDE 识别不到右键不可能有 Run。第二是否有顶层 main 函数。Kotlin 的运行入口必须是顶层函数 fun main() 或 fun main(args: Array )加 fun main() 在 class 里面是不行的。有些教程演示 Java 转 Kotlin 时会在类里写 companion object JvmStatic fun main那种写法在经典 Java 环境里可用但容易把新手绕晕建议直接用顶层函数。第三Gradle 同步是否完成。新增模块、修改 build.gradle 后都要等 Gradle sync 结束状态栏没有报错IDE 才会扫描出新模块的代码结构。同步没完就去点文件很可能没有 Run 菜单。动手前先看一眼窗口右下角的进度条转完了再操作。如果以上三个都没问题还有个细节新增 main 函数后IDE 需要一点点时间刷新运行配置。稍等几秒或者点击一下同步按钮再右键入口一般就会出现。4.2 运行时报错 Module not specified这个报错通常出现在手动创建的 Gradle 配置有问题或者 IDE 的模块缓存没更新的时候。解决办法先点菜单 Build - Make Project 强制编译一遍然后 File - Sync Project with Gradle Files。如果还是不行打开右侧 Gradle 面板在对应模块下点刷新按钮。这套组合拳能解决 90% 以上的模块识别问题。我自己还遇到过一种比较隐蔽的情况settings.gradle 里新模块的 include 路径写错了。正常情况下 IDE 会自动生成 include :kotlin-sandbox但如果你手动改过 settings.gradle就把新模块的 include 行删了或者写成了别的名字Gradle 能同步但 IDE 一直提示 Module not specified。检查一下 settings.gradle确保模块名和文件目录对应。4.3 Kotlin 版本和 JDK 版本不匹配如果你在低版本 Android Studio 上装了新项目的 Kotlin 插件或者反过来很容易遇到编译错误常见提示包括 Unsupported class file major version、Unsupported Kotlin plugin version、Kotlin 编译器版本与 Gradle 版本冲突等。这类问题的根源是 Kotlin、Gradle、JDK 三者版本需要互相兼容。Kotlin 2.0 要求 JDK 8 及以上可以运行但 Gradle 本身对 JDK 版本有要求Android Studio 的新版内置 JDK 17老项目如果用的 Gradle 6.x就可能在同步阶段报错。遇到版本冲突最省事的做法是升级 Android Studio 到较新版本让内置 Gradle 和 Kotlin 版本保持默认一致如果项目本来就是老项目就别在老的 Android Studio 里强行用新语法优先保证能跑通。4.4 中文输出乱码的问题在 Android Studio 内置控制台里Gradle 默认以 UTF-8 编码一般不会乱码。但如果你用命令行 kotlinc/java 跑在 Windows 的 cmd 或 PowerShell 里很容易出现中文乱码因为系统默认编码是 GBK。解决办法编译时给 Kotlin 编译器传编码参数运行时也指定文件编码。编译命令可以加上 -J-Dfile.encodingUTF-8kotlinc -J-Dfile.encodingUTF-8 Hello.kt -include-runtime -d hello.jar运行时带上文件编码参数java -Dfile.encodingUTF-8 -jar hello.jar这样输出和源码里的中文都能正常显示。如果你是在 PowerShell 里跑还可以先执行 chcp 65001 把当前控制台代码页切到 UTF-8再运行 java 命令效果一样。4.5 想运行包含 Android API 的代码怎么办这是另一个高频困惑。比如你想验证 SharedPreferences 存取值、想跑一下 Toast 相关逻辑在纯 JVM 沙箱模块里是跑不起来的因为这些 API 依赖 Android 运行环境普通 JVM 根本没有这些类。这种情况要分两种处理。第一种逻辑本身不依赖 Android 环境只是误用了 Android API那就把代码改造成普通 Kotlin 代码比如用 map 代替 SharedPreferences 做临时存储。第二种确实需要 Android API 环境建议在 app 模块里写单元测试或插桩测试不要强行用沙箱模块。单元测试在 JVM 上运行使用 Robolectric 等框架可以模拟 Android 环境勉强能测 SharedPreferences 之类的东西插桩测试则需要模拟器或真机代价更高。这个知识点不属于本文范围先知道方向后面需要时再深入了解。4.6 快速排查速查表现象可能原因解决动作右键没有 Run文件不在 source root将 .kt 文件移动到 src/main/java 下右键没有 Run没有顶层 main 函数检查 main 是否在文件最外层右键没有 RunGradle 未同步等待同步完成重新 sync运行报错 Module not specified模块配置异常Build - Make Project 后重新 sync编译报错 Unsupported class fileJDK / Gradle / Kotlin 版本不匹配升级 Android Studio 或调整 JDK中文输出乱码命令行编码不是 UTF-8加 -Dfile.encodingUTF-8 参数想跑 Android API纯 JVM 环境不支持改单元测试 / 插桩测试5. 一些实操后的心得和建议这套“模块沙箱法”我现在还在用。每开一个新项目我第一件事就是顺手加一个 kotlin-sandbox 模块专门用来跑临时想法、算法题和依赖验证。好处是主项目的 app 模块不会被练习代码污染lint 检查、打包速度都不受影响。时间久了这个沙箱模块就像你的私人草稿纸打开就能写写完就跑不用等 Android 编译那几十秒。一个小技巧在沙箱模块里可以顺手建一个 src/test/java 目录把验证逻辑写成 JUnit 测试方法然后用 CtrlShiftF10 运行单个测试方法。相比 main 函数JUnit 的方式能直接断言结果、失败时看红绿条更适合验证一串输入输出关系。配合 Android Studio 的测试模板也就多一个依赖的事。最后想说的是别被 IDE 的表面操作困住。Android Studio 跑 Kotlin 单文件这件事剥开看就是三个点Kotlin 编译成字节码在 JVM 上跑、Gradle 模块是代码的容器、顶层 main 是运行入口。这三句话想明白以后换 IntelliJ、换命令行、换 CI 构建你都能触类旁通。现在先照着沙箱模块的方法建一个跑通第一个 Kotlin 文件后面学什么都会顺手很多。