1.函数内容

1.1 函数的声明与用法

kotlin的函数使用fun关键字声明,如下所示:

fun double(x: Int): Int {return 2 * x
}
double(2).tostring()

1.2 函数参数

java不一样,kotlin的函数参数采用pascal表示法定义,即 name: type

fun powerOf(number: Int, exponent: Int) { /*……*/ }

kotlin可以设置默认参数:

fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) { /*……*/ }

kotlin可以使用具名称的函数参数。使得代码可读性更强:

reformat(str,normalizeCase = true,upperCaseFirstLetter = true,divideByCamelHumps = false,wordSeparator = '_'
)
reformat(str, wordSeparator = '_')

具名参数和位置参数混用的时候,位置参数应该放在具名参数的前面,允许调用 f(1, y = 2) 但不允许 f(x = 1, 2)

可以通过使用星号操作符将可变数量参数(vararg) 以具名形式传入:

fun foo(vararg strings: String) { /*……*/ }foo(strings = *arrayOf("a", "b", "c"))

当覆盖一个带有默认值的方法时,应该省略默认参数值:

open class A {open fun foo(i: Int = 10) { /*……*/ }
}class B : A() {override fun foo(i: Int) { /*……*/ }  // 不能有默认值
}

如果要指定某个参数的值,那么可以使用具名参数:

fun foo(bar: Int = 0, baz: Int) { /*……*/ }foo(baz = 1) // 使用默认值 bar = 0

如果lambda表达式作为参数的最后一个值,那么他可以放在括号外面:

fun foo(bar: Int = 0, baz: Int = 1, qux: () -> Unit) { /*……*/ }foo { println("hello") }        // 使用两个默认值 bar = 0 与 baz = 1

1.3 函数返回值

1.3.1 返回Unit的函数

Unit相当于java中的void,即不返回任何值。

fun printHello(name: String?): Unit{ …… }
fun printHello(name: String?) { …… }//代码等同于上面

1.3.2 返回单个表达式的函数

返回单个表达式的时候,可以直接把表达式写在等号后面。并且如果返回值类型可以由编译器推断的时候,那么返回值类型可以忽略。

fun double(x: Int): Int = x * 2
fun double(x: Int) = x * 2//Int类型可以省略

1.3.3 显式返回类型

具有块代码体的函数必须始终显式指定返回类型。 Kotlin 不推断具有块代码体的函数的返回类型,因为这样的函数在代码体中可能有复杂的控制流,并且返回类型对于读者(有时甚至对于编译器)是不明显的。

1.4 中缀表示法

中缀表示法有点像C++中的运算符重载。中缀表示法的标有infix关键字,它三个必要条件:

  • 必须是成员函数或扩展函数;
  • 必须只有一个参数;
  • 其参数不得接受可变数量的参数且不能有默认值。
infix fun Int.add(x: Int): Int {return this + x
}fun main(args: Array<String>) {println("Result = "+(1 add 2))
}

1.5 函数作用域

1.6 泛型函数

1.6.1 Kotlin的泛型

1.6.1.1 泛型的定义与使用

kotlin泛型的写法和java类似,都是将泛型写在尖括号内,并放在类后面。如下所示:

class Box<T>(t: T) {var value = t
}val box: Box<Int> = Box<Int>(1)val box = Box(1)//kotlin会自动判断类型

还有一种就是泛型函数,写法类似:

fun <T> singletonList(item: T): List<T> {// ……
}val l = singletonList<Int>(1)val l = singletonList(1)//kotlin会自动判断类型

1.6.1.2 泛型约束

对应于java泛型中的extend关键字

fun <T:Int> printTest(value:T){println("result = "+(value+3))
}fun main(args: Array<String>) {printTest(1)// printTest("nothing") //报错:inferred type String is not a subtype of Int
}

如果是需要多个上界的话,那么可以用where来实现

