
做Android开发的老哥十有八九都遇到过这种场景临时想验证一段Kotlin语法跑一个算法思路或者试试正则能不能匹配上结果要么拿模拟器开整个App要么新建一个Android项目光等Gradle构建就得喝两三杯水。尤其是有时候只是想测试一个字符串处理函数、想看看某个API返回值格式硬塞进正式工程里又嫌污染代码放到线上模块里又不敢乱动。折腾到最后验证一个函数比写这个函数还费劲。这篇就来解决这个问题专门讲怎么在Android Studio里单独编译运行一个Kotlin文件。不需要新建Android项目不需要连接真机不用等模拟器开机也不用碰AndroidManifest和资源文件。跑通之后你会发现日常写代码时验证逻辑的效率提升不是一星半点。全文不涉及编译原理的深水区主要把Android构建链路和纯JVM运行环境的区别讲透再给出一套能直接下手的操作流程。不管是Android开发者、Kotlin新手还是被Gradle同步折磨到想摔键盘的朋友都能照着做。1. 先搞清楚为什么Android项目不能直接右键Run Kotlin文件很多新手第一次尝试时都会愣住我在Android Studio里写了一个Kotlin文件里面明明有fun main()右键却找不到Run选项或者点了Run之后报错提示找不到主类。这不是你操作姿势不对而是Android项目的构建逻辑和普通JVM项目压根就不一样。1.1 你迟早会遇到这些“只想跑个函数”的瞬间先聊场景。我梳理了一下平时最容易触发这个需求的情况看看你中了几条刷算法题或做Kotlin面试题时想本地跑几个测试用例验证函数输出是否符合预期。热搜词里那堆“kotlin面试题”“kotlin string.format()”就是这个路子的产物。做SharedPreferences封装时想验证数据拼接、默认值解析、类型转换这些中间过程是否正确。直接在本地跑Kotlin文件比在真机上看Logcat快太多而且能精确控制输入输出。调试正则表达式、日期格式化、字符串模板这类纯逻辑代码。每次改完正则都重新启动一个App去验证效率低到无语。测试第三方开源库的API用法。比如想知道某个库的某个方法到底怎么调、返回什么结构在本地写个main函数跑一遍比翻源码猜来猜去直观多了。这种场景的共同特点是代码不依赖Android上下文不需要Context不需要Activity只需要一个能运行的入口和一段代码执行环境。说白了它们就是普通的JVM程序。1.2 Android项目的构建链路和“普通JVM程序”有什么不同要理解为什么不能直接右键Run得知道Android项目在Gradle里到底走了什么流程。一个标准的Android App模块apply的是com.android.application插件。这个插件会让Gradle走Android的编译打包链路Kotlin代码先编译成class文件然后和AndroidManifest.xml、res资源、Android SDK提供的类库打包成一个完整的APK。注意这里面的目标产物是“能在Android设备上运行的应用”而不是“能在电脑上跑起来的独立程序”。右键一个Kotlin文件点RunIDE做的事情是寻找一个带main入口函数的类然后按JVM的方式启动它。但在Android模块里启动一个App的入口是AndroidManifest中指定的Activity不是某个fun main()。就算你的Kotlin文件里写了fun main()IDE也未必把它识别成“可运行目标”因为整个模块的构建配置压根就没有提供JVM Application的运行方式。强行运行要么Run按钮置灰要么跑起来之后直接被Android Gradle Plugin的检查拦下来。另外还有个坑Android模块的编译依赖里包含android.jar这个桩包里面的Activity、Context这些类只有方法签名没有真实实现运行时才由设备系统提供。所以你没法在电脑上直接运行一个依赖这些类的代码一跑就崩。1.3 解决方案的核心思路给Kotlin一个“非Android”的JVM容器既然Android模块不适合直接跑Kotlin文件那就反过来给这个Kotlin文件找一个基于纯JVM的环境。只要不依赖Android SDK的代码在JVM环境下就能像普通Java程序一样编译和运行。最简单可靠的方式就是在现有Android工程里新建一个Java Library模块。这个模块本质上是纯JVM项目不挂com.android.application插件Gradle同步后IDE会把它当成普通Java/Kotlin模块处理。模块里的Kotlin文件只要有main函数右键就能出现Run选项运行过程直接走本地JVM几秒钟出结果。思路就是这么简单。剩下的问题只是操作步骤的细节以及一些常见的坑。下面我会把不同方案对比一遍再给出完整实操流程。2. 方案选型四种常见跑法优缺点一眼看懂在动手之前我建议你先想清楚自己到底需要哪种方式。不同场景适合不同方案选错了容易绕弯路。2.1 方案A在现有工程里新建Java Library模块这是我最推荐的方式也是后文实操部分的主角。它的核心优势是不离开Android Studio不影响现有Android代码而且模块可以长期保留当作你的代码草稿箱。具体好处有三个依赖管理无缝衔接。Android项目里Gradle还常崩溃没关系新模块和你正式模块在同一个工程里反正都要同步本地库用Maven本地仓库或阿里云镜像速度不慢。可以在模块里自由引入第三方库。比如你想验证Gson的某个序列化特性直接在模块的build.gradle里加一行依赖就能在Kotlin文件里import并使用验证完再决定要不要挪到正式代码里。不参与APK打包放心折腾。Java Library模块默认不会进入App的发布产物除非你手动把它加为依赖。所以里面写多少临时测试代码都不怕污染线上工程。缺点也很明显新模块会增加Gradle配置和同步时间如果项目本身已经很大多同步一个模块还是会拖慢一点整体构建速度。不过这点成本比起直接起模拟器来简直可以忽略。2.2 方案B单独装一个IDEA Community如果只是单纯学Kotlin、不想碰Android环境那就没必要用Android Studio装一个IntelliJ IDEA社区版就行。IDEA社区版免费创建Kotlin项目后配置一个JDK就能直接运行Kotlin文件。它对纯Kotlin/JVM开发的支持比Android Studio更干净因为Android Studio本身就是在IDEA基础上加了一堆Android插件的定制版干纯JVM的活反而拖沓。这个方案适合刚开始学Kotlin语法、刷Kotlin题目、写纯逻辑小工具的人。但如果你已经是Android开发者电脑上已经装了Android Studio再装一个IDEA有点占硬盘而且维护两套IDE环境也挺麻烦。2.3 方案C命令行kotlinc如果你习惯了命令行操作也可以安装Kotlin编译器直接在终端里编译并运行Kotlin文件。流程是先安装kotlinc然后把.kt文件编译成jar包再通过java -jar运行。这种方式适合脚本化、批量化操作比如写个自动化脚本跑一堆Kotlin测试文件。但说实话日常开发里大多数人还是习惯可视化操作命令行方式没有IDE的断点调试、变量监视这些功能调试体验差很多。而且初始配置Kotlin编译器本身又是一道门槛新手用起来容易劝退。2.4 方案D在线PlaygroundKotlin官方有一个在线编译器也就是Kotlin Playground网页上写完代码直接点运行不需要在本地装任何东西。这个方案最适合“突然想试一下某个语法点”的临时场景比如Kotlin的let、also、run区别随手在网页里敲几行验证一下就走。缺点是无法引入本地依赖不方便加载你工程里的类也没法做文件IO、网络请求这类需要本机环境的操作。所以它只能当应急工具不能替代本地方案。2.5 选型总结表格方案操作难度依赖引入调试能力适用场景现有工程新建Java Library模块低支持支持断点调试Android开发日常验证IntelliJ IDEA Community低支持支持断点调试纯Kotlin学习与写小项目命令行kotlinc中手动管理不支持脚本化、批量编译运行在线Playground极低不支持不支持临时验证语法如果你本身就在做Android开发同时又不想切换工具那方案A是唯一能满足“不离开Android Studio、又能快速跑Kotlin文件”的组合。下面进入实操。3. 完整实操在Android Studio里新建模块并运行Kotlin文件这部分我会把每一步都写清楚包括点哪个菜单、填什么内容、代码怎么写、右键选哪个。照着做基本不会踩坑。3.1 新建Java Library模块的详细步骤打开你的Android工程点击顶部菜单File - New - New Module。在弹出的面板里左侧选择Java Library。注意不是Android Library这两者的区别很大Android Library会创建一个依赖Android SDK的模块而Java Library是纯Java项目的形态。接着填写模块信息Library name建议填devrunner或者kotlinrunner。我习惯用devrunner含义是“开发期运行草稿”。Package name填一个包名比如com.example.devrunner。这一步不是强制但建议填上方便管理。Java class name这里留空就行。如果你填了MainIDE会默认生成一个Main.java文件但我们是跑Kotlin的这个Java文件后面还得删。点击Finish后Android Studio会开始Gradle同步。同步完成后在Project窗口里就能看到新模块默认目录结构是src/main/java。如果模块自动生成了Main.java先右键删掉避免后面混淆。如果你在模块的build.gradle里看到的是plugins { id java-library }说明模块创建成功。但这时模块还不支持Kotlin编译需要手工加上Kotlin插件这是很多人漏掉的一步。打开新模块的build.gradle初始内容大概是plugins { id java-library } java { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 }改成下面这样plugins { id java-library id org.jetbrains.kotlin.jvm } java { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 }改完右上角会弹出一个Sync Now的提示点击同步。如果项目里Kotlin插件的版本已经是统一管理这一步不会报错如果提示org.jetbrains.kotlin.jvm版本缺失你需要检查工程根目录build.gradle里的Kotlin插件版本声明。多数情况下Android项目根目录已经有Kotlin插件配置新模块直接引用即可。3.2 编写Kotlin入口fun main的写法与要求现在开始写Kotlin文件。在devrunner模块的src/main/java目录上右键选择New - Kotlin File/Class文件名填TestMainKind选择File。注意File和Class的区别Class会创建一个空类适合声明类型我们要的是能直接运行的入口文件用File会生成顶层函数的文件更贴近脚本感。文件里写一段最基础的代码fun main() { println(Hello from Kotlin Runner) val numbers listOf(1, 2, 3, 4, 5) println(numbers.map { it * 2 }) }Kotlin的main函数可以带参数也可以不带。在JVM环境下fun main(args: ArrayString)和fun main()都是合法的入口。IDE识别入口的条件是文件里存在顶层main函数这是唯一的硬性要求。至于函数放在文件顶部、底部还是中间都不能影响被识别。如果你愿意也可以提前定义一个比较复杂的功能来测试。比如写一个计算斐波那契数列的函数然后在main里调用fun fibonacci(n: Int): Int { if (n 1) return n return fibonacci(n - 1) fibonacci(n - 2) } fun main() { println(fibonacci(10)) }这一步相当于把你的验证代码放在main函数里跑完直接看输出。3.3 右键运行与运行配置手动调整代码写完右键点击文件在弹出的菜单里找Run TestMainKt。注意类名是TestMainKt不是TestMain。Kotlin编译器会把顶层函数文件的字节码类名自动改成“文件名Kt”这是Kotlin/JVM的规则IDE的右键菜单会直接显示这个类名你只要认准文件名就行。点击之后IDE会执行Gradle构建并运行该类。如果一切正常底部Run窗口会显示Hello from Kotlin Runner [2, 4, 6, 8, 10] Process finished with exit code 0每次运行都需要等Gradle增量构建第一次大约十几秒后面基本几秒内完成。如果右键之后没有出现Run菜单或者只有十几个灰色选项不要慌多半是IDE还没识别到这个模块是“可运行的JVM模块”。处理方式分三步排查确认新模块目录里src/main/java被标记为蓝色源根目录。在项目窗口里如果看到的是普通文件夹图标右键该目录选择Mark Directory as - Sources Root。打开Gradle工具窗口点击刷新按钮触发同步让IDE重新加载模块信息。确认模块build.gradle里已经加入了org.jetbrains.kotlin.jvm插件这一步漏掉的话IDE根本不会把Kotlin文件识别成可编译源码。如果你想手动配置运行环境可以打开Run - Edit Configurations点击左上角号选择Kotlin。在Main class栏填TestMainKtWorking directory填模块根目录其他默认即可。这种手动配置一般用不到除非右键菜单失效或你需要给运行环境加JVM参数。3.4 在模块里引入第三方依赖很多时候单独跑Kotlin文件不只是为了跑标准库还要测第三方库。比如你想试试Gson解析JSON的写法那就在devrunner模块的build.gradle的dependencies块里加一行dependencies { implementation com.google.code.gson:gson:2.10.1 }同步完成后在Kotlin文件里直接import使用import com.google.gson.Gson data class User(val name: String, val age: Int) fun main() { val json {name:Kotlin,age:7} val user Gson().fromJson(json, User::class.java) println(user) }运行后控制台会打印解析出来的User对象。这个流程和普通Gradle项目引入依赖完全一样。注意Java Library模块里用implementation就够了不会出现Android模块里那种implementation和api选择困难症。依赖下载时如果卡在下载环节多半是网络问题。后面第4部分会说怎么配镜像仓库先往下看。3.5 使用Gradle命令行run任务右键运行适合日常点两下就跑的场景但如果你想自动化、或者从命令行跑某个Kotlin文件那就需要配置application插件来暴露一个任务。在devrunner模块的build.gradle里补充plugins { id java-library id org.jetbrains.kotlin.jvm id application } application { mainClass TestMainKt }然后在Android Studio的Terminal窗口执行./gradlew :devrunner:runWindows环境下是gradlew.bat :devrunner:run它会编译并运行TestMainKt这个入口输出和右键运行一致。这个方案的好处是可以把这个Gradle命令写进脚本一键跑模块里所有验证代码。不过application插件会让模块更像一个独立应用如果不想让模块的构建配置太复杂也可以不加。日常验证用右键就够了命令行属于加分项。4. 写错就翻车常见问题与排查技巧实操过程中总会遇到各种报错很多问题看起来吓人其实原因很简单。我把最常见的几种情况整理成了一份速查列表建议收藏备用。4.1 右键没有Run菜单、运行按钮置灰这是被问得最多的一个问题。如果你在Kotlin文件里写了fun main()右键还是没有Run xxxKt按下面顺序排查先看文件是不是在JVM模块里。如果你把这个Kotlin文件建在了Android App模块下即使写了fun main()Android Studio也会因为Android Gradle Plugin的限制不提供直接运行入口。解决办法把文件挪到devrunner模块里或者重新按上一节的步骤创建模块。再看源根目录标记。有时候Gradle同步失败导致IDE没有正确识别目录属性src/main/java不是蓝色IDE就不会扫描里面的源文件。右键目录选Mark Directory as - Sources Root。最后看Gradle同步状态。如果新模块创建后一直没同步成功构建面板会显示红色报错这时候IDE处于“半瘫痪”状态右键菜单自然不完整。去Gradle窗口点刷新等构建成功再试。4.2 Main method not found报错运行配置已经建好了但一点运行就报Main method not found in class TestMainKt这个报错通常是两个原因。第一个原因你把main函数写成了类成员函数。比如class TestMain { fun main() { println(hello) } }这种写法不会生成JVM入口只有顶层函数fun main()被编译成静态入口。如果你确实想用类成员函数需要加上companion object并用JvmStatic注解或者用object声明否则IDE识别不了。第二个原因类的全限定名和运行配置不匹配。如果你给Kotlin文件加了package声明比如package com.example.devrunner那运行配置里的Main class要填com.example.devrunner.TestMainKt。少了包名JVM在类路径里找不到这个类就会报这个错。解决很简单打开Run - Edit Configurations把Main class改成完整类名或者干脆删掉运行配置回到文件里重新右键Run让IDE自动生成正确配置。4.3 中文输出乱码在Kotlin文件里写了一句println(你好)运行后控制台输出乱码。这是JVM默认编码和文件编码不一致导致的。Windows系统上尤其常见因为默认编码可能是GBK而Android Studio的文件编码是UTF-8。处理方法分两层第一层给运行配置加JVM参数。在Run - Edit Configurations里找到你的Kotlin运行配置在VM options里填-Dfile.encodingUTF-8第二层如果每次新建配置都要手动加太麻烦直接在gradle.properties里加一行org.gradle.jvmargs-Dfile.encodingUTF-8这行会全局影响Gradle守护进程的默认编码改了之后重新同步新建的配置也能继承。两个地方都配置好基本就能根治乱码。4.4 Gradle同步慢到怀疑人生新模块创建后Gradle同步一直卡在下载依赖或插件上这在网络环境下很常见。办法是配置国内Maven镜像仓库。在工程根目录的settings.gradle里找到pluginManagement和dependencyResolutionManagement把仓库地址改成阿里云镜像pluginManagement { repositories { maven { url https://maven.aliyun.com/repository/gradle-plugin } maven { url https://maven.aliyun.com/repository/google } maven { url https://maven.aliyun.com/repository/public } google() mavenCentral() gradlePluginPortal() } } dependencyResolutionManagement { repositories { maven { url https://maven.aliyun.com/repository/google } maven { url https://maven.aliyun.com/repository/public } google() mavenCentral() } }如果项目里已经配了镜像那就不需要额外处理。改完后在Gradle窗口点刷新下载速度会明显改善。4.5 协程、挂起函数跑不起来在fun main()里用delay()或者withContext()编译能过运行时报错说delay只能在挂起函数或协程作用域中调用甚至直接崩溃。这说明你还没把协程依赖加进来。在纯JVM模块里需要在build.gradle里引入协程核心库dependencies { implementation org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 }同步后在Kotlin文件里用runBlocking包住协程代码import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking fun main() { runBlocking { println(start) delay(1000) println(end) } }注意runBlocking会阻塞当前线程等协程体执行完才返回。对本地验证代码来说这种方式够用且稳定。千万别在main函数里直接调用GlobalScope.launch因为协程还没跑完main线程就已经退出程序直接结束你什么都看不到。5. 更灵活的玩法Scratch File与Kotlin脚本如果觉得新建模块还是有点重或者不想在工程里留下太多临时文件还有两种更轻量的做法实战中也很实用。5.1 用Scratch File快速跑临时代码Android Studio基于IDEA自然也继承了Scratch File功能。这个功能是专门为“临时码一扔、马上跑”设计的。操作方式在项目任意位置右键选择New - Scratch File - Kotlin。IDE会生成一个临时的.kts或.kt文件视版本不同你直接在里面写代码右键运行即可。Scratch File的好处是不会污染项目目录不需要写进版本控制相当于一张草稿纸。缺点是它默认不关联模块依赖如果你想用Gson或协程这类第三方库需要额外配置库路径反而麻烦。所以我的习惯是纯标准库语法验证用Scratch File有依赖需求用devrunner模块。5.2 用.kts脚本把常用逻辑做成命令行工具Kotlin支持直接运行.kts脚本文件不需要先编译。你可以在工程里建一个tools目录放一些常用的小工具脚本比如批量重命名文件、读取CSV、生成测试数据等等。举个例子创建一个file_utils.ktsimport java.io.File fun main() { val files File(build/outputs).listFiles() files?.forEach { println(it.name) } } main()然后右键这个.kts文件选择Run file_utils.kts。如果IDE提示没有Kotlin脚本支持检查一下模块里是否已经有org.jetbrains.kotlin.jvm插件它一般会自动带上脚本运行能力。这种方式适合“一次写、反复用”的工具型代码。注意脚本文件里的代码是会被顶层执行的所以如果定义了函数要记得在文件底部或者合适位置主动调用不然脚本跑完等于啥也没干。5.3 长期维护一个devrunner模块的建议如果你决定长期采用方案A我强烈建议把这个模块的定位规划好否则用一段时间后里面可能堆满几十个Test1.kt、Test2.kt之类的文件找起来想哭。我的维护策略是按主题分包比如algorithm包放算法题json包放序列化测试coroutine包放协程测试regex包放正则实验。包名用英文小写加下划线一眼能找到。运行完及时清理验证完某段逻辑后如果确认不再需要果断删除文件或包。别让草稿堆积成山。可以用日期命名单一文件如果只是当天快速验证文件名叫Test_20250214.kt这种格式配合隔段时间清理一次不会乱。把模块的临时性写进团队约定如果团队多人共用这套工程记得在README里说明这个模块是本地开发用的不要被误加到App依赖里。结尾我自己在Android Studio里保留一个叫devrunner的Java Library模块已经成了标配。要测试一段API写法就新建一个Kotlin文件写个fun main()直接跑跑完顺手删掉。平时写算法题、验证正则、模拟JSON数据全在这个模块里搞定。这个模块不参与APK打包无论里面怎么折腾都不会影响正式工程。最后再提醒一句这套方法只适用于不依赖Android API的纯Kotlin/JVM代码。如果你想测试的是Context、SharedPreferences、View这些系统组件相关逻辑那就老老实实去模拟器上跑硬把这类代码塞进纯JVM模块里跑结果只会是编译报错或者运行崩溃。把“能跑哪个”和“不能跑哪个”的边界弄清楚这个技巧用起来才会顺手不会被坑第二次。