Skip to content

program-in-chinese/kotlin_in_hours_chn

Repository files navigation

共享协议

本作使用署名-非商业使用-禁止演绎协议共享。

Kotlin编程一天入门 v0.0.1 alpha

前言

Kotlin入门代码用中文写更能被新手理解, 可惜没有看到类似教程. 本作纯属抛砖引玉, 希望各位多指出错误, 欢迎批评/意见/建议.

编程语言的语法是最机械的, 在阅读过程中, 请尽量关注于程序做了些什么, 而一些语法细节可以暂时忽略. 入门之后, 在接下去的写和读代码过程中, 语法自然会熟练起来. 推荐用30分钟先迅速浏览一遍全文, 由于代码是中文命名, 可以先对代码内容有个直观的了解. 第二遍再开始动手运行例程以及自行修改尝试.

每一讲建议时间30分钟左右. 如果卡住(比如超过一小时), 请在代码库开issue. 目的是让总时间控制在8小时左右, 让"一天入门"更符合实际.

目录

准备编程

问个好吧

Kotlin的现状

算术

变量-在程序中保存修改信息

一 准备编程

编程就是让计算机做你想让它做的事.

编程语言是工具,就像画笔,应该拿上手找块空白就可以用.

为了编写第一个Kotlin程序, 我安装了Kotlin编译器, 过程参考官方文档. 本文的代码足够简单, 任何文本编辑器都可以编写. 写本文时用的是Visual Studio Code.

安装JDK后, 打开命令行窗口,运行kotlinc和java,不报错"command not found",即为成功,可以继续. (待续:常见问题与解决)

二 问个好吧

新建文本文件,命名为"问好.kt".输入最简单的一个Kotlin程序:

fun main(参数: Array<String>) {
    // 待续: 要让它做的事
}

的main是程序入口. 注意所有的大括号都需要配对. 双斜杠"//"之后的是注释,是为读代码的人方便理解写的,不影响编译运行. "参数"很扎眼吧,不用急,第四讲就知道它做什么了.

这个程序可以编译运行(见"手把手"部分),但运行后没有任何输出.因为这个程序是个空架子,没有任何可以看到的运行结果.下面就让它做点事.

fun main(参数: Array<String>) {
    // 要让它做的事
    println("吃了么");
}

加上的这行代码将打印一行字,内容是"吃了么".

试试编译运行,将看到命令行下输出:

吃了么

试试改字符串的内容,再编译运行.恭喜! 你已经可以写出无数个不同的Kotlin程序了. 再试试加一行相同的代码,输出结果变了吗? 恭喜! 你已经可以写出无限长的Kotlin程序了.

手把手:

在命令行下编译和运行

编译:

在程序文件的目录下,运行下面的命令

$ kotlinc 问好.kt -include-runtime -d 问好.jar

此命令将程序文件编译生成.jar,在这个目录下多了一个"问好.jar"文件

运行

下面的命令寻找并运行叫"问好"的类:

$ java -jar 问好.jar

三 Kotlin的现状

在更进一步之前,最好了解现在Kotlin都用来做什么.

优点:

  • Kotlin是开源的.
  • 可以调用所有Java库, 背靠大树好乘凉.

可用于所有Java应用的领域:

  • 很大一部分网络服务
  • 大多数安卓手机应用
  • 少量游戏和桌面应用
  • 一些企业内部用Java Applet做可以嵌入网页的在线工具. Chrome浏览器已不支持Java Applet,原因之一是安全性

四 算术

新建文件"四则运算.kt"

fun main(参数: Array<String>) {
    println(1+2);
}

编译运行后,果然输出3. 再试试其他四则运算吧,加减乘除运算符分别是+-*/. 还有括号也可以用. 注: 如果算式中所有的数都是整数,那么每步运算都会取整

恭喜! 你已经可以用Kotlin程序完成数学运算了.

那么其他的运算呢? 新建文件"根号.kt"

fun main(参数: Array<String>) {
    println(Math.sqrt(4.0));
}

看起来告诉程序的值是4.0,编译运行后, 果然如愿打印出了2.0. Math.sqrt是Kotlin中开根号的方法. 应该不用啰嗦了,试试把4.0改成其他的数,看看结果如何?

