koltin(高阶函数)
高阶函数定义高阶函数就是以另一个函数为参数,或者返回值为函数的函数。例如常用的filter,map,with等都是高阶函数
函数类型
函数类型必须显示的表示出来,如Unit在普通函数中可以隐藏。但是在函数类型的声明中,必须完整的写出来。
当你已经声明了函数类型后,你再写lambda函数,就可以省略掉lambda函数里的参数类型,而直接写他的参数名。
同样的,函数类型也有可空的。但是有两点区分 123456val testNull1: (Int) -> Int? = { null }val testNull2: ((Int) -> Int)? = nullval testError: (Int) -> Nothing = { throw Exception("Error")}
一个是返回类型的可空,一个是函数类型的可空。
在java中使用函数类其背后原理为:函数类型在编译后会被声明为一个普通的接口,一个函数类型的变量就是FunctionN的一个实现。kolitn定义了一系列接口,包括不同数量的参数,Func ...
kotlin(运算符重载和其他约定)
在java中,有一些特定的类与语言特性相关联,例如使用了iterable接口的对象可以在for循环中使用。
而在kotlin中,也有很多与语言特性相关的函数命名,对,他与java并不一样,他是选择了将功能和函数命名来绑定。例如,如果在你的类中定义了一个名为 plus 的特殊方法,那么按照约定,就可以在该类的实例上使用+运算符。因此,在 Kotlin 中,我们把这种技术称为约定
约定因为他并不是强依赖于类和他的继承关系。在kotlin中使用约定可以在类中重载其方法,也可以通过扩展函数去添加约定,从而适应现有的java类而不用修改其代码。
运算符重载运算符重载所需要的关键词是operator,而且他所重载的方法都有特定的命名,都必须带上operator关键字。这些表达式同样也满足+-/的基本运算规则。*
表达式
函数名
a * b
times
a + b
plus
a - b
minus
a / b
div
a % b
mod
a * = b
timesAssign
a + = b
plusAssign
a ...
使用socket实现一个小型的聊天程序
最近在学习使用kotlin,然后试了试用socket实现一个聊天通信功能。然后发现其实kotlin用的很多库都是JAVA中已经存在的。所以更好的使用kotlin不仅要明白kotlin相对于java的优秀特性和他的跨平台能力,还需要对java也有深度的理解。
使用的插件和包:在build.gradle.kts配置文件中配置你所需要的插件和依赖。
插件
12345678910111213141516plugins { ··· id("com.github.johnrengelman.shadow") version "8.1.1" ···}tasks.withType<ShadowJar> { archiveBaseName.set("myapp") // jar 文件的基本名字 archiveVersion.set("1.0.0") // jar 文件的版本号 archiveClassifier.set("") // jar 文件的 ...
通过文件读写实现聊天对话(kotlin)
首先声明,这个任务并没有实现,我暂时没找到可以用来解决kotlin中实时监听键盘动作,并且不会阻塞的回调方法。
123456789101112131415161718import kotlinx.coroutines.*import java.io.Fileimport java.io.FileReader fun main()= runBlocking{ val file = File("src/main/resources/a.txt") var i = 0 while (true){ println("第${i++}次访问文件") delay(2000) println(file.readText()) println("读取完成")// if(readln()=="chat"){// var message = readln()// ...
kotlin(集合和数组)
持有可空类型元素和持有非空类型元素的集合变量自己类型的可空性和用作类型参数 类型 的可空性是有区别的集合中是允许可空值的。
只读集合和可变集合kotlin将访问集合的接口和访问数据的接口分开了。可变集合继承自只读集合,只读集合不可修改,可变集合在只读集合的基础上增加了添加,移除元素,清空集合等方法。
一般的规则是,在代码中都应该使用只读集合。只有在需要修改的地方才使用可变接口的变体。这在函数中接受参数时也更明确了什么什么集合是可修改的,什么时候只适用于读取。只读集合不能传递给可变集合,但是可变集合可以传递给只读集合
所以只读集合也并不总是线程安全的,在多线程环境下处理数据,需要保证代码的正确同步关系。
kotlin集合和java每一个kotlin接口都是对应java集合接口的一个实例。在kotlin和java之间转移并不需要转化:map也并没有继承自Collection和Iterable他也被表示为两种类型:只读和可变
java操作kotlin集合因为java不会区分可变和只读集合,所以从java调用kotliln的集合时,kotlin编译器不会拒绝java代码对集合做了什么,即便对只 ...
Kotlin(基本数据类型)
基本数据类型相比于java而言,kotlin不会区分基本数据类型和他们的包装类,都是统一的数据类型,但是他们的底层实现会和java相关。
java中Int,Boolean之类的基本数据类型都和引用类做了区分,基本数组存值,而包装类存储包含该对象的内存地址的引用。
kotlin中他不区分,都是用一个类Int,Boolean等。这样就很方便我们的操作。但是这并不意味着kotlin直接把所有的类都直接写出引用类型了。因为那样的话,就会非常低效。在运行时,数字类型尽可能的使用最高效的方式存储,大部分情况下—-对于变量,属性,参数和返回类型,kotlin的int类型都会编译为java中的基本数据类型。唯一不可行的就是泛型类,集合。他一定会编译为包装类。
可空数据类型 Int?,Boolean?这些可空数据类型因为不止能存储基础数据类型,还能存储null,所以肯定是包装类。
这是基于JVM虚拟机实现泛型的方式决定的,JVM不支持用基本数据类型作为类型参数,所以必须使用包装类。如果要高效的存储基础数据类型的话,要么使用第三方库(Trove4)等。要么用数组存储。
数字转化在kotlin中没有默认 ...
kotlin(类型系统)
可空性
在java中,运行一个程序,往往遇到的最多的错误就是空指针异常,而空指针异常他是个运行时异常,往往不会指明究竟是哪一行的问题,这就让程序员非常的头疼。
而kotlin的解决方案就是把运行时错误转为编译期的错误。让程序员可以在编译时就减少错误异常的产生。通过区分可空和非空两种数据类型。
可空类型在kotlin中,所有的常见类型都是默认非空的,也就是不能接受null作为参数。除非显示的把他标记为可空,即在类型后面加上?。但是,一旦声明了是可控类型,就会有很多操作受到限制,kotlin会直接拒接一部分函数的调用,除非你对他进行了非空判断处理,然后kotlin系统就会只能判断类别,然后你才能继续执行。例如:
1fun strLen(s:String?) = if(s!=null) s.length else 0
如果你不进行非空判断,他将不允许进行编译。
类型定义
类型就是数据的分类……决定了该类型可能的值,以及该类型的值上可以完成的操作。
在java中,他没有区分可空和非空,例如String类型可以接受String类型和null。而这在运行中就有可能导致空指针异常(NullPoi ...
kotlin(序列)
序列引出序列的使用,首先当我们在使用集合的各种便携式API函数时,他会创建一个中间列表,最后返回。这在使用中并没有什么问题,但是如果采用了链式的多个函数操作,以及集合的基数很大时就会导致效率低下。例如这个,他会在中途生成两个列表,如果基数很大将会变得非常低效。
1people.map(Person: :name) .filter { it.startsWith ("A")}
而序列就是一种惰性集合,他一样可以使用集合所有的api方法,但是他不会在中间创造集合存储,而是类似java中的流。他是一个迭代器的形式,每个元素每个元素的遍历,然后最后在生成结果,如果没有最后的生成结果的步骤,他不会进行之前的操作。
Sequence接口惰性集合的接口就是Sequence接口,而且他只提供了一个方法,也就是iterator。因为Sequence是惰性的,所以他可以很高效的对集合元素执行链式操作,而且不会产生额外的中间集合。
序列操作序列操作有两种,一种中间操作,他返回的任然是序列,一种是末端操作,他返回的结果,可以是任何所需要的对象。中间操作始终是惰性的 ,也就是意味着 ...
Kotlin(lambda函数)
lambdalambda表达式根据图片可以比较清晰的了解lambda的语法,他通过->将参数和函数体分开,参数不用带小括号,整体都用一个中括号括起来,箭头右边写函数体,函数体可以写多行,最后一行做为表达式的值传递回去。为了让你加深理解。
实例1:1234fun main(args: Array<String>) { //{x:Int,y:Int -> x+y}本身就是一个函数 println({x:Int,y:Int -> x+y}(1,2))}
以上内容,肯定了lambda函数表达式,他本身就是一个函数,可以直接使用。像一个正常函数一样。但是这样子意义不大,就像是刻意为之
实例2:1234fun main(args: Array<String>) { var sum = {x:Int,y:Int -> x+y} println(sum(1,3))}
kotlin作为函数式编程语言。他可以直接把函数传递给一个变量存 ...
kotlin(object)
Object单例模式在kotlin中,可以非常简单的通过这个关键词实现一个单例类。他可以实现接口,继承类,也可以用扩展方法去扩展类。他就是一个非常完美的类的声明方法。
当然,同理的作为一个单例类,他并没有构造方法,也就是如果你使用constructor将会直接导致报错。
如果在java中要调用kotlin中的object对象,他需要通过一个字段INSTANCE来实现,具体实例如下
12345678910111213141516//kotlinopen class Student:Child{ fun call(){ println("我会叫") }}object child1:Student(){ val name="abc"}//javapublic class Test { public static void main(String[] args) { child1.INSTANCE.walk(); ...