学习本文章的同学,你一定得熟悉Java方面的知识,否则本文章不是太适合你哦!

一起从零学Kotlin-20170730

0.官方API

链接:http://pan.baidu.com/s/1geVxlJ1 密码:4nht
官方API才是学习的王道……

Intellij IDEA(kotlin开发学习IDEA,并且还支持Java)下载
https://www.jetbrains.com/idea/

官网下载慢的可以从我云盘里面下载:
链接:http://pan.baidu.com/s/1i4Au2nb 密码:qato

1.val和var声明可变和不可变变量

val:用于声明不可变的变量,不可变指的是引用不可变,相当于Java当中的final

var:用于声明可变的变量

fun main(args: Array<String>) {val a = "a是不可变的变量" //不可变var another = 3 //可变println(a)println(another)}

2.fun函数

Kotlin中的函数可以这样声明:

fun 函数名 (参数列表):返回值类型{函数体}

fun 函数名 (参数列表) = 表达式

 //fun 函数名 参数列表:返回值类型{函数体}
fun add1(a1:Int,a2:Int):Int{return a1+a2}//fun 函数名 参数列表 = 表达式
fun add2(a1:Int,a2:Int) = a1+a2

还有一种比较奇怪的方式:

fun main(args: Array<String>) {println(sum1(1,2))println(sum2(3,4))}var sum1 = fun (a1:Int,a2:Int):Int{return a1+a2
}var sum2 = fun(a1:Int,a2:Int) = a1+a2

输出:
3
7

这种方式叫做匿名函数,有啥用途?目前笔者也不是很清楚,学过的大神说它相当的厉害,所以继续往后学,应该会揭晓。

3.聪明的类型推断

Kotlin能够很聪明的判断一些位置所应有的类型,这让程序员省心了不少。
比如:
以下代码:

var a = 3 //自动推断a的类型为Intvar str:String = "string"
var str2 = str //自动推断str2的类型为Stringfun add(a1:Int,a2:Int) = a1 + a2 //自动推断add()方法的返回类型为a1+a2所对应的类型,也就是Int类型

4.Lambda表达式

其实就和匿名函数一样,写法如下:
{(参数列表) -> [函数体,最后一行是返回值]}

fun main(args: Array<String>) {println(sum(1,2))println(sum2(3,4))}var sum = {a1:Int,a2:Int-> a1+a2 }var sum2 = {a1:Int,a2:Int->println("$a1 + $a2 = ${a1 + a2}")a1+a2
}

Lambda的类型是什么,这跟传入的类型和返回的类型相关,比如下面的代码中Lambda对应的类型如下代码所示:

 var sum = {a1:Int,a2:Int-> a1+a2 } //(Int,Int)->Intvar str = {a1:Int,str:String->a1.toString() + str +"".toString()println(str)}//(Int,String)->unit

Kotlinl里面的unit就相当于Java当中的void
Lambda表达式可以嵌套使用吗?当然可以啊,比如Lambda的类型是(Int,(Int,String)->Int)->Int这不是就是Lambda表达式的嵌套吗?只不过作为初学者的我们是有点复杂哦。

那么Lambda表达式如何调用呢?
比如,下面Lambda表达式如何调用:
var sum = {(a1:Int,a2:Int) -> a1+a2}

你可以这么调用:sum(2,3)
你也可以这么调用sum.invoke(2,3)

5.类及类的声明

Java当中的类的声明有以下几个方面:
1.构造器
2.成员变量
3.成员方法
4.访问权限的设置
5.静态和非静态的设置
6.为某些成员变量设置get和set方法
对于那些对Java非常熟悉的同学,这些也就不需要特殊说明了把!不熟悉?那现在还不太适合学习Kotlin,理由很简单,因为面向对象思想都没有理解,那之后学习起来相当吃力的,所以,请务必先接触一下Java,再来学习Kotlin就轻松容易的多了。

那么Kotlin如何取声明一个类呢?
关键字还是很Java一样使用”class”关键字声明类

5.1 构造器

Kotlin当中的构造器的名字可不是跟Java一样,和类名相同,其构造器的名字必须是:constructor,代码如下所示:

class Person{var name:String = "" //成员变量var age:Int = 0constructor(name:String,age:Int){this.age = agethis.name =name}//Person类的构造器}

此外Kotlin对于构造器还有一个特殊的写法,代码如下:

class Student(var name:String,var age:Int)//构造器的特殊写法

对应的代码应该是下面的样子:

class Student{var name:String = "" var age:Int = 0constructor(name:String,age:Int){this.age = agethis.name =name}}

此外,类的构造器分为主构造器和次构造器:

在 Kotlin中的一个类可以有一个主构造函数和一个或多个次构造函数。主构造函数是类头的 一部分:它跟在类名(和可选的类型参数)后,如果主构造函数没有任何注解或者可见性修饰符,可以省略这个constructor 关键字。

主构造函数不能包含任何的代码。初始化的代码可以放到以 init 关键字作为前缀的初始化 块(initializer blocks)中。

主构造函数的参数可以在初始化块中使用。它们也可以在类体内声明的属性初始化器中使用。

如果一个非抽象类没有声明任何(主或次)构造函数,它会有一个生成的不带参数的主构造 函数。构造函数的可见性是public。如果你不希望你的类有一个公有构造函数,你需要声明 一个带有非默认可见性的空的主构造函数。

说了这么多,还不如上上代码来的直接:

class Student(var name:String,var age:Int){//主构造函数init {name = "sda"age = 28}var ID:String = "20171314"constructor(name:String,age:Int,ID:String) : this(name,age) {this.ID = ID}//次级构造函数}

5.2 成员变量

这基本和Java当中是一样的,看上述代码就知道了

5.3 成员方法

Kotlin当中如果从属于类的函数叫做”成员方法”或者”方法”,不从属于类的叫做”函数”,什么是不从属于类呢?比如下列代码中的A()函数:

fun main(args: Array<String>) {A()}fun A(){println("函数A()")}//不从属于类,是函数

Kotlin中的成员方法没什么特别要说明的,基本上和Java的声明类似,代码如下:

class Person{var name:String = ""var age:Int = 0constructor(name:String,age:Int){this.age = agethis.name =name}fun  自我介绍(){println("我是$name,今年${age}岁")}//Person的成员方法"自我介绍()"}

5.4 权限修饰符的设置

Java当中的默认访问权限是default,作用于当前的包内,Kotlin的默认访问权限是public,你没看错,的确是public,kotlin的访问权限特性如下:

类的权限修饰符:
open:如果你确定你自定义的类是会被继承的,那么你需要给这个类添加 open 修饰符。

final:这是kotlin默认的,也就是没有添加任何修饰符,和上面Student类一样,此修饰符代表着你的类不能被继承。

sealed:sealed 修饰的类称为密封类,用来表示受限的类层次结构。例如当一个值为有限集中的 类型、而不能有任何其他类型时。在某种意义上,他们是枚举类的扩展:枚举类型的值集合也是受限的,但每个枚举常量只存在一个实例,而密封类的一个子类可以有可包含状态的多个实例。

data:data 修饰的类称之为数据类。它通常用在我们写的一些 POJO 类上。
当 data 修饰后,会自动将所有成员用operator声明,即为这些成员生成类似 Java 的 getter/setter 方法。

成员变量修饰符:
public:
private:
protected:
上面三种我就不罗嗦了,因为和Java中的是一样的

internal:它是模块级别的访问权限。

何为模块(module),我们称被一起编译的一系列 Kotlin 文件为一个模块。在 IEDA 中可以很明确的看到一个 module 就是一个模块,当跨 module 的时候就无法访问另一个module 的 internal 变量或方法。这会在后面说明。

5.5 静态和非静态的设置

貌似Kotlin中不存在静态修饰符static,那么肯定有个替代的东西,但是存在一个伴生类的写法,它就是用来替代Java当中的静态变量和静态方法的,示例代码如下:

fun main(args: Array<String>) {println(Student.a)println(Student.get())}class Student(var name: String,var  age: Int) {companion object {//静态方法和变量都应该写在这里面var  a:Int =  3;//静态变量fun get():Int{return a}}}

5.6 为某些成员变量设置get和set方法

在类前面加”data”修饰符即可达到效果,而且注意的一点就是,无论你有没有在声明类的时候加”data”关键字。

Getters和 Setters
声明一个属性的完整语法是

其初始器(initializer)、getter 和 setter 都是可选的。属性类型如果可以从初始器 (或者从 其 getter 返回值,如下文所示)中推断出来,也可以省略。

6.Kotlin对基本运算符进行重写以及创造自己的运算符

Java当中是不能对基本的运算符进行重写的,但是Kotlin就不一样了,可以对基本运算符进行重写,怎么样,是不是感觉很牛啊!我们就拿一个数学当中的复数相加操作为例字,我们知道基本运算符中没有复数相加的操作,没关系,我们可以进行在复数类FuShu中把“+”运算符进行重写,代码如下,注意为了让童鞋们更好的理解,我使用了中文命名,实际开发中尽量少用中文:

class 复数(var 实部:Int,var 虚部:Int){operator  fun plus(fuShu: 复数):复数{return 复数(实部 + fuShu.实部,虚部+ fuShu.虚部)}override fun toString(): String {return "$实部 + ${虚部}i"}}fun main(args: Array<String>) {var fuShu1 = 复数(3,4)var fuShu2 = 复数(4,5)println(fuShu1 + fuShu2)}

输出:
7 + 9i

除此之外我们还可以添加我们自己的运算符,比如以下神奇的代码:

class 人(var name:String,var age:Int){infix  fun 吃(str:String){println("我叫$name,今年${age}岁,现在正在吃$str")}//使用中缀表达式对自定义运算符,其实就是可以让方法可以像运算符一样被调用}fun main(args: Array<String>) {var 某个人 = 人("张三",23)某个人 吃 "螃蟹"}

输出:
我叫张三,今年23岁,现在正在吃螃蟹

注意的是要想把方法自定义自己的运算符,此方法一定含有参数,并且只能是一个参数,要问原因,其实很简单,因为运算符只涉及两个参数,一个就是运算的,一个就是被运算的,so 明白了吧!

7.分支表达式,when表达式…

分支表达式?啥玩意儿?Java当中的分支语句?的确,分支表达式这很难理解,其实我把代码一贴出来,你就恍然大悟了:

var string = readLine() //readLine()方法是接收键盘输入的字符串val str = if(readLine()!!.contains("1")){"11111"}else{"aaaaa"}//当输入的字符串当中含有子字符串"1",那么这个分支表达式就会返回字符串"11111",否则返回"aaaaa"

没错,分支表达式可以具有返回值的,分支语句是不会返回值的,so 明白了吧!上述是”if表达式”是分支表达式的一种,那么肯定存在其他的分支表达式,在提到其他的分支表达式之前,必须说明一点,Java当中有个分支语句叫switch,Kotlin没有switch啦,那么咋办呢?删除switch肯定会有替代switch的啦,kotlin中的when语句就可以替代switch语句,代码如下:

var string = readLine()val str = when(string){"1"->"11111" //当string的值为"1",注意是等于,那么就返回值"11111""a"->"aaaaa"else->{"啥都不是" //当string的值不是"1"或者"a"的时候,就返回"啥都不是"}}

看懂笔者写的代码,一方面你已经掌握了Kotlin分支表达式,一方面掌握了分支语句。
区分起来很简单,一个有返回值,一个没有返回值

8.循环语句以及关键字continue和break

Java当中的循环语句有:for语句,while语句,那么Kotlin中的循环语句会跟Java一样 吗?

首先,我们来看看for语句,Java当中for语句用法有:(1)集合或者数组的迭代,(2)次数循环,比如从1加到100,那么Kotlin中的for语句会是什么样子呢?

Kotlin中的for语句:
Kotlin中的for语句迭代很强大,比Java的还要强大,比如,有一个String[]数组,它的迭代是这样的:

var strs:Array<String> = arrayOf("a","b","c","d","e")for(str in strs){println(str)
}

这似乎跟java的基本一样,为什么是似乎?因为Kotlin支持自动类型推断,所以在用于遍历的变量不需要指定类型,不得不再说一句自动类型推断简直太人性话了,但是有些时候,我们必须要带数组下标的方式去遍历,Java当中的for语句可就变得麻烦多了,因为必须要以下类似的写法:

 //Java当中带下标的方式去遍历String数组String[] strs  = {"a","b","c","d","e"}for(int i=0;i<strs.length;i++){System.ou.println(strs[i]) }

这简直太麻烦了,还要声明一个变量i,Kotlin可不需要,它是这样的

var strs:Array<String> = arrayOf("a","b","c","d","e")//不带下标遍历数组
for(str in strs){println(str)
}//带下标遍历数组
for((Index,Value) in strs.withIndex()){println("下标:$Index,值:$Value")} //withIndex()方法返回Iterable<IndexedValue<T>>

这么一比较,又觉得kotlin那叫一个爽。那么如何使用Kotlin中的for语句求的1到100之和呢?代码如下:

var intRange:IntRange = 1..100 // 这是[1,100]区间var sum = 0;for(i in intRange){sum = sum + i}println("1到100的累和结果是:$sum")

接下来看看while循环,kotlin的while跟Java是一样一样的,都有
while(条件体){循环体}

do{循环体}while(条件体)两种方式,由于是一样的,这里我就不在啰嗦了。

接下来,来看看kotlin中的continue和break关键字,这俩关键字也是跟Java当中是一样一样的,所以我也就再次不想啰嗦了,实例代码如下:

fun main(args: Array<String>) {var students:Array<Student> = arrayOf(Student("a",1),Student("b",2),Studen("c",3),Student("d",4),Studet("e",5))for((Index,Value) in students.withIndex()){if(Value.name == "a")continueif(Value.name == "c")breakprintln("下标:$Index,值:${Value.name}->${Value.age}")}}class Student(var name:String,var age:Int)

9.Kotlin中的异常

Java的异常体系是这样的:

其中非运行时异常必须捕获和处理,通过try{}catch(){}finally{}语句来处理,除此之外,Java中可以自定义异常类,继承自基础体系中的异常,即可让自己的类加入到异常体系的大家族,具体细节,我就不罗嗦了,这都是Java的基础。

那么Kotlin中的异常体系又是如何呢?
Kotlin中所有异常类都是Throwable类的子孙类。每个异常都有消息、堆栈回溯信息和可选 的原因。跟Java一样代码块使用throw来抛出异常,方法使用throws来抛出异常,使用tru{}catch(){}finally{}语句来捕获和处理异常,可以有零到多个catch块。finally 块可以省略。但是catch和finally 块至少应该存在一个。这基本上和Java保持一致的,除此之外,try{}catch(){}finally{}是一个表达式,也就是说它可以具有返回值,示例代码如下:

var str = try {var file = File("D:\\aa")var fis  = FileInputStream(file)}catch (e:FileNotFoundException){"文件木有找到"}finally {"文件找到啦"}println(str)

注意的是Kotlin中并不会去取检查异常,什么意思?在Java中非运行时异常一定要捕获和处理,但是Kotlin并不存在运行时异常和非运行时异常的概念,也就是说,捕获和处理不是强制性的,这要靠程序员自己去捕获和处理,比如上面代码中的FileNotFoundException在Java当中一定是要被捕捉处理的,但是Kotlin不强制要求你捕捉和处理,为什么Kotlin要这样呢?因为强制捕捉异常会让代码变得复杂,Kotlin有其精简的特性,当然不会强制要求你捕捉异常的啦,不过,有些必须进行捕捉处理的,尽管Kotlin强制要求,我们都要去捕捉和处理。

其实理解表达式很简单,就是表达式一定是有返回值的,这一点一定要记住,一旦理解了这一点,那么Kotlin的所有表达式,就了如指掌了。

10.具名参数,变长参数,默认参数

具名参数,就是通过具体的参数名来传入参数,示例代码如下:

fun main(args: Array<String>) {println(add(a1 = 1,a2 = 2))//使用函数add(a1,a2)具体的参数名字"a1"(a1 = 1)和"a2"(a2 = 2)来对函数add(a1,a2)进行调用}fun add(a1:Int,a2:Int) = a1+a2

变长参数,什么是变长参数呢?当你的方法不确定要传入几个参数,并且这几个参数的类型相同,那么你就可以使用变长参数的方式来满足你的要求,使用vararg关键字进行声明,示例代码如下:

fun main(args: Array<String>) {println(add(1,2,3,4))println(add(1,3,4,0,8,2,3,5,6,7,8))}fun add(vararg ints:Int):Int{//变长的参数var sum = 0for(i in ints){sum = sum + i}return sum
}

我们都知道,Java中也存在这种变长参数,但是Java的变长参数只能在方法参数列表的最后面,但是Kotlin就不一样了,kotlin的变长参数可以出现在参数列表的任意位置。示例代码如下:

fun main(args: Array<String>) {println(add(true,1,2,3,4,str = "哈哈哈"))println(add(false,3,4,0,8,2,3,5,6,7,8,str = "hello"))var intArray:IntArray = intArrayOf(1,2,3,4,5)println(add(false,*intArray,str = "sasda"))//直接把数组作为变长参数ints的值}fun add(falg:Boolean,vararg ints:Int,str:String):Int{var sum = 0for(i in ints){sum = sum + i}return sum
}

默认参数,在你声明自己的方法或者函数的时候,可以使用默认参数来为你的参数来个初始化,这样做的结果就是,你在调用这个方法的时候,可以不用再次传递参数给它,当然也可以传递参数给他,示例代码如下:

fun main(args: Array<String>) {var r = 5.0println("半径为${r}cm的圆的面积为:${getYuanMianJi(r = r)}(cm*cm)")var r1 = 6.22println("半径为${r}cm的圆的面积为:${getYuanMianJi(3.1415,r1)}(cm*cm)")}fun getYuanMianJi(pi: Double = 3.14,r:Double) = r*r*pi

输出结果:
半径为5.0cm的圆的面积为:78.5(cm*cm)
半径为6.22cm的圆的面积为:121.5396086(cm*cm)

一起从零学Kotlin-20170730相关推荐

  1. 从零学web前端_从零到前端英雄(第2部分)

    从零学web前端 This article is part two of the "From Zero to Front-end Hero" series. In part one ...

  2. map根据value值排序_凯哥带你从零学大数据系列之Java篇---第十九章:集合(Map+Collections)...

    温馨提示:如果想学扎实,一定要从头开始看凯哥的一系列文章(凯哥带你从零学大数据系列),千万不要从中间的某个部分开始看,知识前后是有很大关联,否则学习效果会打折扣. 系列文章第一篇是拥抱大数据:凯哥带你 ...

  3. 从零学React Native之13 持久化存储

    数据持久化就是指应用程序将某些数据存储在手机存储空间中. 借助native存储 这种方式不言而喻,就是把内容传递给native层,通过原生API存储,详见从零学React Native之05混合开发 ...

  4. sql两个数字之差取最接近的_从零学DAX/Sql/Python030203SQL数据分类汇总续篇

       点击"数字化审计",可以关注哦! 开篇啰嗦话 上篇文章,为你介绍了SQL语句中select 的group by参数进行分类统计,group by在审计数据分析过程中是必然绕不 ...

  5. ios 获取一个枚举的所有值_凯哥带你从零学大数据系列之Java篇---第十一章:枚举...

    温馨提示:如果想学扎实,一定要从头开始看凯哥的一系列文章(凯哥带你从零学大数据系列),千万不要从中间的某个部分开始看,知识前后是有很大关联,否则学习效果会打折扣. 系列文章第一篇是拥抱大数据:凯哥带你 ...

  6. java lambda表达式_凯哥带你从零学大数据系列之Java篇---第二十二章:Lambda表达式...

    温馨提示:如果想学扎实,一定要从头开始看凯哥的一系列文章(凯哥带你从零学大数据系列),千万不要从中间的某个部分开始看,知识前后是有很大关联,否则学习效果会打折扣. 系列文章第一篇是拥抱大数据:凯哥带你 ...

  7. 多层数组如何遍历_带你从零学大数据系列之Java篇---第五章:数组

    温馨提示:如果想学扎实,一定要从头开始看凯哥的一系列文章(凯哥带你从零学大数据系列),千万不要从中间的某个部分开始看,知识前后是有很大关联,否则学习效果会打折扣. 系列文章第一篇是拥抱大数据:凯哥带你 ...

  8. 从零学javascript_我刚刚问了23,000个开发人员他们对JavaScript的看法。 这是我学到的。...

    从零学javascript by Sacha Greif 由Sacha Greif 我刚刚问了23,000个开发人员他们对JavaScript的看法. 这是我学到的. (I just asked 23 ...

  9. 从零学web前端_从零到前端英雄(第1部分)

    从零学web前端 I remember when I first started learning front-end development. I encountered so many artic ...

最新文章

  1. 在iOS 8中使用UIAlertController
  2. linux字符设备驱动架构,linux驱动开发--字符设备:cdd_cdev结构中private_data使用
  3. Re:关于集成测试与系统测试
  4. vue 如何点击按钮返回上一页
  5. DM8168 TILER(3)
  6. 使用Python音频双通道分离
  7. composer安装扩展包异常
  8. C#线程系列讲座(4):同步与死锁
  9. qt designer 弹出输入框_Qt编写的项目作品3-输入法V2018
  10. PHP-----文件系统的交互
  11. python创建员工_Python综合练习之创建员工信息表
  12. POJ 3617 Best Cow Line
  13. 《图像语义分析》学习笔记 (一)
  14. 在计算机操作系统中操作系统是处于应用软件,计算机操作系统考试复习题
  15. netperf mips 移植
  16. 物联网设备接入流程与平台架构
  17. 网络对战五子棋(附带源码,可以直接下载使用)
  18. 美的置业不能停:何享健的号子与郝恒乐的纤绳
  19. ObjectiveC, Xcode, iOS开篇导言
  20. msp430单片机c语言应用程序,MSP430单片机C语言应用程序设计实例精讲

热门文章

  1. unity之子弹发射
  2. 计算机usb接口禁用,台式机usb接口禁用了怎么办
  3. 网络、浏览器专题重点知识(含原理)
  4. Arm物联网全面解决方案加速产业创新,赋能开发者多样化市场
  5. 迪士尼地铁背后的指挥官——地铁控制中心OCC,NOCC系统
  6. signature=c0ffabca9db77bd424cc24014d68327f,交易加速
  7. Alignment trap
  8. UltraEdit小众用法
  9. 25. 答疑 - SAP OData 框架处理 Metadata 元数据请求的实现细节,前后端组件部署在同一台物理服务器
  10. Ascent代码分析4-World之地图管理及实现结构