• 《Kotlin中文教程》

  • 价格:免费
  • 状态:全书已完结
  • 在读人数:22
  • 热度:1298
创建者
内容简介
Kotlin是JetBrains团队开发的一门现代的、注重工程实用性的静态类型编程语言,JetBrains团队以开发了世界上最好用的IDE而著称。Kotlin于2010年推出,并在2011年开源。Kotlin充分借鉴汲取了 Java、Scala、Groovy、C#、Gosu、JavaScript、Swift等多门杰出语言的优秀特性,语法简单优雅、表现力丰富、抽象扩展方便、代码可重用性好,同时也支持面向对象和函数式编程的多范式编程。Kotlin可以编译成Java字节码运行在JVM平台和Android平台,也可以编译成JavaScript运行在浏览器环境,而且还可以直接编译成机器码的系统级程序,直接运行在嵌入式、iOS、MacOS/Linux/Windows等没有JVM环境的平台。Kotlin源自产业界,它解决了工程实践中程序设计所面临的真实痛点,例如,类型系统可以避免空指针异常的问题。

我最早是被Kotlin的下面这段代码所吸引:

package com.easy.kotlin
fun <A, B, C> compose(f: (B) -> C, g: (A) -> B): (A) -> C {
    return { x -> f(g(x)) }
}
fun isOdd(x: Int) = x % 2 != 0
fun length(s: String) = s.length
fun main(args: Array<String>) {
    val oddLength = compose(::isOdd, ::length)
    val strings = listOf("a", "ab", "abc")
    println(strings.filter(oddLength))
}
13行。

这大约是在三年前,当时我在学习 Java 8 中的函数式编程以及 Lambda 表达式等新特性。那时,我也对Scala、Groovy、Clojure、Haskell等技术很感兴趣,简单学习了部分知识。在这样伴随着兴趣的学习过程中,我无意中看到了上面那段Kotlin代码,第一眼看到这么优雅的函数式编程风格,尤其是compose函数的定义实现,我被深深地吸引了。

Swift 使用func关键字声明函数多个 c 怪怪的,Groovy、Scala 等使用 def 跟函数本义联想不直接 ,JavaScript 中使用 function 关键字又显得死板了些。而 Kotlin 中的 fun 则简单优雅地恰到好处,关键还让人自然联想到“乐趣、开心的、使人愉快的”这样的意思。使用 Kotlin每写一个函数都是充满乐趣的。

我们不妨来看看同样的逻辑实现,如果我们使用 Java 8来写,代码如下所示

package com.easy.kotlin;
import java.util.ArrayList;
import java.util.List;
interface G<A, B> {
    B apply(A a);
}
interface F<B, C> {
    C apply(B b);
}
interface FG<A, B, C> {
    C apply(A a);
}
public class ComposeFunInJava<A, B, C> {
    public static void main(String[] args) {
        G<String, Integer> g = (s) -> s.length();
        F<Integer, Boolean> f = (x) -> x % 2 != 0;
        FG<String, Integer, Boolean> fg = (x) -> f.apply(g.apply(x));
        List<String> strings = new ArrayList();
        strings.add("a");
        strings.add("ab");
        strings.add("abc");
        List<String> result = new ArrayList();
        for (String s : strings) {
            if (fg.apply(s)) {
                result.add(s);
            }
        }
        System.out.println(result);
    }
}
36行,差不多是 Kotlin 的3倍。

我们知道,Java是一门非常优秀的面向对象语言。但是在函数式编程方面,跟其他函数语言相比,还是显得有些笨重与生涩,并且其内在体现出来的思想,依旧是面向对象的思想。

而功能强大的Scala 语言,复杂性却相对较高,学习成本也远高于 Kotlin。 另外,Scala 与 Java 的互操作性没有 Kotlin 好。所以,如果我们既想方便地流畅地使用 Java 的强大且完善的生态库,又想使用更加先进的编程语言的特性,无疑 Kotlin 是个非常不错的选择。

我立马进入了Kotlin的世界。

Kotlin之前一直是默默无闻的,直到今年(2017)5.18 Google IO 大会上,Google宣布正式支持Kotlin为Android的官方开发语言,而且从Android Studio 3.0开始,将直接内置集成Kotlin而无需安装任何的插件。另外,在Spring 5.0 M4 中也引入了对Kotlin专门的支持。

在学习和使用Kotlin中,我发现我越来越喜欢 Kotlin,它是一门非常优秀、优雅有趣、流畅实用的语言,绝对值得一试。感谢Kotlin团队!

本书可以说是我对Kotlin的使用和思考过程的粗浅总结。通过本书的写作,加深了我对 Kotlin语言及其编程的理解,我深刻体会到了学无止境的含义。写书的过程也是我系统学习与思考Kotlin的过程,如果本书能够对你有所帮助,将不胜欣慰。

如何阅读本书
本书共16章。我们希望通过简练的表述,全面介绍Kotlin语言特性以及如何使用Kotlin进行实际项目开发,主要包括如下内容:

快速开始 Hello World
基础语法
基本数据类型和类型系统
常用数据结构集合类
面向对象编程和函数式编程
协程
Kotlin与 Java 互操作
集成 SpringBoot 进行服务端开发
使用 Kotlin DSL
文件IO操作与多线程
使用 Kotlin Native以及与 C 语言互操作
第1章是Kotlin 语言的简介,快速学习Kotlin的环境搭建以及常用工具的使用。该章最后还给出一个编程语言学习的小结。通过该章的学习,能够快速进入Kotlin的世界。

第2章是快速开始 Hello World,分别给出了使用命令行REPL、可执行应用程序、Web RESTFul、Android、Kotlin JavaScript等平台环境上的HelloWorld示例。通过该章的学习,可以快速体验在多平台上使用Kotlin语言进行开发的过程。

第3章介绍Kotlin语言的基础知识,包括Kotlin语言的关键字与标识符等、表达式与流程控制、运算操作符、函数及其扩展等基本内容。

第4章介绍Kotlin语言的基本类型和类型系统。我们会首先简单介绍类型的基本概念,然后具体介绍 Kotlin 的内置基本类型:数字、字符串、布尔、数组等。 接着介绍 Kotlin 中引入的特殊的可空类型。最后,简单介绍了Kotlin中的类型推断与类型转换的相关内容。

第5章介绍Kotlin标准库中的集合类:List、Set、Map。Kotlin 中提供了不可变集合类与可变集合类。通过该章的学习,我们将了解到Kotlin 是如何扩展的Java集合库,使得写代码更加简单容易。

第6章介绍Kotlin泛型的基本概念、型变以及类型边界等内容,同时简单介绍了泛型类与泛型函数。

第7章介绍Kotlin面向对象编程的特性: 类与构造函数、抽象类与接口、继承以及多重继承等基础知识,同时介绍了Kotlin中的注解类、枚举类、数据类、密封类、嵌套类、内部类、匿名内部类等特性类。最后我们学习了Kotlin中对单例模式、委托模式的语言层面上的内置支持:object对象、委托。

第8章介绍Kotlin函数式编程的相关内容,其中重点介绍了Kotlin中的高阶函数、Lambda表达式、闭包等核心语法,并给出相应的实例说明。还探讨了关于Lambda演算、Y组合子与递归等函数式编程思想等相关内容。

第9章介绍Kotlin中的协程。首先引入了协程的基本概念,然后通过一些基础使用实例来学习有关协程的创建、执行、取消等操作的方法。在该章的后半部分,我们主要探讨挂起函数的组合执行、协程上下文与调度器、通道与管道等相关内容。最后,我们对协程与线程进行了简单比较,简要介绍了Kotlin的协程API库。

第10章介绍Kotlin与Java的互操作。

第11章介绍如何使用Kotlin集成Spring Boot、SpringMVC等框架来开发Web服务端应用,给出了一个完整的开发实例。最后,简单介绍了Spring 5.0中对Kotlin的支持特性。

第12章介绍使用 Kotlin 集成Gradle 开发的相关内容。

第13章通过一个具体的Android开发实例,来一起学习使用 Kotlin 开发 Android 应用的具体方法。其中用到了Anko、ButterKnife、Realm 等相关框架。

第14章介绍Kotlin中DSL的相关内容。我们将会看到Kotlin 的扩展函数和高阶函数(Lambda 表达式)特性,为定义Kotlin DSL提供了极大的支持。使用DSL的代码风格,可以让我们的程序更加直观易懂、简洁优雅。如果使用Kotlin来开发项目的话,我们完全可以去尝试一下。

