一起从零学Kotlin-20170730
学习本文章的同学,你一定得熟悉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相关推荐
- 从零学web前端_从零到前端英雄(第2部分)
从零学web前端 This article is part two of the "From Zero to Front-end Hero" series. In part one ...
- map根据value值排序_凯哥带你从零学大数据系列之Java篇---第十九章:集合(Map+Collections)...
温馨提示:如果想学扎实,一定要从头开始看凯哥的一系列文章(凯哥带你从零学大数据系列),千万不要从中间的某个部分开始看,知识前后是有很大关联,否则学习效果会打折扣. 系列文章第一篇是拥抱大数据:凯哥带你 ...
- 从零学React Native之13 持久化存储
数据持久化就是指应用程序将某些数据存储在手机存储空间中. 借助native存储 这种方式不言而喻,就是把内容传递给native层,通过原生API存储,详见从零学React Native之05混合开发 ...
- sql两个数字之差取最接近的_从零学DAX/Sql/Python030203SQL数据分类汇总续篇
点击"数字化审计",可以关注哦! 开篇啰嗦话 上篇文章,为你介绍了SQL语句中select 的group by参数进行分类统计,group by在审计数据分析过程中是必然绕不 ...
- ios 获取一个枚举的所有值_凯哥带你从零学大数据系列之Java篇---第十一章:枚举...
温馨提示:如果想学扎实,一定要从头开始看凯哥的一系列文章(凯哥带你从零学大数据系列),千万不要从中间的某个部分开始看,知识前后是有很大关联,否则学习效果会打折扣. 系列文章第一篇是拥抱大数据:凯哥带你 ...
- java lambda表达式_凯哥带你从零学大数据系列之Java篇---第二十二章:Lambda表达式...
温馨提示:如果想学扎实,一定要从头开始看凯哥的一系列文章(凯哥带你从零学大数据系列),千万不要从中间的某个部分开始看,知识前后是有很大关联,否则学习效果会打折扣. 系列文章第一篇是拥抱大数据:凯哥带你 ...
- 多层数组如何遍历_带你从零学大数据系列之Java篇---第五章:数组
温馨提示:如果想学扎实,一定要从头开始看凯哥的一系列文章(凯哥带你从零学大数据系列),千万不要从中间的某个部分开始看,知识前后是有很大关联,否则学习效果会打折扣. 系列文章第一篇是拥抱大数据:凯哥带你 ...
- 从零学javascript_我刚刚问了23,000个开发人员他们对JavaScript的看法。 这是我学到的。...
从零学javascript by Sacha Greif 由Sacha Greif 我刚刚问了23,000个开发人员他们对JavaScript的看法. 这是我学到的. (I just asked 23 ...
- 从零学web前端_从零到前端英雄(第1部分)
从零学web前端 I remember when I first started learning front-end development. I encountered so many artic ...
最新文章
- 在iOS 8中使用UIAlertController
- linux字符设备驱动架构,linux驱动开发--字符设备:cdd_cdev结构中private_data使用
- Re:关于集成测试与系统测试
- vue 如何点击按钮返回上一页
- DM8168 TILER(3)
- 使用Python音频双通道分离
- composer安装扩展包异常
- C#线程系列讲座(4):同步与死锁
- qt designer 弹出输入框_Qt编写的项目作品3-输入法V2018
- PHP-----文件系统的交互
- python创建员工_Python综合练习之创建员工信息表
- POJ 3617 Best Cow Line
- 《图像语义分析》学习笔记 (一)
- 在计算机操作系统中操作系统是处于应用软件,计算机操作系统考试复习题
- netperf mips 移植
- 物联网设备接入流程与平台架构
- 网络对战五子棋(附带源码,可以直接下载使用)
- 美的置业不能停:何享健的号子与郝恒乐的纤绳
- ObjectiveC, Xcode, iOS开篇导言
- msp430单片机c语言应用程序,MSP430单片机C语言应用程序设计实例精讲
热门文章
- unity之子弹发射
- 计算机usb接口禁用,台式机usb接口禁用了怎么办
- 网络、浏览器专题重点知识(含原理)
- Arm物联网全面解决方案加速产业创新,赋能开发者多样化市场
- 迪士尼地铁背后的指挥官——地铁控制中心OCC,NOCC系统
- signature=c0ffabca9db77bd424cc24014d68327f,交易加速
- Alignment trap
- UltraEdit小众用法
- 25. 答疑 - SAP OData 框架处理 Metadata 元数据请求的实现细节,前后端组件部署在同一台物理服务器
- Ascent代码分析4-World之地图管理及实现结构