Kotlin语言入门学习(二)

 

本篇文章是对Kotlin语言入门学习(一)的补充,适用于有一定Java基础的同学学习,在理解Kotlin的基本语法结构后,更重要的是加以实践,方便更快更好的理解Kotlin语言。

 


一、Kotlin是什么
Kotlin是一种基于JVM的静态类型编程语言
Kotlin的入口是main()函数


Kotlin的特点:
1,极简:语法简洁优雅,类型系统中一切皆引用
2,空安全:?可空
3,多范式:Kotlin同时支持OOP与FP编程范式
4,可扩展:Kotlin可直接扩展函数与属性
5,高阶函数与闭包
6,支持快速实现DSL
7,智能推断


Kotlin的工具平台:云端IDE,命令行REPL,IDEA

 

二、Kotlin语法基础

throw表达式:在Kotlin中,throw是表达式,它的类型是特殊类型Nothing。该类型没有值,与C、Java中的void意思一样


Kotlin中有两种类型的相等性:
引用相等===  !==  (两个引用指向同一对象,即值与引用都相等)
结构相等== !=  (使用equals()判断,比较值)


Elvis操作符  ?:   在Kotlin中,Elvis操作符特定是跟null进行比较,如:y = x?:0   等价于:val y = if(x!==null) x else 0
 

非空断言“!!”
Kotlin提供了断言操作符“!!”,使得可空类型对象可以调用成员方法或者属性(但遇见null,就会导致空指针异常)
Kotlin中没有三元表达式,对应的是:if...else语句,如:if(true) 1 else 0。而Elvis操作符是精简版的三元运算符


三、类型系统与可空类型


3.1类型系统
相对于Java语言,Kotlin语言去掉了原始数据类型,只有包装类型
Kotlin系统类型分为可空类型和不可空类型


Kotlin在类型T后面加个“?”,就表达了可空类型
                  fun main(args:Array<String>){
                        println(strLength(null))
                        println(strLength("abc"))
                  }
                 fun strLength(s:String?):Int{
                        return s?.length ?:0  //?.是安全调用符,?:是Elvis操作符
                 }          
 

3.2特殊类型
Unit、Nothing、Any及其对应的可空类型Unit?、Nothing?、Any?
当一个函数没有返回值的时候,用Unit来表示这个特征,而不是null,但大多数时候,可省略,返回类型是Unit
Void对应Nothing?,其唯一可被访问的返回值是null


如果一个函数的返回值是Nothing,意味着这个函数永远不会有返回值
Any?是可空类型层次的根,Any是非空类型层次结构的根,Any?是Any的超集,Any?是Kotlin类型层次结构的最顶端


3.3类型检测与类型转换
Kotlin中的is和!is类似于Java中的instanceOf,类型匹配
as运算符用于类型转换,as?为可空转换,如果类型不兼容,则返回null
在Kotlin中,父类是禁止转换为子类的

 

四、类与面向对象编程

 

Kotlin中没有静态属性和方法,但可以使用关键字object声明一个object单例对象,Kotlin中还提供了伴生对象,用companion object关键字声明
数据类:只存储数据,不包含操作行为的类,Kotlin中使用关键字data class可创建一个只包含数据的类,类似于Java中的bean类

 

五、函数与函数式编程

5.1函数式编程
函数式编程(FP),使一种编程范式,即面向函数编程,核心思想在于解决问题的过程,把任务分解为一个个的函数,最后通过函数组合来实现目标


比如,我们现在有一个字符串列表:val strList = listOf("a","ab","abc","abcd","abcde","abcdef","abcdefg")
现在我们想要过滤出字符串元素中长度是奇数的列表,那么可以把这个问题的解决逻辑拆成两个函数来组合实现:
             val f = fun (x:Int) = x % 2 == 1     //判断输入的Int是否奇数
             val g = fun (s:String) = s.length    //返回输入的字符串参数的长度
再使用函数h来封装:
             val h = fun (g:(String) -> Int,f:(Int -> Boolean):(String) -> Boolean){
                        return{ f(g(it)) }
              }
这个h函数稍显长,可通过类型别名typealias使代码更简洁

 

5.2Kotlin中的特殊函数
特殊函数主要有:run()、apply()、let()、also()、with()


run():使用时可使用run(其它函数),表示执行()内的函数,()可省略


apply():通过.方式调用,表示在run()的基础上返回当前调用者对象


let():通过.方式调用,表示把当前调用对象作为参数传给let函数,如myfun().let{println(it)},则表示执行完myfun函数后,返回这传给let()函数,最后打印结果为myfun()返回值


also():通过.方式调用,表示在let()基础上返回当前调用者


with():执行传入的代码块,或者理解为接收一个指定类型的对象去执行body函数

 

以上5种函数没有给出具体示例,希望读者找相关例子进行更好的理解并在实践中加以应用

 

六、扩展函数

 

为List扩展一个filter()函数
            fun <T> List<T>.filter(predicate: (T) -> Boolean):MutableList<T>{
                         val result = ArrayList<T>()
                         this.forEach{
                               if(predicate(it)){
                                          result.add(it)
                               }
                         }                         
                  return result
            }

 

