【Kotlin 二】函数/高阶函数/内联函数 对象/主构造函数/次要构造函数/对象初始化

ops/2024/9/24 7:22:22/

1.函数

函数声明如下:

kotlin">fun 函数名称([函数参数...]): 返回值类型{// 方法体
}fun sum(num1: Int, num2: Int): Int {return num1 + num2
}

注意:Kotlin函数返回值为空时为Unit,并非常见的void

函数可以设置默认值:

kotlin">fun printNum(numA: Int = 10, numB: Int = 20): Int{println(numA + numB)
}

函数入参默认为val(常量),不支持在方法体中修改

1.1 常用的库函数

println:输出一行

readln:接收一行

pow:取次方

1.2 高阶函数

一个函数如果入参类型 or 返回值类型是函数,那么这个函数就是一个高阶函数

一个变量可以有各种各样的类型(Int/String/…),函数当然也会有自己的类型

对于下面的函数,(String) -> Int就是该函数的类型。函数类型其实就是将函数的入参和返回值抽象出来。

kotlin">fun test(str: (String)): Int {return str.toInt()
}

1.2.1 变量接收函数(声明)

Kotlin支持将函数赋给一个变量,与Java不同的是格式上有所区别

kotlin">// func1为一个能够表示函数的变量,该函数接收一个Int作为入参,没有返回值
var func1: (Int) -> Unit

既然Kotlin已经能够使用变量接收函数了,那么必然就能使用函数A作为函数B的形参

kotlin">// test作为一个函数,能够接受另一个函数的返回值作为入参
// 形参函数的入参事String,返回值是一个Int
fun test(num1: (String) -> Int) {}

1.2.2 变量接收函数(赋值)

对于已有函数,可以使用::获取函数引用

kotlin">fun main() {var func: (String) -> Int = ::testprintln(func("1"))
}fun test(str: (String)): Int {return str.toInt()
}

也可以直接写匿名函数:

kotlin">fun main() {var func: (String) -> Int = fun(str: String): Int {return str.toInt()} 
}

匿名函数还有一种更简洁的写法(项目中绝大多数采用这种Lambda表达式来调用高阶函数):

kotlin">fun main() {var func: (String, String) -> Unit = { str1: String, str2: String ->println(str1 + str2)}func("a", "1")
}
// 输出
a1

因为Kotlin有匿名推断机制,所以lambda入参类型可以去掉

kotlin">fun main() {var func: (String, String) -> Unit = { str1, str2 ->println(str1 + str2)}func("a", "1")
}

在lambda表达式只有一个入参的情况时,无需显式写明入参,在函数体内可以直接使用it来代替入参

kotlin">val func1: (Int) -> Unit = {println(it)}

1.4 内联函数

类似于C++,Kotlin使用inline声明一个内联函数。内联函数在编译时会被编译器直接替换到调用该方法的地方

kotlin">fun main() {test()
}inline fun test() {println("111")
}// 内联函数替换后
fun main() {println("111")
}

2.对象

2.1 主构造函数

一个类可以有多个构造函数,直接写在类名后的是主构造函数。这种形式可以写上默认值,也可以不写

kotlin">class Student constructor(var name: String, var age: Int) {}

也可以将类属性放在类体中,类似于Java,但是这种形式要求必须写上默认值

kotlin">class Student () {var name: String = ""var age: Int = 0
}

还有一种形式是以上两种形式结合起来,下面这种方法能够自定义getter和setter

kotlin">class Student (name: String, age: Int) {var name: String = nameget() = fieldset(value) {field = value + "1"}var age: Int = ageget() = fieldset(value) {field = value * 10}
}

和Java一样,如果没有规定主构造函数,那么Kotlin会为当前类生成一个无参的默认构造函数;如果规定了主构造函数,那么就不会再有默认的无参构造函数

2.2 次要构造函数

次要构造函数还是需要使用this()来调用主构造函数。次要构造函数可以有自己的函数体

kotlin">class Student (var name: String, var age: Int) {constructor(name: String): this(name, 0) {// 次要构造函数体}
}

2.3 对象的初始化

因为主构造函数没有函数体,想在对象初始化阶段进行操作时,可以使用init块

