Kotlin入门学习记录
2023/11/27
可空类型
在KT中为了避免空指针异常,禁止直接给变量赋予空值,如下错误演示
var str = null
但null依然存在,即可以声明可空类型,如下
//声明了一个可空的字符串类型
var str:String? = null
null安全
为了避免风险,KT禁止在可空类型值上直接进行调用函数,如下错误演示
var str:String? = readLine().capitalize()
安全调用符
使用?
加到函数调用前,如果值为null
则自动跳过函数执行,如下
var str:String? = readLine()?.capitalize()
使用if
也可以达到相应的效果,如下
var str:String? = readLine()
if( str != null){
str = str.capitalize()
}
let函数
标准库函数,一般结合安全调用符使用,如下
var str:String? = "butterfly"
str = ""
str = str?.let {
//非空白字符串
if (it.isNotBlank()){
it.capitalize()
}else{
"butterfly"
}
}
println(str)//butterfly
非空断言操作符
使用!!
加到函数调用前,如果值为null
正常执行函数,但会抛出KotlinNullPrintException且程序中止,如下
var str:String? = "butterfly"
str = null
println(str!!.capitalize())
空合并表达式
使用?:
加到函数调用前,如果左值为null
则使用右侧的值,如下
var str:String? = "butterfly"
str = null
str = str?.let { it.capitalize() } ?: "butterfly"
println(str)
自定义异常
fun main() {
var number:Int? = null
try {
checkOperation(number)
number!!.plus(1)
} catch (e: Exception) {
println(e)
}
}
fun checkOperation(number:Int?){
number?:throw UnskilledExcaption()
}
class UnskilledExcaption():IllegalAccessException("操作不当")
先决条件函数
KT中提供了便利函数,这些函数可以抛出自定义信息的异常
函数 | 描述 |
---|---|
checkNotNull | 如果参数为null,抛出IllegalStateException,否则返回非null值 |
require | 如果参数为false,抛出IllegalArgumentException |
requireNotNull | 如果参数为null,抛出IllegalStateException,否则返回非null值 |
error | 如果参数为null,抛出IllegalStateException并输出错误信息,否则返回非null值 |
assert | 如果参数为false,抛出AssertError,并打上断言编译器标记 |
代码实现如下
fun main() {
var number:Int? = null
try {
checkOperation(number)
number!!.plus(1)
} catch (e: Exception) {
println(e)
}
}
fun checkOperation(number:Int?){
checkNotNull(number,{"something is notgood"})
//java.lang.IllegalStateException: something is not good
}
String操作
KT的String函数是基于Java的加强
substring函数
两种传参方式
- 和Java一样传递起始下标和结束下标进行截取
- 传递range表达式,如下
const val NAME = "LY_C's friend"
fun main() {
var indexOf = NAME.indexOf('\'')
var str = NAME.substring(0, indexOf)//LY_C
str = NAME.substring(0 until indexOf)//LY_C
println(str)
}
Java实现如下
String NAME = "LY_C's friend";
int indexOf = NAME.indexOf('\'');
System.out.println(NAME.substring(0, indexOf));//LY_C
split函数
两种获取返回值的方式
- 和Java一样用数组接收
- 支持解构语法即多变量接收,如下
const val TEST = "LY_C.CRY.CHEN"
fun main(){
var data = TEST.split(".")
//依次输出数组数据
data.forEach({
println(it)
})
var (name1,name2,name3) = TEST.split('.')
println(name1 + name2 + name3)//LY_CCRYCHEN
}
Java实现如下
String TEST = "LY_C.CRY.CHEN";
String[] array = TEST.split("\\.") ;
for (String s : array) {
System.out.println(s);
}
replace函数
和Java一样字符串替换函数,不同的是可以结合lamdba表达式,如下
var str1 = "I asdi YOU!"
var str2 = str1.replace(Regex("[asdi]")){
when(it.value){
"a" -> "L"
"s" -> "O"
"d" -> "V"
"i" -> "E"
else -> it.value
}
}
println(str2)//I LOVE YOU!
Java实现如下
String str1 = "I asdi YOU!";
String str2 = str1.replace("a", "L")
.replace("s", "O")
.replace("d", "V")
.replace("i", "E");
System.out.println(str2);
字符串比较
在KT中的==
和===
与Java不同
在KT中==
比较的字符串的内容而在Java中是比较的是引用
在KT中===
比较的字符串指向堆上的对象和Java的equals方法相同
在JVM中,为了减少不必要的内存开辟,字符串存放在字符串常量池中并且是不可变的,当两个变量存放的字符串一样则这两个变量都指向相同的地址,如下
var str3 = "LY_C";
var str4 = "LY_C";
字符串比较,KT
var str3 = "LY_C"
//执行capitalize()时Jvm会新添加一个String对象"LY_C"
var capitalize = "lY_C".capitalize()
println(capitalize == str3)//true
println(capitalize === str3)//false
Java实现如下
String str2 = "LY_C";
//执行toUpperCase()时Jvm会新添加一个String对象"LY_C"
String upperCase = "lY_C".toUpperCase();
System.out.println(str2 == upperCase);//false
System.out.println(str2.equals(upperCase));//true
字符串遍历
使用forEach
,如下
var str3 = "LY_C";
str3.forEach { print(it) }//LY_C