interface A{fun printA(infor:String)
}interface B{fun printB(infor:String)
}fun <T> printTest2(value:T)
where
T:A,
T:B
{value.printA("打印A")value.printB("打印B")
}
fun main(args: Array<String>) {printTest2(object:A,B{override fun printA(infor:String){println("printA = "+infor)}override fun printB(infor:String){println("printB = "+infor)}})
}

1.6.1.3 类型擦除

类型擦除指的是泛型声明用法执行的类型安全检测仅在编译期进行。在运行期间不保留实参的任何信息,即无法用as来判断类型。然而有一种例外即内联函数的具体化类型参数。

1.6.2 声明处型变

型变分为两种:协变和逆变。用法分别是在参数前加上out和in。

协变的时候对象是作为生产者,也就是说它只负责产出。逆变的时候对象是作为消费者,它只负责消费。具体代码如下所示:

interface Operation<out T>{fun eat():T
}interface Operation2<in E>{fun print(e:E)
}fun main(args: Array<String>) {val A:Operation<Number> = object:Operation<Int>{override fun eat():Int{return 17}}val B:Operation2<Int> = object:Operation2<Number>{override fun print(e:Number){println("Operation2")}}
}

1.6.3 使用处型变

使用处型变也称为类型投影,他是在不变类型上动态做协变或者逆变。

    val list1:MutableList<String> = mutableListOf()list1.add("hello")list1.add("world")val list2:MutableList<out String> = mutableListOf()list2.add("hello")  // compile errorlist2.add("world")  // compile errorval list3:MutableList<in String> = mutableListOf()list3.add("hello")list3.add("world")lateinit var list4:MutableList<String>list4 = list3;     // compile error

如上所示MutableList是一个不变对象。当使用out时,list2即变成协变的对象,他不能作为消费者而只能是生产者。对应的当使用in时候,list3就变成了逆变的对象。

1.6.5 星投影

有种场景是参数类型未知,那么星投影的功能就是声明对象的只读特性。
Foo <out T:Tupper>,那么Foo<*>表示的意义就是该对象作为生产者,可以安全的读取读取TUpper 的值。

fun main(args: Array<String>) {val star6: Star3<*> = Star3<String>("hello word")println(star6.getValue())
}class Star3<T:CharSequence>(private var t: T) {fun getValue(): T {return this.t}
}

打印出的是"hello word",那么可以理解为out修饰参数的时候,星投影会则输出的是Sting的类。

Foo <in T>,那么Foo<*>表示的意义就是该对象作为消费者,不能写入任何数据。这个好理解,既然类型都不知道,输入什么都是不安全的。也就是只读不能写了。
Foo <T:Tupper>,那么Foo<*>表示的意义就是结合了上面两种场景。写入时候不能安全写入任何数据,读取时只能安全读取 TUpper 的值。

2.总结

总体上感觉kotlin的函数是对java的方法做了几点处理:

优化:比如说弥补了java泛型在只产出或者只消费的场景下无法型变的问题

智能:会在编译的时候就自动判别类型,比如说 val key = 1,key就自动判断为Int类型。这点在java做不到

扩展:引入了内联,以及类似运算符重载的中缀表示法。

接下来继续学习内联函数,扩展函数等其他类型的函数。