第15章介绍Kotlin文件IO 操作、正则表达式以及多线程相关的内容。

第16章简单介绍了Kotlin Native,该章给出了一个简单的 Hello World 的 Native 实例,同时给出了 Kotlin 与 C 语言互操作的完整实例。

谁适合阅读本书
本书适合于所有程序员,不管你是前端开发者、Android/iOS 开发者,还是Java 开发者、C 语言开发者,等等。
如果你目前还不是程序员,但想进入编程世界,那么可以尝试从Kotlin开始学习。虽然本书中的部分内容需要一定的编程基础,但是Kotlin本身的极简特性能激发你对编程的兴趣。
章节目录
  • 第一章 Kotlin简介
  • 1.1 kotlin简史
  • 1.1 kotlin简史 1.1.1 Kotlin概述 科特林岛(Котлин)是一座俄罗斯的岛屿,位于圣彼得堡以西约30公里处,形状狭长,东西长度约14公里,南北宽度约2公里,面积有16平方公里,扼守俄国进
  • 1.2 快速学习工具
  • 1.2.1 云端IDE 未来的是云的世界。不需要搭建本地开发运行环境,直接用浏览器打开 https://try.kotlinlang.org/ 你就可以直接使用云端IDE来即时编写Kotlin代码,并运行之。一个运行示例如下图:1.2.2 本地命令行环境搭建 Kotlin是运行在JVM环
  • 第二章 快速开始:HelloWorld
  • 2.1 命令行的HelloWorld
  • 2.1 命令行的HelloWorld 安装配置完Kotlin命令行环境之后,我们直接命令行输入kotlinc, 即可进入 Kotlin REPL界面。 $ kotlinc Welcome to Kotlin version 1.1.2-2 (JRE 1.8.0_40-b27) Type :help for help, :quit for quit &gt;&gt;&gt; pr
  • 2.2 应用程序版HelloWorld
  • 我们如果想拥有学习Kotlin的相对较好的体验,就不建议使用eclipse了。毕竟Kotlin是JetBrains家族的亲儿子,跟Intelli IDEA是血浓于水啊。我们使用IDEA新建gradle项目,选择Java,Kotlin(Java)框架支持,如下图:新建完项目,我们写一个HelloWorld.kt类 package com.eas
  • 2.3 Web RESTFul HelloWorld
  • 本节介绍使用 Kotlin 结合 SpringBoot 开发一个RESTFul版本的 Hello.World。 1.新建gradle,kotlin工程: 打开IDEA的File &gt; New &gt; Project , 如下图按照界面操作,输入相应的工程名等信
  • 2.4 Android版的HelloWorld
  • 2017谷歌I/O大会:宣布 Kotlin 成 Android 开发一级语言。 2017谷歌I/O大会上,谷歌宣布,将Kotlin语言作为安卓开发的一级编程语言。Kotlin由JetBrains公司开发,与Java100%互通,并具备诸多Java尚不支持的新特性。谷歌称还将与JetBrains公司合作,为Kotlin设立一个非盈
  • 2.5 JavaScript版HelloWorld
  • 在Kotlin 1.1中,开始支持JavaScript和协程是引人注目的亮点。本节我们简单介绍Kotlin代码编译转化为JavaScript的方法。 为了极简直观地感受这个过程,我们先在命令行REPL环境体验一下Kotlin源码被编译生成对应的JavaScript代码的过程。 首先,使用编辑器新建一个HelloWord.kt fun helloWorld(){println(&quot;H
  • 第三章 Kotlin语言基础
  • 3.1 包(package)
  • 我们先来举个例子。比如说,程序员A写了一个类叫 JSON , 程序员B也写了一个类叫 JSON。然后,我们在写代码的时候,想要同时使用这两个类,该怎么区分呢?一个答案是使用目录命名空间。对应在Java中,就是使用package来组织类,以确保类名的唯一性。上面说的例子,A写的类放到package com.abc.fastjson 中, B写的类就放到 package
  • 3.2 声明变量和值
  • 首先,在Kotlin中, 一切都是对象。所以,所有变量也都是对象(也就是说,任何变量都是根据引用类型来使用的)。Kotlin的变量分为 var (可变的) 和 val (不可变的)。可以简单理解为:1.var 是可写的,在它生命周期中可以被多次赋值;2.而 val 是只读的,仅能一次赋值,后面就不能被重新赋值。 代码示例 package com.easy.kotlin import ja
  • 3.3 变量类型推断
  • 3.3.1 省去变量类型 在Kotlin中大部分情况你不需要说明你使用对象的类型,编译器可以直接推断出它的类型。代码示例 fun typeInference(){val str = &quot;abc&quot;println(str)println(st
  • 3.4 字符串与其模板表达式
  • 原始字符串(raw string)由三重引号(”””)分隔(这个跟python一样)。原始字符串可以包含换行符和任何其他字符。 package com.easy.kotlin fun main(args: Array&lt;String&gt;) {val rawString = &quot;&quot;
  • 3.5 流程控制语句
  • 流程控制语句是编程语言中的核心之一。可分为: 1.分支语句(if 、 when) 2.循环语句(for、while )和 3.跳转语句 (return 、 break 、continue、throw)等。3.5.1 if表达式 if-else语句是控制程序流程的最基本的形式,其中else是可选的。在 Kotlin 中,if 是一个表达式,即它会返回一个值(跟Scala一样)。 代码示例: pac
  • 3.6 代码注释
  • 正如 Java 和 JavaScript,Kotlin 支持行注释及块注释。 // 这是一个行注释 /* 这是一个多行的块注释。 */ 与 Java 不同的是,Kotlin 的块注释可以嵌套。就是说,你可以这样注释: /*** hhhh* /*** fff* /*** ggggg* */* */** abc**/ fun main(args:Array&lt;
  • 3.7 语法与标识符
  • 我们知道,任何一门编程语言都会有一些自己专用的关键字、符号以及规定的语法规则等等。程序员们使用这些基础词汇和语法规则来表达算法步骤,也就是写代码的过程。词法分析是编译器对源码进行编译的基础步骤之一。词法分析是
  • 3.8 函数扩展和属性扩展(Extensions)
  • Kotlin 支持 扩展函数 和 扩展属性。其能够扩展一个类的新功能而无需继承该类或使用像装饰者这样的设计模式等。大多数时候我们在顶层定义扩展,即直接在包里: package com.easy.kotlin val &lt;T&gt; List&lt;T&gt;.lastIndex: Int get() = size - 1 fun String.notEmpty(): Boolean
  • 3.9 空指针安全(Null-safety)
  • 我们写代码的时候知道,在Java中NPE(NullPointerExceptions)是一件成程序员几近崩溃的事情。很多时候,虽然费尽体力脑力,仍然防不胜防。以前,当我们不确定一个DTO类中的字段是否已初始化时,可以使用@Nullable和@NotNull注解来声明,但功能很有限。现在好了,Kotlin在编译器级别,把你之前在Java中需要写的null chec
  • 第四章 基本数据类型与类型系统
  • 4.1 什么是类型?
  • 在计算机中,任何数值都是以一组比特(01)组成的,硬件无法区分内存地址、脚本、字符、整数、以及浮点数。这个时候,我们使用类型赋予一组比特以特定的意义。类型(Type),本质上就是内存中的数值或变量对象的逻辑映射。《周易》有云: 易有太极,是生两仪,两仪生四象,四象生八卦。(《易传
  • 4.2 编译时类型与运行时类型
  • Koltin是一门强类型的、静态类型、支持隐式类型的显式类型语言。4.2.1 弱类型(Weakly checked language)与强类型(Strongly checked language) 类型系统最主要的作用是,通过检查类型的运算和转换过程,来减少类型错误的发生。如果一个语言的编译器引入越多的类型检查的限制,就可以称这个语言的类型检查越强,反之越弱
  • 4.3 根类型Any
  • Kotlin 中所有类都有一个共同的超类 Any ,如果类声明时没有指定超类,则默认为 Any 。我们来看一段代码: &gt;&gt;&gt; val any = Any() &gt;&gt;&gt; any j
  • 4.4 基本类型(Primitive Types)
  • 本节我们来探讨学习:Kotlin的基础类型:数字、字符、布尔和数组等。我们知道Java的类型分成两种:一种是基本类型,一种是引用类型。它们的本质区别是: 基本类型是在堆栈处分配空间存“值”,而引用类型是在堆里面分配空间存“值”。Java的基本类型有: byte、int、short、long、float、double、char、boolean,这些类都有对应的装箱类(引用类型)。另外,
  • 4.5 Any?可空类型(Nullable Types)
  • 可空类型是Kotlin类型系统的一个特性,主要是为了解决Java中的令人头疼的 NullPointerException 问题。我们知道,在Java中如果一个变量可以是null,来那么使用它调用一个方法就是不
  • 4.6 kotlin.Unit类型
  • Kotlin也是面向表达式的语言。在Kotlin中所有控制流语句都是表达式(除了变量赋值、异常等)。Kotlin中的Unit类型实现了与Java中的void一样的功能。不同的是,当一个函数没有返回值的时候,我们用Unit来表示这个特征,而不是null。大多数时候,我们并不需要显式地返回Unit,或者声明一个函数的返回类型为Unit。编译器会推断出它。代码示
  • 4.7 kotlin.Nothing类型
  • Kotlin中没有类似Java和C中的函数没有返回值的标记void,但是拥有一个对应Nothing。在Java中,返回void的方法,其返回值void是无法被访问到的: public class VoidDemo {public void voidDemo() {System.out.println(&quot;Hello,Void&qu
  • 4.8 类型检测与类型转换
  • 4.8.1 is,!is运算符 is运算符可以检查对象是否与特定的类型兼容(“兼容”的意思是:此对象是该类型,或者派生于该类型)。is运算符用来检查对象(变量)是否属于某数据类型(如Int、String、Boolean等)。C#里面也有这个运算符。 is运算符类似Java的instanceof: @org.junit.runne
  • 4.9 小结
  • 在本章中,我们停下脚步,仔细深入地去探讨了Kotlin语言中最重要的部分之一的:类型系统。与Java相比,Kotlin的类型系统更加简单一致,同时引入了一些新的特性,这些特性对于提高代码的安全性、可靠性至关重要。例如:可空类型和只读集合。关于只读集合类,我们将在下一章中介绍。 我们下一章的主
  • 第五章 集合类
  • 5.1 集合类是什么
  • 5.1.2 集合类是一种数据结构 在讲 Kotlin 的集合类之前,为了更加深刻理解为什么要有集合类,以及集合类到底是怎么一回事,让我们先来简单回顾一下编程的本质: 数据结构 + 算法 (信息的逻辑结构及其基本操作)我们使用计算机编程来解决
  • 5.2 Kotlin 集合类简介
  • 集合类存放的都是对象的引用,而非对象本身,我们通常说的集合中的对象指的是集合中对象的引用(reference)。Kotlin的集合类分为:可变集合类(Mutable)与不可变集合类(Immutable)。集合类
  • 5.3 创建不可变List
  • 我们可以使用listOf函数来构建一个不可变的List(read-only,只读的List)。它定义在libraries/stdlib/src/kotlin/collections/Collections.kt 里面。关于listOf这个构建函数有下面3个重载函数: @kotlin.internal.InlineOnly public inline fun &lt;T&gt; lis
  • 5.4 创建可变集合MutableList
  • 我们可以使用listOf函数来构建一个不可变的List(read-only,只读的List)。它定义在libraries/stdlib/src/kotlin/collections/Collections.kt 里面。关于listOf这个构建函数有下面3个重载函数: @kotlin.internal.InlineOnly pu
  • 5.5 遍历List元素
  • 使用Iterator迭代器 我们以集合 val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9)为例,使用Iterator迭代器遍历列表所有元素的操作: &gt;&gt;&gt; val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9)
  • 5.6 List集合类的基本运算函数
  • any()判断集合至少有一个元素 这个函数定义如下: public fun &lt;T&gt; Iterable&lt;T&gt;.any(): Boolean {for (element in this) return truereturn false } 如果该集合至少有一个元素,返回true,否则返回false。代码示例: &gt;&gt;&gt; val emp
  • 5.7 List过滤操作函数
  • take(n: Int): List&lt;T&gt; 挑出该集合前n个元素的子集合 函数定义: public fun &lt;T&gt; Iterable&lt;T&gt;.take(n: Int): List&lt;T&gt; {require(n &gt;= 0) { &quot;Requested element count $n is less than zero
  • 5.8 List映射操作符
  • map(transform: (T) -&gt; R): List&lt;R&gt; 将集合中的元素通过转换函数transform映射后的结果,存到一个集合中返回。 &gt;&gt;&gt; val list = listOf(1,2,3,4,5,6,7) &gt;&gt;&gt; list.map({it}) [1, 2, 3, 4, 5, 6, 7]
  • 5.9 List分组操作符
  • groupBy(keySelector: (T) -&gt; K): Map&lt;K, List&lt;T&gt;&gt; 将集合中的元素按照条件选择器keySelector(是一个函数)分组,并返回Map。 代码示例: &gt;&gt;&gt; val words = listOf(&quot;a&quot;, &quot;abc&
  • 5.10 List 排序操作符
  • reversed(): List&lt;T&gt; 倒序排列集合元素。 代码示例 &gt;&gt;&gt; val list = listOf(1,2,3) &gt;&gt;&gt; list.reversed()
  • 5.11 List生产操作符
  • zip(other: Iterable&lt;R&gt;): List&lt;Pair&lt;T, R&gt;&gt; 两个集合按照下标配对,组合成的每个Pair作为新的List集合中的元素,并返回。 如果两个集合长度不一样,取短的长度。 代码示例: &gt;&gt;&gt; val list1 = listOf(1,2,3) &gt;&gt;&gt; val list2 = listOf
  • 5.12 Set集合
  • 类似的,Kotlin中的Set也分为:不可变Set和支持增加和删除的可变MutableSet。不可变Set同样是继承了Collection。MutableSet接口继承于Set, MutableCollection,同时对Set进行扩展,添加了对元素添加和删除
  • 5.13 Map
  • 5.5.1 Map概述 Map是一种把键对象Key和值对象Value映射的集合,它的每一个元素都包含一对键对象和值对象(K-V Pair)。 Key可以看成是Value 的索引,作为key的对象在集合中不可重复(uniq)。如果我们从数据结构的本质
  • 第六章 泛型
  • 6.1 泛型(Generic Type)简介
  • 通常情况的类和函数,我们只需要使用具体的类型即可:要么是基本类型,要么是自定义的类。但是尤其在集合类的场景下,我们需要编写可以应用于多种类型的代码,我们最简单原始的做法是,针对每一种类型,写一套刻板的代码。这样做,代码复用率会很低,抽象也没有做好。在 jdk 5 中,Java引入了泛型。泛型,即“参数化类型”(Parameterize
  • 6.2 型变(Variance)
  • 6.2.1 Java的类型通配符 Java 泛型的通配符有两种形式。我们使用: 1.子类型上界限定符? extends T 指定类型参数的上限(该类型必须是类型T或者它的子类型) 2.超类型下界限定符? super T 指定类型参数的下限(该类型必须是类型T或者它的父类型) 我们称
  • 6.3 Kotlin的泛型特色
  • 正如上文所讲的,在 Java 泛型里,有通配符这种东西,我们要用? extends T指定类型参数的上限,用 ? super T指定类型参数的下限。而Kotlin 抛弃了这个东西,引用了生产者和消费者的概念。也就是我们前面讲到的PEC
  • 6.4 泛型函数
  • 类可以有类型参数。函数也有。类型参数要放在函数名称之前: fun &lt;T&gt; singletonList(item: T): List&lt;T&gt; {} fun &lt;T&gt; T.basicToString() :
  • 6.5 泛型类
  • 声明一个泛型类 class Box&lt;T&gt;(t: T) {var value = t } 通常, 要创建这样一个类的实例, 我们需要指定类型参数: val box: Box&lt;Int&gt; = Box&lt;Int&gt;(1) 但是, 如果类型参数可以通过推断得到, 比如, 通过构造器参数类型, 或通过其他手段推断得到, 此时允许省略类型参数: val box = Box
  • 6.6 本章小结
  • 泛型是一个非常有用的东西。尤其在集合类中。我们可以发现大量的泛型代码。本章我们通过对Java泛型的回顾,对比介绍了Kotlin泛型的特色功能,尤其是协变、逆变、in、 out等概念,需要我们深入去理解。只有深入理解了这些概念,我们
  • 第七章 面向对象编程(OOP)
  • 7.1 面向对象编程思想
  • 7.1.1 一切皆是映射 《易传&#183;系辞上传》:“易有太极,是生两仪,两仪生四象,四象生八卦。” 如今的互联网世界,其基石却是01(阴阳),不得不佩服我华夏先祖的博大精深的智慧。计算机领域中的所
  • 7.2 类与构造函数
  • Kotlin和Java很相似,也是一种面向对象的语言。下面我们来一起学习Kotlin的面向对象的特性。如果您熟悉Java或者C++、C#中的类,您可以很快上手。同时,您也将看到Kotlin与Java中的面向对象编程的一些不同的特性。Kotlin中的类和接口跟Java中对应的概念有些不同,比如接口可以包含属性声明;Kot
  • 7.3 抽象类
  • 7.3.1 抽象类的定义 含有抽象函数的类(这样的类需要使用abstract修饰符来声明),称为抽象类。下面是一个抽象类的例子: abstract class Person(var name: String, var age: Int) : Any() {abstract var addr: Stringabstract val weight: Floatabstra
  • 7.4 接口
  • 7.4.1 接口定义 和Java类似,Kotlin使用interface作为接口的关键词: interface ProjectService Kotlin 的接口与 Java 8 的接口类似。与抽象类相比,他们都可以包含抽象的方法以及方法的实现: interface ProjectSer
  • 7.5 继承
  • 继承是面向对象编程的一个重要的方式,因为通过继承,子类就可以扩展父类的功能。在Kotlin中,所有的类会默认继承Any这个父类,但Any并不完全等同于java中的Object类,因为它只有equals(),hashCode()和toString()这三个方法。7.5.1 open类 除了抽象类、接口默认
  • 7.6 枚举类
  • Kotlin的枚举类定义如下: public abstract class Enum&lt;E : Enum&lt;E&gt;&gt;(name: String, ordinal: Int): Comparable&lt;E&gt; {companion object {}public final val name: String
  • 7.7 注解类
  • Kotlin 的注解与 Java 的注解完全兼容。 7.7.1 声明注解 annotation class 注解名 代码示例: @Target(AnnotationTarget.CLASS,AnnotationTarget.FUNCTION,AnnotationTarget.EXPRESSION,AnnotationTarget.
  • 7.8 单例模式(Singleton)与伴生对象(companion object)
  • 7.8.1 单例模式(Singleton) 单例模式很常用。它是一种常用的软件设计模式。例如,Spring中的Bean默认就是单例。通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例。我们用J
  • 7.9 sealed 密封类
  • 7.9.1 为什么使用密封类 就像我们为什么要用enum类型一样,比如你有一个enum类型 MoneyUnit,定义了元、角、分这些单位。枚举就是为了控制住你所有要的情况是正确的,而不是用硬编码方式写成字符串“元”,“角”,“分”。同样,se
  • 7.10 data 数据类
  • 7.11.1 构造函数中的 val/var 在开始讲数据类之前,我们先来看一下几种类声明的写法。 写法一: class Aook(name: String) 这样写,这个name变量是无法被外部访问到的。它对应的反编译之后的Java代码如下: public f
  • 7.11 嵌套类(Nested Class)
  • 7.12.1 嵌套类:类中的类 类可以嵌套在其他类中,可以嵌套多层: class NestedClassesDemo {class Outer {private val zero: Int = 0val one: Int = 1class Nested {fun getTwo() = 2class
  • 7.12 委托(Delegation)
  • 7.12.1 代理模式(Proxy Pattern) 代理模式,也称委托模式。 在代理模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。代理模式是一项基本技巧,许多其他的模式,如状态模式、策略模式、访问者模式本质上是在特殊的场合采用
  • 7.13 本章小结
  • 本章我们介绍了Kotlin面向对象编程的特性: 类与构造函数、抽象类与接口、继承以及多重继承等基础知识,同时介绍了Kotlin中的注解类、枚举类、数据类、密封类、嵌套类、内部类、匿名内部类等特性类。最后我们学习了Kotlin中对单例模式、委托模式的语言层面上的内置支持:object对象、委托。总的来说,Kotlin相比于Java的面向对象编程,增加不少有趣的功能与特性
  • 第八章 函数式编程(FP)
  • “函数式编程”, 又称泛函编程, 是一种”编程范式”(programming paradigm),也就是如何编写程序的方法论。它的基础是 λ 演算(lambda calculus)。λ演算可以接受函数当作输入(参数)和输出(返回值)。和指令式编程相比,函数式编程的思维方式更加注重函数的计算。它的主
  • 8.1 函数式编程概述
  • 函数式编程思想是一个非常古老的思想。我们简述如下: 我们就从1900 年 David Hilbert 的第 10 问题(能否通过有限步骤来判定不定方程是否存在有理整数解?) 开始说起吧。1920,Sch&#246;nfinkel,组合子逻辑(combinatory logic)。
  • 8.2 面向对象编程(OOP)与面向函数编程(FOP)
  • 面向对象编程(OOP) 在OOP中,一切皆是对象。在面向对象的命令式(imperative)编程语言里面,构建整个世界的基础是类和类之间沟通用的消息,这些都可以用类图(class diagram)来表述。《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software,
  • 8.3 函数式编程基本特性
  • 在经常被引用的论文 “Why Functional Programming Matters” 中,作者 John Hughes 说明了模块化是成功编程的关键,而函数编程可以极大地改进模块化。在函数编程中,我们有一个内置的框架来开发更小的、更简单的和更一般化的模块, 然后将
  • 8.4 组合与范畴
  • 函数式编程的本质是函数的组合,组合的本质是范畴(Category)。和搞编程的一样,数学家喜欢将问题不断加以抽象从而将本质问题抽取出来加以论证解决,范畴论就是这样一门以抽象的方法来处理数学概念的学科,主要用于研究一些数学结构之间的映射关系(函数)。在范畴论里,一个范畴(category)由三部分组成: 1.对象(object) 2.态射(morphism) 3.组合(
  • 8.5 Kotlin中的函数
  • 首先,我们来看下Kotlin中函数的概念。#### 函数声明Kotlin 中的函数使用 fun 关键字声明 fun double(x: Int): Int {return 2*x } 函数用法 调用函数使用传统的方法 ```kotlin fun test() {val doubleTwo = double(2)println(&quot;double(2)
  • 8.6 扩展函数
  • 通过 扩展 声明完成一个类的新功能 扩展 ,而无需继承该类或使用设计模式(例如,装饰者模式)。一个扩展String类的swap函数的例子: fun String.swap(index1: Int, index2: Int): String {val charArray = this.toCharArray()val tmp = charArray[in
  • 8.7 中缀函数
  • 在以下场景中,函数还可以用中缀表示法调用: .成员函数或扩展函数 .只有一个参数 .用 infix 关键字标注 例如,给 Int 定义扩展 infix fun Int.shl(x: Int): Int {... } 用中缀表示法调用扩展函数: 1 shl 2 等同于这样 1
  • 8.8 函数参数
  • 函数参数使用 Pascal 表示法定义,即 name: type。参数用逗号隔开。每个参数必须显式指定其类型。 fun powerOf(number: Int, exponent: Int): Int {return Math.pow(number.toDouble(), expone
  • 8.9 函数返回类型
  • 函数参数使用 Pascal 表示法定义,即 name: type。参数用逗号隔开。每个参数必须显式指定其类型。 fun powerOf(number: Int, exponent: Int): Int {return Math.pow(number.toDouble(), exponent.toDouble()).toInt() } 测试代码: val eight = powerOf(
  • 8.10 单表达式函数
  • 当函数返回单个表达式时,可以省略花括号并且在 = 符号之后指定代码体即可 fun double(x: Int): Int = x * 2 当返回值类型可由编译器推断时,显式声明返回类型是可选的: fun double(x: Int) = x * 2
  • 8.11 函数作用域
  • 在 Kotlin 中函数可以在文件顶层声明,这意味着你不需要像一些语言如 Java、C# 或 Scala 那样创建一个类来保存一个函数。此外除了顶层函数,Kotlin 中函数也可以声明在局部作用域、作为成员函数以及扩展函数。#### 局部函数(嵌套函数)Kotlin 支持局部函数,即一个函数在另一个函数
  • 8.12 泛型函数
  • 函数可以有泛型参数,通过在函数名前使用尖括号指定。 例如Iterable的map函数: public inline fun &lt;T, R&gt; Iterable&lt;T&gt;.map(transform: (T) -&gt; R
  • 8.13 高阶函数
  • 高阶函数是将函数用作参数或返回值的函数。例如,Iterable的filter函数: public inline fun &lt;T&gt; Iterable&lt;T&gt;.filter(predicate: (T) -&gt; Boolean): List&lt;T&gt; {return filterTo(ArrayList
  • 8.14 匿名函数
  • 我们也可以使用匿名函数来实现这个predicate函数: list.filter((fun(x: Int): Boolean {return x % 2 == 1 }))
  • 8.15 Lambda 表达式
  • 我们也可以直接使用更简单的Lambda表达式来实现一个predicate函数: list.filter {it % 2 == 1 } .lambda 表达式总是被大括号 {} 括着 .其参数(如果有的话)在 -&gt; 之前声明(参数类型可以省略) .函数体(如果存在的话)在 -&gt; 后面 上面的写法跟: list.filter({it
  • 8.16 it:单个参数的隐式名称
  • 单个参数的隐式名称 Kotlin中另一个有用的约定是,如果函数字面值只有一个参数, 那么它的声明可以省略(连同 -&gt;),其名称是 it。 代码示例: &gt;&gt;&gt; val list = listOf(1,2,3,4,5) &gt;&gt;&gt; list.map { it * 2 } [2, 4, 6, 8, 10]
  • 8.17 闭包(Closure)
  • Lambda 表达式或者匿名函数,以及局部函数和对象表达式(object declarations)可以访问其 闭包,即在外部作用域中声明的变量。 与 Java 不同的是可以修改闭包中捕获的变量: fun sumGTZe
  • 8.18 带接收者的函数字面值
  • Kotlin 提供了使用指定的 接收者对象 调用函数字面值的功能。使用匿名函数的语法,我们可以直接指定函数字面值的接收者类型。下面我们使用带接收者的函数类型声明一个变量,并在之后使用它。代码示例: &gt;&gt;&gt; val sum = fun Int.(other: Int): Int = this + other &gt;&gt
  • 8.19 具体化的类型参数
  • 有时候我们需要访问一个参数类型: fun &lt;T&gt; TreeNode.findParentOfType(clazz: Class&lt;T&gt;): T? {var p = parentwhile (p != null &amp;&amp; !clazz.isInstance(p)) {p = p
  • 8.20 尾递归tailrec
  • Kotlin 支持一种称为尾递归的函数式编程风格。 这允许一些通常用循环写的算法改用递归函数来写,而无堆栈溢出的风险。 当一个函数用 tailrec 修饰符标记并满足所需的形式时,编译器会优化该递归,生成一个快速而高效的基
  • 8.21 本章小结
  • 本章我们一起学习了函数式编程的简史、Lambda演算、Y组合子与递归等核心函数式的编程思想等相关内容。然后重点介绍了在Kotlin中如何使用函数式风格编程,其中重点介绍了Kotlin中函数的相关知识,以及高阶函数、Lambda表达式、闭包等核心语法,并给出相应的实例说明。我们将在下一章 中介绍Kotlin的 轻量级线程:协程(Cor
  • 第九章 轻量级线程:协程
  • 9.1 协程简介
  • 从硬件发展来看,从最初的单核单CPU,到单核多CPU,多核多CPU,似乎已经到了极限了,但是单核CPU性能却还在不断提升。如果将程序分为IO密集型应用和CPU密集型应用,二者的发展历程大致如下: IO密集型应用: 多进程-&gt;多线程-&gt;事件驱动-&gt;协程 CPU密集型应用:多进程-&gt;多线
  • 9.4 协程是轻量级的
  • 直接运行下面的代码: fun testThread() {val jobs = List(100_1000) {Thread({Thread.sleep(1000L)print(&quot;.&quot;)})}jobs.forEach { it.start() }jobs.forEach { it.join() } } 我们应该会看到输出报错
  • 9.5 协程 vs 守护线程
  • 在Java中有两类线程:用户线程 (User Thread)、守护线程 (Daemon Thread)。所谓守护线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因此,当所有的非守护线程结束时,程序也就终止了,同时
  • 9.6 协程执行的取消
  • 我们知道,启动函数launch返回一个Job引用当前协程,该Job引用可用于取消正在运行协程: fun testCancellation() = runBlocking&lt;Unit&gt; {val job = launch(CommonPool) {repeat(1000) { i -&gt;print
  • 9.7 设置协程超时时间
  • 我们通常取消协同执行的原因给协程的执行时间设定一个执行时间上限。我们也可以使用 withTimeout 函数来给一个协程任务的执行设定最大执行时间,超出这个时间,就直接终止掉。代码示例如下: fun testTimeouts() = runBlocking {withTimeou
  • 9.8 挂起函数的组合执行
  • 本节我们介绍挂起函数组合的各种方法。9.8.1 按默认顺序执行 假设我们有两个在别处定义的挂起函数: suspend fun doJob1(): Int {println(&quot;Doing Job1 ...&quot;)delay(1000L) //
  • 9.9 协程上下文与调度器
  • 到这里,我们已经看到了下面这些启动协程的方式: launch(CommonPool) {...} async(CommonPool) {...} run(NonCancellable) {...} 这
  • 9.10 通道
  • 延迟对象提供了一种在协程之间传输单个值的方法。而通道(Channel)提供了一种传输数据流的方法。通道是使用 SendChannel 和使用 ReceiveChannel 之间的非阻塞通信。9.10.1 通道 vs 阻塞队列 通道的概念类似于 阻塞队列(BlockingQueu
  • 9.11 管道
  • 9.11.1 生产无限序列 管道(Pipeline)是一种模式, 我们可以用一个协程生产无限序列: fun produceNumbers() = produce&lt;Long&gt;(CommonPool) {var x = 1Lwhile (true) send(x++) // infinite stream of integers starting from 1 } 我们的消费序列的函
  • 9.12 构建无穷惰性序列
  • 我们可以使用 buildSequence 序列生成器 ,构建一个无穷惰性序列。 val fibonacci = buildSequence {yield(1L)var current = 1Lvar next = 1Lwhile (true) {yield(next)val tmp = current + next
  • 9.13 协程与线程比较
  • 直接先说区别,协程是编译器级的,而线程是操作系统级的。协程通常是由编译器来实现的机制。线程看起来也在语言层次,但是内在原理却是操作系统先有这个东西,然后通过一定的API暴露给用户使用,两者在这里有不同。协程就是用户空间下的线程。用
  • 9.14 协程的好处
  • 与多线程、多进程等并发模型不同,协程依靠user-space调度,而线程、进程则是依靠kernel来进行调度。线程、进程间切换都需要从用户态进入内核态,而协程的切换完全是在用户态完成,且不像线程进行抢占式调度,协程是非抢占式的调度。通常多个运行在同一调度器中的协程运行在一个线程内,这也消除掉了多线程同步等带来的编程复杂性。同一时刻同一调度器中的协程只有一个会处
  • 本章小结
  • 本章我通过大量实例学习了协程的用法;同时了解了作为轻量级线程的协程是怎样简化的我们的多线程并发编程的。我们看到协程通过挂起机制实现非阻塞的特性大大提升了我们并发性能。最后,我们还简单介绍了协程的实现的原理以及标准API库。Kotlin的协程的实现大量地调用了Java中的多线程API。所以在Kotlin中,我们仍然完全可以使用Java中的多线程编程。下
  • 9.2 桥接 阻塞和非阻塞
  • 上面的例子中,我们给出的是使用非阻塞的delay函数,同时又使用了阻塞的Thread.sleep函数,这样代码写在一起可读性不是那么地好。让我们来使用纯的Kotlin的协程代码来实现上面的 阻塞+非阻塞 的例子(不用Thread)。9.2.1 runBlocking函数 Kotlin中提供了runBlocking函数来实现类似主协程的功能: f
  • 9.3 等待一个任务执行完毕
  • 我们先来看一段代码: fun firstCoroutineDemo() {launch(CommonPool) {delay(3000L, TimeUnit.MILLISECONDS)println(&quot;[firstCoroutineDemo] Hello, 1&quot;)}launch(CommonPoo
  • 第十章 Kotlin与Java互操作
  • 10.1 Kotlin 调用 Java示例
  • Kotlin 很像 Java。它长得不像 Clojure 或者 Scala 那么奇怪(承认现实吧,这两种语言就是挺奇怪的)。所以我们学 Kotlin 应该很快。这门语言显然就是写给 Java 开发者来用的。Kotlin 在设计之初就考虑了与 Java 的互操作性。我们可以从 Kotlin
  • 10.2 Kotlin使用Java的集合类
  • Kotlin的集合类API很多就是直接使用的Java的API来实现的。我们在使用的时候,毫无违和感,自然天成: @RunWith(JUnit4::class) class KotlinUsingJavaTest {
  • 10.3 Kotlin调用Java中的Getter 和 Setter
  • 在Java中遵循这样的约定: getter 方法无参数并以 get 开头,setter 方法单参数并以 set 开头。在 Kotlin 中我们可以直接表示为属性。 例如,我们写一个带setter和getter的Java类: package com.easy.kotlin; import java.util.Date; public class Product {Long id;String
  • 10.4 调用Java中返回 void 的方法
  • 如果一个 Java 方法返回 void,那么从 Kotlin 调用时中返回 Unit。 public class Admin {String name;public void setName(String name) {this.name = name;}@Overridepublic String toString() {return &quot;Admin{&quot;
  • 10.5 空安全和平台类型
  • 我们知道Java 中的任何引用都可能是null,这样我们在使用 Kotlin 调用来自 Java 的对象的时候就有可能会出现空安全的问题。Java 声明的类型在 Kotlin 中会被特别对待并称为平台类型(platform types )。对这种类型的空检查会放宽,因此它们的安全保证与在 J
  • 10.6 平台类型
  • 平台类型不能在程序中显式表述,因此在语言中没有相应语法。 然而,编译器和 IDE 有时需要(在错误信息中、参数信息中等)显示他们,所以我们用一个助记符来表示他们: .T! : 表示 T 或者 T? .(Mutable) Collection&lt;T&gt;! : 表示 “可以可变或不可变、可空或不可空的 T 的 Java 集合”.Arra
  • 10.7 Kotlin与Java中的类型映射
  • Kotlin 特殊处理一部分 Java 类型。这样的类型不是“按原样”从 Java 加载,而是映射到相应的 Kotlin 类型。映射只发生在编译期间,运行时表示保持不变。Java 的原生类型映射到相应的 Kotlin 类型:Java 类型Kotlin 类型bytekotlin.Byteshortkotlin.Shortintkotlin.Intlongkotlin.Longcharko
  • 10.8 Kotlin 中使用 Java 的泛型
  • Kotlin 的泛型与 Java 有点不同。当将 Java 类型导入 Kotlin 时,我们会执行一些转换:Kotlin 的泛型Java 的泛型说明Foo&lt;out Bar!&gt;!Foo&lt;? extends Bar&gt;Java 的通配符转换成类型投影Foo&lt;? super Bar&gt;Foo&l
  • 10.9 Kotlin与Java 中的数组
  • 与 Java 不同,Kotlin 中的数组是非型变的,即 Kotlin 不允许我们把一个 Array&lt;String&gt; 赋值给一个 Array&lt;Any&gt;。Java 平台上,持有原生数据类型的数组避免了装箱/拆箱操作的开销。在Kotlin中,对于每种原生类型的数组都有一个特化的类(In
  • 10.10 Java 可变参数
  • Java 类有时声明一个具有可变数量参数(varargs)的方法来使用索引。 public class VarArgsDemo&lt;T&gt; {static VarArgsDemo vad = new VarArgsDemo();public
  • 10.11 非受检异常
  • 在 Kotlin 中,所有异常都是非受检的(Non-Checked Exceptions),这意味着编译器不会强迫你捕获其中的任何一个。而在Java中会要求我们捕获异常,例如下面的代码:也就是说,我们需要写类似下面的try catch代码块: try {jsonUtils.parseObject(&quot;{}&quot;); } catch (
  • 10.12 对象方法
  • Java中的java.lang.Object定义如下: public class Object {private static native void registerNatives();static {registerNatives();}public final native Class&lt;?&gt; getClass();public native int hashCode();pu
  • 10.13 访问静态成员
  • Java 类的静态成员会形成该类的“伴生对象”。我们可以直接显式访问其成员。例如:一个带静态方法的Java类 public class JSONUtils {public static String toJsonString(Object o) {return JSON.
  • 10.14 Kotlin与Java 的反射
  • 我们可以使用 instance::class.java、ClassName::class.java 或者 instance.javaClass 通过 java.lang.Class 来进入 Java 的反射类java.lang.Class, 之后我们就可以使用Ja
  • 10.15 SAM 转换
  • 我们在Kotlin中,要某个函数做某件事时,会传一个函数参数给它。 而在Java中,并不支持传送函数参数。通常Java的实现方式是将动作放在一个实现某接口的类中,然后将该类的一个实例传递给另一个方法。在大多数情况下,这些接
  • 10.16 Java 调用 Kotlin
  • 一些 Kotlin 关键字在 Java 中是有效标识符:in、 object、 is等等。如果一个 Java 库使用了 Kotlin 关键字作为方法,我们可以通过反引号(`)字符转义它来调用该方法。例如我们有个Java类,其中有个is方法: public class MathTools {public boolean is(Object o)
  • 10.17 Java访问Kotlin属性
  • Kotlin 属性会编译成以下 Java 元素: .一个 getter 方法,名称通过加前缀 get 算出; .一个 setter 方法,名称通过加前缀 set 算出(只适用于 var 属性); .一个与属性名称相同的私有字段。 例如,下面的Kotlin类: class
  • 10.18 Java调用Kotlin的包级函数
  • 在 package com.easy.kotlin 包内的 KotlinExample.kt 源文件中声明的所有的函数和属性,包括扩展函数,都将编译成一个名为 com.easy.kotlin.KotlinExampleKt 的 J
  • 10.19 实例字段
  • 我们使用 @JvmField 注解对Kotlin中的属性字段标注,表示这是一个实例字段(Instance Fields),Kotlin编译器在处理的时候,将不会给这个字段生成getters/setters方法。 class Department {var id: Long = -1Lvar name: String = &quot;Dep
  • 10.20 静态字段
  • Kotlin中在命名对象或伴生对象中声明的属性: class Department {...companion object {var innerID = &quot;X001&quot;@JvmFieldvar innerNa
  • 10.21 静态方法
  • Kotlin 中,我们还可以将命名对象或伴生对象中定义的函数标注为 @JvmStatic,这样编译器既会在相应对象的类中生成静态方法,也会在对象自身中生成实例方法。跟静态属性类似的,我们看下面的代码示例: class Department {...companion object {var innerID = &quot;X001&quot;@JvmFieldvar inner
  • 10.22 可见性
  • Kotlin 的可见性与Java的可见性的映射关系如下表所示:例如下面的Kotlin代码: class ProgrammingBook {private var isbn: String = &quot;978-7-111-44250-9&quot;protected var author:
  • 10.23 生成默认参数值函数的重载
  • 我们在Kotlin中写一个有默认参数值的 Kotlin 方法,它会对每一个有默认值的参数都生成一个重载函数。这样的Kotlin函数,在 Java 中调用的话,只会有一个所有参数都存在的完整参数签名方法可见。如果我们希望Java像Kotlin中一样可以调用多个重载,可以使用@JvmOverloads注解。下面我们来通过一个实例对比两者的
  • 10.24 检查Kotlin中异常
  • 如上所述,Kotlin 没有受检异常。即像下面像这样的 Kotlin 函数: class CheckKotlinException {fun thisIsAFunWithException() {throw Exception(&quot;I am an exception in kotlin&quot;)} } 在Java中调用,编译器是不会检查这个异常的: @Test pu
  • 10.25 Kotlin与Java对比
  • 在前面的内容里,我们已经看到了Java与Kotlin的互操作的基本方式。为了更好的认识Java与Kotlin这两门语言,我们在这里给出一些基本功能,同时使用Java与Kotlin来实现的代码实例。通过横向对比,从中我们可以看出它们的异同。 (此处可整理成表格形式) 打印日志 Java System.out.print(&quot;Java&qu
  • 本章小结
  • 章我们一起学习了Kotlin与Java的互操作,同时我们用一些简单的示例对比了它们的异同。在这之中,我们能感受到Kotlin的简洁、优雅。 我们可以用更少的代码来实现更多的功能。 另外,在IDEA中,我们可以直接使用Kotlin插件来直接进行J
  • 第十一章 使用Kotlin集成SpringBoot开发Web服务端
  • 11.1 Spring Boot简介
  • SpringBoot是伴随着Spring4.0诞生的。从字面理解,Boot是引导的意思,SpringBoot帮助开发者快速搭建Spring框架、快速启动一个Web容器等,使得基于Spring的开发过程更加简易。 大部分Spring Boot Application只要一些极简的配置,即可“一键运行”。 SpringBoot的特性如下: 1.创建独立的Spring applications 2.
  • 11.2 统架构技术栈
  • 本节我们介绍使用 Kotlin 集成 Spring Boot 开发一个完整的博客站点的服务端Web 应用, 它支持 Markdown 写文章, 文章列表分页、搜索查询等功能。其系统架构技术栈如下表所示:
  • 11.3 环境准备
  • 首先,我们使用SPRING INITIALIZR来创建一个模板工程。 第一步:访问 http://start.spring.io/, 选择生成一个Gradle项目,使用Kotlin语言,使用的Spring Boot版本是2.0.0 M2。 第二步: 配置项目基本信息。 Group: com
  • 11.4 数据库层配置
  • 上面的模板工程,我们来直接运行main函数,会发现启动失败,控制台会输出如下报错信息: BeanCreationException: Error creating bean with name &#39;dataSource&#39; defined in class
  • 11.5 Endpoint监控接口
  • 我们来尝试访问:http://127.0.0.1:8000/application/beans ,浏览器显示如下信息: Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this
  • 11.6 数据库实体类
  • 我们在上面已经完成了MySQL数据源的配置,下面我们来写一个实体类。新建package com.easy.kotlin.chapter11_kotlin_springboot.entity ,然后新建Article实体类: package com.easy.kotlin.chapter11_kotlin_springboot.entit
  • 11.7 数据访问层代码
  • 在Spring Data JPA中,我们只需要实现接口CrudRepository&lt;T, ID&gt;即可获得一个拥有基本CRUD操作的接口实现了: interface ArticleRepository : CrudRepository&lt;Article, Long&gt; JPA会自动实现ArticleRepository接口中的方法,不需要我们写基本的CRUD操作代码。它的常用的
  • 11.8 控制器层
  • 我们新建子目录controller,然后在下面新建控制器类: @Controller class ArticleController { } 我们首先,装配数据访问层的接口Bean: @Autowired val articleRepository: ArticleRepository? = nul
  • 11.9 启动初始化CommandLineRunner
  • 为了方便测试用,我们在SpringBoot应用启动的时候初始化几条数据到数据库里。Spring Boot 为我们提供了一个方法,通过实现接口 CommandLineRunner 来实现。这是一个函数式接口: @FunctionalInterface public interface CommandLineRunner {void run(String... args) throws
  • 11.10 应用启动类
  • 我们在main函数中调用SpringApplication类的静态run方法,我们的SpringBootApplication主类代码如下: package com.easy.kotlin.chapter11_kotlin_springboot impo
  • 11.11 Model数据绑定
  • 我们写一个返回ModelAndView对象控制器类,其中数据模型Model中放入文章列表数据,代码如下: @GetMapping(&quot;listAllArticleView&quot;) fun listAllArticleView(model: Model): ModelAndView {mod
  • 11.12 模板引擎视图页面
  • 我们使用Freemarker模板引擎。我们在templates目录下新建一个list.ftl文件,内容如下: &lt;html&gt; &lt;head&gt;&lt;title&gt;Blog!!!&lt;/title&gt; &lt;/head&gt; &lt;body&gt; &lt;table&gt;&lt;thead&gt;&lt;th&gt;序号&lt;/th&gt
  • 11.13 运行测试
  • 重启应用,浏览器访问 : http://127.0.0.1:8000/listAllArticleView ,我们可以看到页面输出:到这里,我们已经完成了一个从数据库到前端页面的完整的一个极简的Web应用。
  • 11.14 引入前端组件
  • 我们使用基于Bootstrap的前端UI库Flat UI。首先去Flat UI的首页:http://www.bootcss.com/p/flat-ui/ 下载zip包,加压后,放到我们的工程里,放置的目录是:src/main/resources/static 。如下图所示:我们在list.ftl头部引入静态资源文件: &lt;head&gt;&lt;meta char
  • 11.15 实现写文章模块
  • 我们在列表页上面添加一个“写文章”的入口: &lt;a href=&quot;addArticleView&quot; target=&quot;_blank&quot; class=&quot;btn bt
  • 11.16 添加Markdown支持
  • 我们写技术博客文章,最常用的就是使用Markdown了。我们来为我们的博客添加Markdown的支持。我们使用前端js组件Mditor来支持Markdown的编辑。 Mditor是一个简洁、易于集成、方便扩展、期望舒服的编写 markdown 的编辑器。 11.16.1 引入静态资源 &lt;link href=&quot;/mditor
  • 11.17 文章列表分页搜索
  • 为了方便检索我们的博客文章,我们再来给文章列表页面添加分页、搜索、排序等功能。我们使用前端组件DataTables来实现。提示:更多关于DataTables,可参考: http://www.datatables.club/11.17.1 引入静态资源文件 &lt;link href=
  • 11.18 Spring 5.0对Kotlin的支持
  • Kotlin 关键性能之一就是能与 Java 库很好地互用。但要在 Spring 中编写惯用的 Kotlin 代码,还需要一段时间的发展。 Spring 对 Java 8 的新支持:函数式 Web 编程、bean 注册 API , 这同样可以在 Kotlin 中使用。Kotlin 扩展是Kotlin 的编程利器。它能对现有的 API 实现非侵入式的扩展
  • 本章小结
  • 本章我们较为细致完整地介绍了使用Kotlin集成SpringBoot进行服务后端开发,并结合简单的前端开发,完成了一个极简的技术博客Web站点。我们可以看到,使用Kotlin结合Spring Boot、Spring MVC、JPA等Java框架的无缝集成,关键是大大简化了我们的代码。同时,在本章最后我们简单介绍了Spring 5.0中对Kotlin的支持诸多新特性,这些新特性令人惊喜。使
  • 第十二章 使用Kotlin集成Gradle开发
  • 源仓库中,开源书籍作者把第 11 章作为了第 12 章的内容,请关注作者仓库的更新: https://github.com/JackChan1999/EasyKotlin/blob/master/12.%E4%BD%BF%E7%94%A8Kotlin%E9%9B%86%E6%88%90Gradle%E5%BC%80%E5%8F%91/%E7%AC%AC12%E7%AB
  • 第十三章 使用 Kotlin 和 Anko 的Android 开发
  • 13.1 什么是 Anko?
  • Anko 是一个用 Kotlin 写的Android DSL (Domain-Specific Language)。长久以来,Android视图都是用 XML 来完成布局的。这些 XML可重用性比较差。同时在运行的时候,XML 要转换成 Java 表述,这在一定程度上占用了 CPU 和耗费了电量。Anko
  • 13.2 一个简单Anko视图
  • 这里是一个转换成 Anko 的简单 XML 文件。 &lt;LinearLayoutxmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;android:layout_height=&quot;match_parent&quot;android:layout_width=&quot;match_par
  • 13.3 快速入门实例
  • 下面我们通过一个“我的日程”待办事项应用,来详细介绍使用 Kotlin 混合 Java,使用 Anko 开发的Android 应用的方法。移动端数据库引擎我们使用 Realm,视图绑定使用Butter Knife。这个应用程序界面如下所示:
  • 13.4 使用 Android Studio 新建工程
  • 我们首先在 Android Studio 中新建工程,步骤如下: 第一步,新建项目第二步,配置项目基本信息第三步,设置支持设备以及 SDK 版本第四步,选择 Basic Activity第五步,使用默认的Activity命名我们将得到一个标准的 Gradle Android 工程:其中,app 工程 src 目录如下:. ├──
  • 13.5 设计UI 界面主题颜色
  • 我们首先把应用名称改成“我的日程”。在文件MyTodoApplication/app/src/main/res/values/strings.xml中: &lt;resources&gt;&lt;string name=&quot;a
  • 13.6 配置 Kotlin 与 Anko 依赖
  • 我们默认生成的 app 项目的 Gradle 配置文件build.gradle如下: apply plugin: &#39;com.android.application&#39; android {compileSdkVersion 25buildToolsVersion &quot;25.0.3&quot;defaultConfig {applicationId &quot;com.easy
  • 13.7 将MainActivity.java 转成 Kotlin 代码
  • 选中默认生成的MainActivity.java, 我们使用 IDEA 的 Code &gt; Convert Java File to Kotlin File :点击转换,即可看到转换成 Kotlin 的代码: package com.easy.kotlin.mytodoapplicatio
  • 13.8 在 Kotlin 中使用 Realm
  • 我们需要添加针对 Kotlin 的realm注解处理的库: kapt &quot;io.realm:realm-annotations:0.87.1&quot; kapt &quot;io.realm:realm-annotations-processor:0.87.1&quot;
  • 13.9 添加日程实体类
  • 我们先从领域模型的建立开始。首先我们需要设计一个极简的待办事项的实体类 Todo, 它有主键 id、标题、内容三个字段。 @RealmClass open class Todo : RealmObject() {@PrimaryKeyopen var id: String = &quot;-1&quot;open var title: String = &quot;日程&q
  • 13.10 添加日程事件
  • 现在我们点击添加日程的浮层按钮中,添加切换到 “日程添加编辑” TodoEditFragment的逻辑。 // 添加日程事件 fab?.setOnClickListener { _ -&gt;// Snackb
  • 13.11 添加日程界面
  • 下面我们来完成这个添加日程的界面。我们采用Fragment来实现。首先新建一个TodoEditFragment继承Fragment() : class TodoEditFragment : Fragment() {val realm: Realm = Realm.getDefaultInstance()var todo: Todo? = nullcompan
  • 13.12 保存到 Realm 中
  • 新增待办事项,存入Realm数据库: private fun createTodoFrom(title: EditText, todoContent: EditText) {realm.beginTransaction()// Either update the edited object or create a new
  • 13.13 用RecyclerView 来展示待办事项
  • 下面我们来实现这个页面。首先,这个是主页面,对应 activity_main.xml 视图, 文件内容如下: &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt; &lt;android.support.design.widg
  • 13.14 运行测试
  • 编译安装应用,我们就可以看到如下的界面了,我们可以在里面添加编辑我们的待办事项。
  • 本章小结
  • Android 中经常出现的空引用、API的冗余样板式代码等都是是驱动我们转向 Kotlin 语言的动力。另外,Kotlin 的 Android 视图 DSL Anko帮我们从繁杂的 XML 视图配置文件中解放出来。我们可以像在 Java 中一样方便的使用 And
  • 第十四章 使用 Kotlin DSL
  • 14.1 DSL 是什么
  • DSL 是什么 DSL(Domain-Specific Language,领域特定语言)指的是专注于特定问题领域的计算机语言(领域专用语言)。不同于通用的计算机语言(GPL),领域特定语言只用在某些特定的领域。 比如用来显示网页的HTML语言,以及Emacs所使用的Emac LISP语言等。更加典型的例子是Gradle,它基
  • 14.2 Kotlin 的 DSL 特性支持
  • Kotlin 的 DSL 特性支持 扩展(eXtension)特性。
  • 14.3 实现一个极简的 DSL
  • OkHttp是一个成熟且强大的网络库,在Android源码中已经使用OkHttp替代原先的HttpURLConnection。很多著名的框架例如Picasso、Retrofit也使用OkHttp作为底层框架。在这里我对OkHttp做一下简单的封装,其实封装得有点粗暴只是为了演示如何实现dsl。 impor
  • 14.4 使用kotlinx.html DSL 写前端代码
  • kotlinx.html是可在 Web 应用程序中用于构建 HTML 的 DSL。 它可以作为传统模板系统(例如JSP、FreeMarker等)的替代品。kotlinx. html 分别提供了kotlinx-html-jvm 和 kotlinx-html-js库的DSL , 用于在 JVM 和浏览器 (或其他 javascript 引擎) 中直接使用 Kotlin 代码来构建 html, 直接解
  • 第十五章 Kotlin 文件IO操作与多线程
  • 15.1 Kotlin IO 简介
  • Kotlin的IO操作都在kotlin.io包下。Kotlin的原则就是Java已经有的,好用的就直接使用,没有的或者不好用的,就在原有类的基础上进行封装扩展,例如Kotlin 就给 File 类写了扩展函数。这跟Groovy的扩展API 的思想是一样的。
  • 15.2 终端 IO
  • Java 超长的输出语句 System.out.println() 居然延续到了现在!同样的工作在C++里面只需要简单的 cout&lt;&lt; 就可以完成。当然,如果需要的话,我们可以在工程中直接封装 System.out.println() 为简单的打印方法。在Kotlin里面很简单,只需要使用println或者print这两个全局函数即可,我们不再需要冗长的前缀。当然如果
  • 15.3 文件 IO 操作
  • Kotlin为java.io.File提供了大量好用的扩展函数,这些扩展函数主要在下面三个源文件中: kotlin/io/files/FileTreeWalk.kt kotlin/io/files/Utils.kt kotlin/io/FileReadWrite.kt 同时,Kotlin 也针对InputStream、OutputStream和 Re
  • 15.4 遍历文件树
  • 和Groovy一样,Kotlin也提供了方便的功能来遍历文件树。遍历文件树需要调用扩展方法walk()。它会返回一个FileTreeWalk对象,它有一些方法用于设置遍历方向和深度,详情参见FileTreeWalk API 文档说明。 提示:FileTreeWalk API 文档链接下面的例子遍历了指定文件夹下的所有文件。 fun traverseF
  • 15.5 网络IO操作
  • Kotlin为java.net.URL增加了两个扩展方法,readBytes和readText。我们可以方便的使用这两个方法配合正则表达式实现网络爬虫的功能。下面我们简单写几个函数实例。根据 url 获取该 url 的响应 HTML函数 fu
  • 15.6 kotlin.io标准库
  • Kotlin 的 io 库主要是扩展 Java 的 io 库。下面我们简单举几个例子。 appendBytes 追加字节数组到该文件中 方法签名: fun File.appendBytes(array: ByteArray) appendText 追加文本到该文件中 方法签名: fun File.appendText(text:
  • 15.7 执行Shell命令行
  • 我们使用 Groovy 的文件 IO 操作感觉非常好用,例如 package com.easy.kotlin import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 @RunWith(JUnit4)
  • 15.8 正则表达式
  • 我们在 Kotlin 中除了仍然可以使用 Java中的 Pattern,Matcher 等类之外,Kotlin 还提供了一个正则表达式类 kotlin/text/regex/Regex.kt ,我们通过 Regex 的构造函数来创建一个正则表达式。15.8.1 构造 Regex 表达式 使用Regex构造函数 &gt;&g
  • 15.9 Kotlin 的多线程
  • Kotlin中没有synchronized关键字。 Kotlin中没有volatile关键字。 Kotlin的Any类似于Java的Object,但是没有wait(),notify()和notifyAll() 方法。那么并发
  • 本章小结
  • Kotlin 是一门工程实践性很强的语言,从本章介绍的文件IO、正则表达式以及多线程等内容中,我们可以领会到 Kotlin 的基本原则:充分使用已有的 Java 生态库,在此基础之上进行更加简单实用的扩展,大大提升程序员们的
  • 第十六章 使用 Kotlin Native
  • 16.1 Kotlin Native 简介
  • Kotlin Native利用LLVM来编译到机器码。Kotlin Native 主要是基于 LLVM后端编译器(Backend Compiler)来生成本地机器码。Kotlin Native 的设计初衷是为了
  • 16.2 快速开始 Hello World
  • 16.2.1 运行环境准备 我们直接去 Github上面去下载 kotlin-native 编译器的软件包。下载地址是 :https://github.com/JetBrains/kotlin-native/releases下载解压之后,我们可以看到 Kotlin
  • 16.3 Kotlin Native 编译器 konan 简介
  • 本小节我们简单介绍一下Kotlin Native 编译器的相关内容(主要以 Mac OS 平台示例)。bin目录 bin目录下面是执行命令行 cinterop klib konanc kotlinc kotlinc-native run_konan run_konan 是真正的入口 shell,它
  • 本章小结(全书完)
  • 本章工程源码: https://github.com/EasyKotlin/chatper16_kotlin_native_helloworld现在我们可以把 Kotlin 像C 一样地直接编译成的机器码来运行,这样在 C 语言出现的地方(例如应用于嵌入式等对性能要求比较高的场景),Kotlin 也来了。Kotlin 将会在嵌入式系统
读者评论
  • 你还没登录,点击这里
  • 本书评论
最近这些人在读这本书