前言
1.这本书是对比着 java、scala来介绍kotlin,这里笔记重点只在java和kotlin。
2.开始之前最好idea下载插件
kotlin to java decompiler 很方便!
kotlin介绍
kotlin简介
1.基于JVM平台
2.Kotlin在2017年Google I/O大会之后,也成为安卓平台上潜力巨大的官方支持语言。但不仅仅只适用于安卓。
3.JetBrains开发idea全家桶完全支持
4.核心目标:完全兼容Java,为java程序员提供一门更好的语言
5.在java的基础上进行了一些改良,“简单灵活”的另一面意味着抽象和晦涩
6.如果你很喜欢java8的高阶函数和lambda、stream和optional这种函数式编程你也会喜欢kotlin并且会更容易上手。
基础语法
类型声明
java
类型 变量名 值
String a = "I am Java";
kotlin
变量名 类型 值
val a: String = "I am Kotlin"
// 关于val下文有讲述
与java完全相反
官方的解释:
我们相信这样可以使得代码的可读性更好。同时,这也有利于使用一些良好的语法特性,比如省略类型声明。Scala的经验表明,这不是一个错误的选择。
。。好吧
类型推导
val a: String = "I am Kotlin"
可以简写为
val b = "I am Kotlin"
------------------
fun main(args: Array<String>) {
val a: String = "I am Kotlin"
val b = "I am Kotlin"
// sout 快捷键一样的
println(a.javaClass.name)
println(b.javaClass.name)
}
------------------
java.lang.String
java.lang.String
编译器可以在不显式声明类型的情况下,自动推导出它所需要的类型。
声明函数返回值类型
关键字fun 定义一个函数
sum 函数名
x,y 参数 int参数类型
: Int 返回值
fun sum(x: Int, y: Int): Int {
return x + y
}
没有声明返回值的话会默认返回Unit类型,可以暂时理解为java的void
fun sum(x: Int, y: Int){
}
你还可以这么写
fun main(args: Array<String>) {
fun sum(x: Int, y: Int) = x + y
println(sum(1,2))
}
前置的参数限制使它不需要显示声明返回值
这种用单行表达式与等号的语法来定义函数,叫作表达式函数体,作为区分,普通的函数声明则可叫作代码块函数体
----------------------------
但是在一些诸如递归的复杂情况下,即使用表达式定义函数,我们也必须显式声明类型
fun foo(n: Int): Int = if (n == 0) 1 else n * foo(n - 1)
是否需要显式声明类型的总结:
·如果它是一个函数的参数?
必须使用。
·如果它是一个非表达式定义的函数?
除了返回Unit,其他情况必须使用。
·如果它是一个递归的函数?
必须使用。
·如果它是一个公有方法的返回值?
为了更好的代码可读性及输出类型的可控性,建议使用。
除上述情况之外,你可以尽量尝试不显式声明类型,直到你遇到下一个特殊情况。
val和var
val声明的可以看作Java中被final修饰的常量,即引用不可变。
var声明即变量
抽象、高阶函数和Lambda
1.抽象
《计算机程序的构造和解释》这本经典的书籍的开篇,有一段关于抽象这个概念的描述:
心智的活动,除了尽力产生各种简单的认识外,主要表现在如下3个方面:
1)将若干简单的认识组合为一个复合认识,由此产生出各种复杂的认识;
2)将两个认识放在一起对照,不管它们如何简单或者复杂,在这样做时并不将它们合二为一;由此得到有关它们的相互关系的认识;
3)将有关认识与那些在实际中和它们同在的所有其他认识隔离开,这就是抽象,所有具有普遍性的认识都是这样得到的。
2.函数
之前的认识是总结抽象事物的规律并且得出一个结果
书上给了一个例子:
2岁左右的小孩就会开始认知数字1、2、3……之后,我们总结出了一些公共的行为,如对数字做加减、求立方,这被称为过程
它接收的数字是一种数据,然后也可能产生另一种数据。
定义过程的能力,也就是函数。
有画面感了。
3.高级函数
高级函数打破了函数定义过程时,只能接收数据为参数的限制。
具体表现为:接收一个或多个过程为参数;或者以一个过程作为返回结果。
也可以理解成“以其他函数作为参数或返回值的函数”。
函数的类型
Kotlin中的函数类型声明需遵循以下几点:
·通过->符号来组织参数类型和返回值类型,左边是参数类型,右边是返回值类型;
·必须用一个括号来包裹参数类型;
·返回值类型即使是Unit,也必须显式声明。
(Int) -> Unit
如果是一个没有参数的函数类型,参数类型部分就用()来表示。
() -> Unit
多个用逗号分隔
(errCode: Int, errMsg: String) -> Unit
接下来是一个神奇的问号
这里的?代表errMsg可能为空
(errCode: Int, errMsg: String?) -> Unit
这里的?代表此函数可能为空
((errCode: Int, errMsg: String?) -> Unit)?
高阶函数
它的返回值为函数:(Int) -> Unit
(Int) -> ((Int) -> Unit)
简写
(Int) -> Int -> Unit
支持匿名函数
方法和成员引用
class : : method
通过两个冒号来实现对于某个类的方法进行引用
Lambda
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
简写一
val sum = { x: Int, y: Int -> x + y }
简写二
val sum: (Int, Int) -> Int = { x, y -> x + y }
总结:
·一个Lambda表达式必须通过{}来包裹;
·如果Lambda声明了参数部分的类型,且返回值类型支持类型推导,那么Lambda变量就可以省略函数类型声明;
·如果Lambda变量声明了函数类型,那么Lambda的参数部分的类型就可以省略。
单个参数的隐式名称
listOf(1, 2, 3).forEach { foo(it) }
等价于
listOf(1, 2, 3).forEach { item -> foo(item) }
这里的it关键字是简写了表达式
for循环和范围表达式
for (i: Int in 1..10) {
println(i)
}
简写
for (i in 1..10) println(i)
1..10 Range表达式是通过rangeTo函数实现的,通过“..”操作符与某种类型的对象组成,除了整型的基本类型之外,该类型需实现java.lang.Comparable接口。
step 2 间隔 2
for (i in 1..10 step 2) print(i)
13579
downTo倒序
for (i in 10 downTo 1 step 2) print(i)
until 半开区间
for (i in 1 until 10) { print(i) }
123456789
中缀表达式
A 中缀方法 B
定义一个中缀函数,它必须需满足以下条件:
·该中缀函数必须是某个类型的扩展函数或者成员方法;
·该中缀函数只能有一个参数;
·虽然Kotlin的函数参数支持默认值,但中缀函数的参数不能有默认值,否则以上形式的B会缺失,从而对中缀表达式的语义造成破坏;
·同样,该参数也不能是可变参数,因为我们需要保持参数数量始终为1个。
函数可变参数
字符串判等
·结构相等。通过操作符来判断两个对象的内容是否相等
·引用相等。通过操作符=来判断两个对象的引用是否一样,与之相反的判断操作符是!。如果比较的是在运行时的原始类型,比如Int,那么=判断的效果也等价于==。