kotlin读书笔记之函数基本知识以及泛型相关推荐

  1. Kotlin读书笔记之内联函数、扩展函数、匿名函数、lambda

    本文主要涉及内联函数.扩展函数.lambada以及匿名函数等.作为读书笔记对于细节深入没有过多的扩展,后续将对于各个知识点作进一步的研度.本文的内容主要是参考官方教程以及博客内容,作为读书笔记以及后续 ...

  2. kotlin 读书笔记

    <Kotlin 编程权威指南> 读书笔记 1 匿名函数 2 null安全的操作符 3 标准库函数 4 构造函数 5 Object 关键字 1 匿名函数 函数的定义 就是 把表达式或语句 放 ...

  3. kotlin读书笔记之基础语法

    1.初识Kotlin 1.1 变量 变量的定义写法上和java差别挺大的.变量分为可读以及可读可写,而且kotlin会自动推测出变量的类型,可推测的情况下. val a: Int = 1 // 立即赋 ...

  4. Kotlin读书笔记之优雅且高效的Kotlin

    一. Kotlin的流畅性 1.1. 重载运算符 说到运算符重载,是不是想起来大学被C++折磨的日子.传统上,我们对数值类型来创建表达式,例如:2 + 3 或 4.2 * 7.1.运算符重载是一种特性 ...

  5. 【黑客免杀攻防】读书笔记6 - PE文件知识在免杀中的应用

    0x1 PE文件与免杀思路 基于PE文件结构知识的免杀技术主要用于对抗启发式扫描. 通过修改PE文件中的一些关键点来达到欺骗反病毒软件的目的. 修改区段名 1.1 移动PE文件头位置免杀 工具:PeC ...

  6. Kotlin读书笔记之函数式kotlin

    一. 使用lambda进行函数式编程 函数式代码是声明式的 - 你关注于做什么,并将如何做的细节分配给底层函数库.现在的Java这种命令式编程在去过很长时间都是主流,Java处理命令式风格还有面向对象 ...

  7. 世界是数字的重点读书笔记(计算机科普知识)

    <世界是数字的>是世界顶尖计算机科学家Brian W.Kernighan写的一本计算机科普类读物,简明扼要但又深入全面地解释了计算机和通信系统背后的秘密,适合计算机初学者和非计算机专业的人 ...

  8. 《世界是数字的》读书笔记(计算机科普知识)

    <世界是数字的>是世界顶尖计算机科学家Brian W.Kernighan写的一本计算机科普类读物,简明扼要但又深入全面地解释了计算机和通信系统背后的秘密,适合计算机初学者和非计算机专业的人 ...

  9. kotlin读书笔记之类与对象

    1. 类与继承 1.1 类的用法 与java一样使用class声明类,后面可以跟着大括号: class Invoice { /*--*/ } class Empty 1.2 构造函数 kotlin可以 ...

最新文章

  1. App 组件化/模块化之路——如何封装网络请求框架
  2. 互联网分布式微服务云平台规划分析--服务监控中心
  3. IFE-16 addEventHandler跨浏览器实现事件绑定
  4. Android之LinearLayout线性布局
  5. 计算机管理器win,进入windows启动管理器,win启动管理器
  6. GoogleAppEngine是什么?
  7. Trust Region Policy Optimization (TRPO) 背后的数学原理
  8. vba随机抽取人名不重复_用vb编写个随机滚动抽取人名的抽奖系统,怎么样做到不重复并添加一个记录显示已抽到的人名...
  9. 恋爱物语iapp源码导入就可以用
  10. python zip压缩_用Python处理ZIP压缩包
  11. 【最佳实践】行云管家数据库运维审计解决方案
  12. mqtt 服务器 ca 证书,如何将SSL MQTT客户机与CA签名服务器证书连接?
  13. 异常:The JSP specification requires that an attribute name is preceded by whitespace
  14. 5G推动下,XR的需求“爆发”会来自B端还是C端?...
  15. 新C++(9):谈谈,翻转那些事儿
  16. 一线互联网企业高级Android工程师面试题大全,含小米、腾讯、阿里
  17. 国开本科计算机应用基础操作题,新版国家开放大学中央电大本科计算机应用基础操作题题库...
  18. Kali之Crunch:自定义字典
  19. 什么是Base-64编码
  20. Ubuntu boot menu

热门文章

  1. 02-Bootstrap基本性组件
  2. 如何写高大上的 godoc(Go 文档)
  3. 两天血赚1w7,我搬了一趟家,却险些面临甲醛超标的问题,说说这魔幻的两天...
  4. wget批量下载文件
  5. 销售业绩-各区负责人大盘情况PPT汇报
  6. ARM学习笔记 计算机结构 总线 南北桥
  7. 2023美赛ICM F题 详细思路
  8. opkg list 报错
  9. detectron2使用自定义数据集及数据加载
  10. USB controller介绍及controller驱动移植