调用:
             val list = mutableListOf(1,2,3,4,5,6,7)
             val result = list.filter{
                   it%2==1
             }
             predicate(result)     //[1,3,5,7]

 

扩展属性:允许定义在类或者Kotlin文件中,不允许定义在函数中

 

七、集合类
集合类存放的都是对象的引用,而非对象本身,Kotlin中集合类分为:可变集合类(Mutable)与不可变集合类(Immutable)
遍历集合中的元素:forEach
             list.forEach{
                      println(it)
             }


映射函数map:
             val list = listOf(1,2,3,4,5,6,7)  //声明并初始化一个List
             list.map{it*it}     //map函数对每个元素进行乘方操作,返回[1,4,9,16,25,36,49]
             set和map类似

过滤函数filter:
             data class Student(var id:Long,var name:String,var age:Int,var score:Int){  //声明Student数据类
                              override fun toString():String{  //覆写toString()函数
                                            return "Student(id = $id,name = '$name',age = $age,score = $score)"
                              }
             }
创建一个持有Student对象的List
             val studentList = listOf(
                   Student(1,"Jack",18,90),
                   Student(2,"Rose",17,90),
                   Student(3,"Alice",16,70),
             )
此时,如果我们想要过滤出大于等于18岁的学生,可以这样写:
             studentList.filter{it.age>=18}
输出结果:[Student(id = 1,name = "Jack",age = 18,score = 90)]


排序函数:
            reversed()倒序
            sorted()升序
元素去重:

           distinct()

 

八、泛型
类型上界
fun <T:Comparable<T>> gt(x:T,y:T):Boolean  //T的类型上界是Comparable<T>,即告诉编译器,类型参数T代表的都是实现了Comparable接口的类,这样等于告诉编译器,它们都实现了CompareTo方法。
如果没有上界声明,则无法直接使用CompareTo操作符

 

out T 等价于 ? extend T  指定类型参数的上界
in T  等价于 ? super T  指定类型参数的下界

 

九、文件I/O操作、正则表达式与多线程
Kotlin的序列化直接采用了Java序列化类的类型别名
internal typealias Serializable = java.io.Serializable

 

Kotlin中常用的文件读写API:
File.readText()  //读取该文件的所有内容作为一个字符串返回
File.readLines()  //读取该文件的每一行内容,存入一个List返回
File.readBytes()  //读取文件所有内容以ByteArray的方式返回
File.writeText()  //覆盖写入text字符串到文件中
File.writeBytes()  //覆盖写入ByteArray字节流数组
File.appendText()  //在文件末尾追加写入text字符串
File.appendBytes()  //在文件末尾追加写入ByteArray字节流数组

 

9.1遍历文件树
遍历文件树:walk函数
下面的例子遍历了指定文件夹下的所有文件
                  fun traverseFileTree(filename:String){
                        val f = File(filename)
                        val fileTreeWalk = f.walk()  //调用walk()会返回一个FileTreeWalk对象
                        fileTreeWalk.iterator().forEach{
                                             println(it.absolutePath)
                        }                   
                   } 

 

9.2递归复制文件
复制该文件或者递归该目录及其所有子文件到指定目录下,如果指定路径下的文件不存在,会自动创建
copyRecursively函数签名:
                  fun File.copyRecursively{
                               target:File,  //目标文件
                               overrite:Boolean = false  //是否覆盖
                               onError:(File,IOException) -> OnErrorAction = { _,exception -> throw exception})  //错误处理
                   }:Boolean
 
 9.3网络I/0
 readBytes和readText
 使用这两个方法配合正则表达式实现网络爬虫功能:
 根据URL获取该URL的响应HTML函数:
                 fun getUrlContent(url:String):String{
                           return URL(url).readText(Charset.defaultCharset())  //获取该URL的响应HTML文本
                 }
 根据URL获取该URL的响应比特数组函数
                fun getUrlBytes(url:String):ByteArray{
                          return URL(url).readBytes  //获取该URL的响应ByteArray
                }
 把URL响应字节数组写入文件中
               fun writeUrlBytesTo(filename:String,url:String){
                          val bytes = URL(url).readBytes()
                          File(filename).writeBytes(bytes)  //写入文件
               }
 


 9.4正则表达式
 构造Regex表达式
 val r1 = Regex("[a-z]+")  //创建一个Regex对象,匹配的正则表达式是[a-z]+
 val r2 = "[a-z]+".toRegex()  //直接使用Kotlin中给String扩展的toRegex函数
 
 Regex函数:
 mataces()  //输入字符串全部匹配
 containMatchIn()  //输入字符串至少有一个匹配
 matchEntrie()  //输入字符串全部匹配,返回一个匹配结果对象
 replace()  //把输入字符串中匹配的部分替换成replacement的内容//把输入字符串中匹配到的值,用函数transform映射之后的新值替换
 find()  //返回输入字符串中第一个匹配的值
 findAll()  //返回输入字符串中所有匹配的值MatchResult的序列 

 

同步方法和块:
synchronized不是Kotlin中的关键字,它替换为@Sychronized注解
同样的,Kotlin中没有volalile关键字,但是有@Volatile注解

 

参考:《Kotlin从入门到进阶实战》  ——陈光剑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值