跳到主要内容

Kotlin 第一个程序

完成环境配置后,让我们开始编写第一个 Kotlin 程序。本章将详细介绍程序的结构、编译运行方式以及一些基础知识。

Hello World 程序

按照传统,我们从经典的 "Hello, World!" 程序开始:

fun main() {
println("Hello, World!")
}

将这段代码保存为 Hello.kt 文件,然后运行它。你将在控制台看到:

Hello, World!

虽然只有短短三行代码,但它包含了 Kotlin 程序的基本要素。让我们逐行分析:

代码详解

fun main() {
println("Hello, World!")
}

第一行 fun main()

  • fun 是 Kotlin 中定义函数的关键字(function 的缩写)
  • main 是函数名,这是一个特殊的函数名——程序入口点
  • () 表示函数参数列表,这里为空表示无参数
  • {} 大括号包裹的是函数体,包含要执行的代码

第二行 println("Hello, World!")

  • println() 是标准输出函数,用于打印一行文本并自动换行
  • "Hello, World!" 是一个字符串字面量,用双引号包裹
  • 语句末尾不需要分号(Kotlin 不强制要求分号)

main 函数的作用

在 Kotlin 中,main 函数是程序的入口点(Entry Point)。当你运行一个 Kotlin 程序时,JVM 会自动寻找并执行 main 函数。这与 Java 中的 public static void main(String[] args) 类似,但 Kotlin 的写法更加简洁。

// Java 的 main 方法
public static void main(String[] args) {
System.out.println("Hello, World!");
}

// Kotlin 的 main 函数
fun main() {
println("Hello, World!")
}

可以看到,Kotlin 的版本省去了很多样板代码,让你更专注于实际逻辑。

程序结构

一个完整的 Kotlin 源文件通常包含以下部分:

// 1. 包声明(可选,但推荐)
package com.example.hello

// 2. 导入语句(按需导入)
import java.util.Date
import kotlin.math.PI

// 3. 顶层函数、类、对象等
fun main() {
// 程序入口
}

class Person(val name: String)

object Config {
const val APP_NAME = "MyApp"
}

包声明

Kotlin 使用 package 关键字声明包,用于组织代码结构:

package com.example.myapp

fun main() {
println("Hello from myapp")
}

包名通常采用反向域名命名法(如 com.example.project)。值得注意的是,Kotlin 不强制要求目录结构与包名匹配,但为了代码可维护性,建议保持一致。

导入语句

使用 import 导入其他包中的类、函数或常量:

// 导入单个类
import java.util.Date

// 导入整个包
import kotlin.collections.*

// 导入并重命名(解决命名冲突)
import java.util.Date as JDate
import java.sql.Date as SDate

带参数的 main 函数

除了无参数形式,main 函数还可以接收命令行参数:

fun main(args: Array<String>) {
println("收到 ${args.size} 个参数")

args.forEachIndexed { index, arg ->
println("参数 $index: $arg")
}
}

运行示例:

# 编译
kotlinc ArgsDemo.kt -include-runtime -d ArgsDemo.jar

# 运行并传递参数
java -jar ArgsDemo.jar hello world 123

输出结果:

收到 3 个参数
参数 0: hello
参数 1: world
参数 2: 123

实际应用:命令行计算器

fun main(args: Array<String>) {
if (args.size < 3) {
println("用法: java -jar Calc.jar <数字1> <运算符> <数字2>")
println("示例: java -jar Calc.jar 10 + 5")
return
}

val num1 = args[0].toDoubleOrNull()
val operator = args[1]
val num2 = args[2].toDoubleOrNull()

if (num1 == null || num2 == null) {
println("错误: 请输入有效的数字")
return
}

val result = when (operator) {
"+" -> num1 + num2
"-" -> num1 - num2
"*" -> num1 * num2
"/" -> {
if (num2 == 0.0) {
println("错误: 除数不能为零")
return
}
num1 / num2
}
else -> {
println("错误: 不支持的运算符 '$operator'")
return
}
}

println("$num1 $operator $num2 = $result")
}

标准输入输出

输出函数

Kotlin 提供两个标准输出函数:

fun main() {
// print() - 输出不换行
print("Hello, ")
print("World!")
// 输出: Hello, World!

// println() - 输出并换行
println("第一行")
println("第二行")
}

println() 是最常用的输出函数,它可以打印各种类型的数据:

fun main() {
// 字符串
println("Hello, Kotlin!")

// 数字
println(42)
println(3.14159)

// 布尔值
println(true)
println(false)

// 字符
println('A')

// 任意对象(调用其 toString() 方法)
println(listOf(1, 2, 3))
}

字符串模板

Kotlin 支持强大的字符串模板功能,让你可以方便地在字符串中嵌入变量和表达式:

fun main() {
val name = "Kotlin"
val version = 2.0
val year = 2024

// 简单变量引用:$变量名
println("欢迎学习 $name!")
// 输出: 欢迎学习 Kotlin!

// 表达式引用:${表达式}
println("当前版本: $version,发布于 $year 年")
// 输出: 当前版本: 2.0,发布于 2024 年

// 复杂表达式
val a = 10
val b = 20
println("$a + $b = ${a + b}")
// 输出: 10 + 20 = 30

// 调用方法
val message = "Hello"
println("$message 的长度是 ${message.length}")
// 输出: Hello 的长度是 5

// 在模板中使用条件表达式
val score = 85
println("成绩: $score,结果: ${if (score >= 60) "及格" else "不及格"}")
// 输出: 成绩: 85,结果: 及格
}
字符串模板的优势

使用字符串模板比传统的字符串拼接更简洁、更易读:

// 传统拼接方式
val result = "Hello, " + name + "! Your score is " + score

// 字符串模板方式(推荐)
val result = "Hello, $name! Your score is $score"

输入函数

Kotlin 提供了 readln() 函数用于从标准输入读取用户输入:

fun main() {
// 读取一行输入
println("请输入你的名字:")
val name = readln()
println("你好, $name!")
}

运行示例:

请输入你的名字:
张三
你好, 张三!

结合输入输出,可以创建交互式程序:

fun main() {
// 交互式问候程序
println("=== 问候程序 ===")

print("请输入你的名字: ")
val name = readln()

print("请输入你的年龄: ")
val ageInput = readln()
val age = ageInput.toIntOrNull() ?: 0

print("请输入你的城市: ")
val city = readln()

println()
println("--- 个人信息 ---")
println("姓名: $name")
println("年龄: $age 岁")
println("城市: $city")
println("出生年份约: ${2024 - age} 年")
}
readln() 与 readlnOrNull()
  • readln():读取一行,如果到达 EOF 则抛出异常
  • readlnOrNull():读取一行,如果到达 EOF 则返回 null

在交互式程序中,推荐使用 readln()。在处理文件或可能意外结束的输入流时,使用 readlnOrNull() 更安全。

编译与运行

使用命令行编译器

如果你已经安装了 Kotlin 命令行编译器,可以使用以下方式编译和运行程序:

方式一:编译为 JAR 文件

# 编译(包含 Kotlin 运行时)
kotlinc Hello.kt -include-runtime -d Hello.jar

# 运行
java -jar Hello.jar

参数说明:

  • kotlinc:Kotlin 编译器命令
  • Hello.kt:源文件名
  • -include-runtime:将 Kotlin 运行时库打包进 JAR(使 JAR 可独立运行)
  • -d Hello.jar:指定输出文件名

方式二:编译为 class 文件

# 编译(不包含运行时)
kotlinc Hello.kt -d .

# 使用 kotlin 命令运行
kotlin HelloKt

这种方式生成的 JAR 文件更小,但运行时需要 Kotlin 运行时库。

方式三:脚本模式

Kotlin 支持直接运行脚本文件:

// hello.kts
println("Hello from Kotlin script!")
val x = 10
val y = 20
println("$x + $y = ${x + y}")

运行脚本:

kotlin hello.kts

使用交互式 REPL

Kotlin 提供了交互式 REPL(Read-Eval-Print Loop)环境,适合快速测试代码:

# 启动 REPL
kotlinc

# 在 REPL 中输入代码
>>> val x = 10
>>> println(x * 2)
20
>>> fun greet(name: String) = "Hello, $name!"
>>> greet("Kotlin")
res2: kotlin.String = Hello, Kotlin!

# 退出 REPL
>>> :quit

使用 IntelliJ IDEA

对于日常开发,推荐使用 IntelliJ IDEA:

  1. 创建项目:File → New → Project → Kotlin → JVM
  2. 创建文件:右键 src 目录 → New → Kotlin Class/File
  3. 运行程序:点击 main 函数旁的绿色三角形 → Run

IDE 会自动处理编译过程,并提供代码补全、语法高亮、调试等功能。

使用 Gradle 构建

对于正式项目,建议使用 Gradle 构建工具:

项目结构

my-project/
├── build.gradle.kts
├── settings.gradle.kts
└── src/
└── main/
└── kotlin/
└── Main.kt

build.gradle.kts

plugins {
kotlin("jvm") version "1.9.22"
application
}

application {
mainClass.set("MainKt")
}

repositories {
mavenCentral()
}

运行项目

# 编译
./gradlew build

# 运行
./gradlew run

程序示例

让我们通过几个示例程序,进一步了解 Kotlin 的基本语法。

示例一:个人信息展示