kotlin">class Student (var name: String, var age: Int) {init {println(name + "出生了")}
}

2.4 初始化顺序

当执行一个对象的构造函数时,对应的初始化顺序如下:

  1. init代码块
  2. 主构造函数(如果没有会执行默认的无参构造函数)
  3. 次要构造函数

2.5 空值和空类型

Kotlin默认所有的类型都是非空类型,即编译阶段就可以避免出现变量被赋值为null的情况出现

如果真的需要将某个变量在初始化情况下使用null而不是某个具体的对象,需要在类型名称后加一个?将该变量声明为可空类型

kotlin">fun main() {val student: String? = null
}

Kotlin提供了一种安全的空类型操作:如果想要安全地访问可能包含null值的对象的属性,可以使用安全调用运算符?.

如果对象属性为null则返回null

如果想在可空变量实际为null时返回一个指定的结果,可以使用?:

kotlin">fun main() {var student: Student? = nullvar studentName: String = student?.name ?: "name"println(studentName)
}

2.6 访问控制权限

Kotlin有4种访问控制权限:public/internal/protected/private

其中internal是Java所没有的。如果使用了internal修饰符,他将在当前的项目中可以随意访问,权限等同于public,但是如果别人引用我们的项目,别人无法使用被修饰的东西


http://www.ppmy.cn/ops/47660.html

相关文章

从头搭hadoop集群--分布式hadoop集群搭建

模板虚拟机安装配置见博文:https://blog.csdn.net/weixin_66158110/article/details/139236148 配置文件信息如下:https://pan.baidu.com/s/1074eD5aNVugEPcjwVvi9jA?pwdl1xq(提取码:l1xq) hadoop版本:h…

【网络编程开发】4.socket套接字及TCP的实现框架 5.TCP多进程并发

4.socket套接字及TCP的实现框架 Socket套接字 Socket套接字是网络编程中用于实现不同计算机之间通信的一个基本构建块。 在现代计算机网络中,Socket套接字扮演着至关重要的角色。它们为应用程序提供了一种方式,通过这种方式,程序能够通过网…

鸿蒙轻内核M核源码分析系列七 动态内存Dynamic Memory

内存管理模块管理系统的内存资源,它是操作系统的核心模块之一,主要包括内存的初始化、分配以及释放。 在系统运行过程中,内存管理模块通过对内存的申请/释放来管理用户和OS对内存的使用,使内存的利用率和使用效率达到最优&#x…

SOCKS 代理 和 HTTP 代理, WebSocket

SOCKS 代理 和 HTTP 代理 的区别 SOCKS 代理 和 HTTP 代理 都是代理服务器,它们充当客户端和目标服务器之间的中介,但它们的工作方式和应用场景有所不同。 1. SOCKS 代理: 工作原理: SOCKS 代理是一种更底层的代理,…

一维时间序列突变检测方法(小波等,MATLAB R2021B)

信号的突变点检测问题是指在生产实践中,反映各种系统工作状态的信号,可能因为受到不同类型的噪声或外界干扰而发生了信号突变,导致严重失真的信号出现,因此必须探测突变出现的起点和终点。研究目的在于设计出检测方案,…

安全风险 - 检测设备是否为模拟器

在很多安全机构的检测中,关于模拟器的运行环境一般也会做监听处理,有的可能允许执行但是会提示用户,有的可能直接禁止在模拟器上运行我方APP 如何判断当前 app 是运行在Android真机,还是运行在模拟器? 可能做 Framework 的朋友思…

k8s群集调度之 pod亲和 node亲和 标签指定

目录 一 调度约束 1.1K8S的 List-Watch 机制 ⭐⭐⭐⭐⭐ 1.1.1Pod 启动典型创建过程 二、调度过程 2.1Predicate(预选策略) 常见的算法 2.2priorities(优选策略)常见的算法 三、k8s将pod调度到指定node的方法 3.1指…

【C#】中托管与非托管对象区别、托管与非托管DLL区别

C 中的托管与非托管的区别_托管程序和非托管程序-CSDN博客 C# 中托管与非托管对象区别 在C#中,托管对象和非托管对象的主要区别在于内存管理和执行环境: 托管对象 (Managed Objects) 内存管理:托管对象的内存由.NET运行时(CLR…