现在,你可能已经觉得程序的"回答"太"精简"和生硬了,那么人性化一些吧,下面开始只列出main方法内的代码

    println("4的平方根是" + Math.sqrt(4));

输出听起来顺耳些了,但如果想要把4改成其他数,需要改程序的两个地方,这种麻烦可要不得! 可以把4先存到一个变量里,然后在两处引用同一个变量:

    val= 4.0;
    println("${数}的平方根是" + Math.sqrt(数));

这样只要改一处了.不过,为了改输入值,还是要改程序,再编译再运行,这种麻烦可要不得! "参数"终于派上用场了.

    val= 参数[0].toDouble();
    println("${数}的平方根是" + Math.sqrt(数));

"参数[0]"是"参数"数组的第一个值. toDouble()是Kotlin把字符串转换成小数的方法. 现在代码里没有了输入值,该怎样告诉程序需要给什么数开根号呢? 在运行程序时,命令后加上一个"参数":

$ java -jar 根号.jar 4.0

如果忘了在运行时加参数, 这个程序会打印一个异常报告: java.lang.ArrayIndexOutOfBoundsException. 意思是:数组是空的,却要取第一个值,没辙.

试试多加几个参数吧, 参数[1]是"参数"数组第二个值,以此类推. 恭喜! 你的程序不用修改代码就可以接受不同的外部输入了.

Math是Kotlin自带标准库中的数学类,包含很多有用的方法.详细请查阅官方文档.

标准库有很多有用的类. 比如随机数, 用在很多聊天机器人上. 新建"随机数生成器.kt":

fun main (参数: Array<String>) {
    val 生成器 = java.util.Random();
    println("我想到的数字是:" + 生成器.nextInt());
}

java.util.Random是随机数类的全路径, java.util是它所在的包. 没有全路径Java就找不到这个类了. 为什么Math和Integer没有这样的前缀呢? 因为他们在java.lang包里,是"亲生"的,不用包名Java也能找到这些类.

"生成器"是随机数类的一个"个体". 一个现实的比方: "人"是一个类型, 你我都是同样类型的不同个体. nextInt是产生一个随机数的方法. 为什么Math.sqrt不用new出一个个体呢? 因为它们和main方法一样, 都是静态(static)的.

五 变量-在程序中保存修改信息

在上一讲的"根号"类中,用了一个整数(int)变量来保存输入值. "参数"是一个字符串(String)数组.

val意味着这个变量是无法修改的, 也就是说无法被重新赋值. 如果需要一个"真正"的变量, 就是它可以真正被修改/赋值, 那么就用var

Kotlin中还有其他几种基本变量: Boolean, Char, Byte, Short, Long, Float, Double

    val 年纪尚幼: Boolean = true; // true或false,真或假
    val: Char = ''; // 单个字符
    val 年龄: Byte = 27; // 字节: -128到127, 即-2^7到(2^7-1)
    val 认识人数: Short = 1234; // 短整数: -32768到32767, 即-2^15到(2^15-1)
    val 不认识人数: Int = 1234567890; // 整数: -2^31到(2^31-1)
    val 星球数: Long = 123456789000000000L; // 长整数: -2^63到(2^63-1)
    val 身高: Float = 1100000000f; // 单精度浮点数: 2^-126到(2-2^-23)*2^127
    val 体重: Double = 999999999999.9; // 双精度浮点数: 2^-1074到(2-2^-52)*2^1023

它们的范围逐渐增大,可以根据需要选择. 长整数后如果不加'L'(大写的l),会被默认为整数值.

上一讲的四则运算类中,已经尝试了4种运算符. 变量运算的结果可以赋给自己,或者另一个变量.

举个例子, 如2岁的时候认识一个字,每年增加两倍, 3年之后会变成多少.下面是一个很直白的计算方法:

fun main (参数: Array<String>) {
    var 识字量: Int = 1;
    val 每年增倍数: Int = 2;

    // 第一年
    识字量 = (1 + 每年增倍数) * 识字量;

    // 第二年
    识字量 = (1 + 每年增倍数) * 识字量;

    // 第三年
    识字量 = (1 + 每年增倍数) * 识字量;
    println("三年后认识" + 识字量 + "个字咯");
}

你的感觉没错, 它看起来就很累赘, 而且如果要算10年后呢?

恭喜! 你已经有了判断代码优劣的直觉. 至于改进方法,留个悬念吧.