fun main() {
// 使用 val 定义不可变变量
val name = "张三"
val age = 25
val city = "北京"
val job = "软件工程师"

// 使用字符串模板格式化输出
println("========== 个人信息 ==========")
println("姓名: $name")
println("年龄: $age 岁")
println("城市: $city")
println("职业: $job")

// 计算出生年份
val currentYear = 2024
val birthYear = currentYear - age
println("出生年份: $birthYear 年")

// 多行字符串
val introduction = """
大家好!我是 $name
我是一名 $job,今年 $age 岁。
很高兴认识大家!
""".trimIndent()

println("\n$introduction")
}

示例二:简单计算器

fun main() {
println("=== 简单计算器 ===")

// 读取用户输入
print("请输入第一个数字: ")
val num1 = readln().toDoubleOrNull() ?: 0.0

print("请输入运算符 (+, -, *, /): ")
val operator = readln()

print("请输入第二个数字: ")
val num2 = readln().toDoubleOrNull() ?: 0.0

// 计算结果
val result = when (operator) {
"+" -> num1 + num2
"-" -> num1 - num2
"*" -> num1 * num2
"/" -> {
if (num2 != 0.0) num1 / num2 else {
println("错误: 除数不能为零")
return
}
}
else -> {
println("错误: 不支持的运算符 '$operator'")
return
}
}

// 输出结果
println("\n计算结果:")
println("$num1 $operator $num2 = $result")
}

示例三:猜数字游戏

fun main() {
// 生成随机数
val target = (1..100).random()
var attempts = 0
var guessed = false

println("=== 猜数字游戏 ===")
println("我已经想好了一个 1 到 100 之间的数字")
println("你有 7 次机会来猜中它!\n")

while (attempts < 7 && !guessed) {
attempts++
print("第 $attempts 次尝试,请输入你的猜测: ")

val guess = readln().toIntOrNull()
if (guess == null) {
println("请输入有效的数字!")
attempts--
continue
}

when {
guess < target -> println("太小了!再试试看。")
guess > target -> println("太大了!再试试看。")
else -> {
guessed = true
println("\n恭喜你猜对了!答案就是 $target")
println("你用了 $attempts 次猜中!")
}
}
}

if (!guessed) {
println("\n游戏结束!正确答案是 $target")
}
}

常见问题

1. 文件名与类名的关系

在 Kotlin 中,文件名不需要与类名一致。一个 .kt 文件可以包含多个类、函数和对象。但为了代码可维护性,建议:

  • 如果文件只包含一个公共类,文件名与类名保持一致
  • 如果文件包含多个相关定义,使用描述性的文件名
// Utils.kt - 包含多个工具函数
fun formatDate(date: Date): String { ... }
fun parseDate(str: String): Date { ... }

class DateUtils { ... }

2. 为什么不需要分号?

Kotlin 采用智能分号推断(Semicolon Inference),编译器会自动判断语句结束位置。这意味着:

// 以下两种写法等价
val x = 10
val y = 20

val x = 10;
val y = 20;

但在某些情况下需要手动添加分号:

// 同一行多条语句
val a = 1; val b = 2; val c = 3

// return 或 throw 后跟同一行的表达式
if (condition) return; else doSomething()

3. main 函数可以在哪里定义?

main 函数可以定义在文件的顶层,不需要放在类中:

// Hello.kt - 顶层 main 函数
fun main() {
println("Hello")
}

// 也可以定义在包中
package com.example

fun main() {
println("Hello")
}

4. 如何运行 Kotlin 程序?

Kotlin 程序可以通过多种方式运行:

方式说明适用场景
IntelliJ IDEA点击运行按钮日常开发
java -jar xxx.jar运行编译后的 JAR生产部署
kotlin MainKt直接运行 class 文件开发测试
kotlin script.kts运行脚本文件快速测试
Kotlin Playground在线运行学习尝鲜

5. 编译后的文件在哪里?

编译后生成的文件取决于编译方式:

  • kotlinc Hello.kt:生成 HelloKt.class 文件
  • kotlinc -d Hello.jar:生成 JAR 文件
  • Gradle build:生成 build/libs/xxx.jar

小结

本章我们学习了:

  1. Hello World 程序:理解程序入口点和基本语法
  2. 程序结构:包声明、导入语句、函数定义
  3. main 函数:无参数形式和带参数形式
  4. 标准输入输出print()println()readln()
  5. 字符串模板:使用 $${} 嵌入变量和表达式
  6. 编译运行:命令行、IDE、Gradle 等多种方式

接下来,我们将深入学习 Kotlin 的基础语法,包括变量、数据类型、运算符等内容。

练习

  1. 修改 Hello World:编写程序输出你的名字和今天的日期
  2. 交互式问候:让用户输入名字,输出个性化问候语
  3. 温度转换:输入摄氏温度,转换为华氏温度并输出
  4. 命令行参数:使用命令行参数实现简单的四则运算
  5. 个人信息卡片:创建一个程序,展示你的个人信息(姓名、年龄、爱好等)