赞
踩
![在这里插入图片描述](https://img-
blog.csdnimg.cn/b348d6f3f301482c8e6845676674b346.gif#pic_center)
* 1、默认变量不可赋空值
* 1、捕获并处理异常
* 1、先决条件函数概念
Java 中的空指针问题 :
在 Java 语言 编写的程序中 , 出现最多的崩溃就是 NullPointerException 空指针异常 ,
该异常是 运行时 才爆出的 , 在 代码编写时 以及 编译期 很难提前排查出来 ;
Kotlin 的空安全机制 :
在 Kotlin 语言 中 , 针对 空指针异常 问题 进行了优化 , 引入了 空安全机制 ,
在代码编写后的 编译期 , 就可以 提前排查出可能出现的空指针异常问题 , 并提前进行处理 ,
这样极大地提高了 Kotlin 程序的 代码健壮性 ;
在 Java 中 , 引用类型的变量 默认为 null
空值 ;
但是在 Kotlin 中 , 变量默认不可为 null
空值 ,
这样所有的 变量 在默认状态下 , 都有一个 默认的实例对象 ,
从而极大的 减少了 空指针异常 出现的概率 ;
代码示例 : 先定义一个 name
变量 , 为其赋值字符串 "Tom"
,
然后再为其赋值 null
空值 ;
fun main() {
var name = "Tom"
name = null
}
此时 , 在 IntelliJ IDEA 中 就会提示如下报错信息 :
Null can not be a value of a non-null type String
这是因为 var name
变量 默认为非空的 ,
在 Kotlin 中 不允许将 默认变量 赋值一个空值 ,
除非 将该变量声明为 可空类型 ;
声明可空类型变量 :
如果要声明一个 可空类型的变量 , 必须 声明该变量的具体的类型 ,
并在该类型后添加 ?
标志 , 具体格式如下 :
var 变量名: 变量类型?
代码示例 : 在下面的代码张红 ,
将 var name
变量声明为了 String?
可空类型 ,
此时就可以为 该变量 赋值 null
值 ;
fun main() {
var name: String? = "Tom"
name = null
}
进行了 String?
可空类型声明后 , 在 IntelliJ IDEA 中 , 就不再进行报错了 ;
Kotlin 语言中 , 变量类型 分为 可空类型 和 非空类型 ,
默认状态 下 , 变量是 非空类型 的 ,
如果使用 类型?
将变量声明为 可空类型 ,
那么就需要使用 手动安全管理 ;
代码示例 : 在下面的代码中 , 将 name
变量声明为了 String?
可空类型 ,
那么 调用该可空类型变量 的 成员 或 方法 时 , 就不能直接调用了 ,
必须引入 手动安全管理 ;
fun main() {
var name: String? = "Tom"
name.count()
}
上述代码中 , 在调用该变量时 , 就会出现如下报错信息 :
Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
在 Kotlin 语言中 , 调用 可空类型变量 的 成员 时 ,
可以使用 " 安全调用操作符 " 也就是 ?
进行调用 ,
使用格式如下 :
可空类型变量?.成员
使用了 安全调用操作符 之后 , 在调用变量成员前 , 会自动进行 空值检查 ,
如果该变量为空 , 则会 跳过后面的 成员调用 , 继续执行下一行代码 ;
代码示例 : 在下面的代码中 , 调用 name
变量时 , 使用 ?
安全调用操作符 name?.count()
进行调用 ;
fun main() {
var name: String? = "Tom"
name?.count()
}
如果想要在 变量 原有基础上 , 继续执行其它操作 , 可以使用let
标准函数 ;
安全调用操作符 经常与 let
标准函数 一起使用 ;
如 : 以 name?.let{}
方式调用 let
函数 ,
其含义是 如果 name
变量不为空 , 则调用 let
函数 ,
如果 name
变量为空 , 则跳过后面的 let
函数执行 ;
代码示例 : 在下面的代码中 ,
将变量 name
声明为了 可空类型 String?
,
为 name
变量执行一些 附加操作 时 , 可使用 ?.let{}
方式进行 ,
含义是 , 假如 name
变量不为空 , 则执行 let
函数中的 Lambda 表达式内容 ,
let 函数 返回 匿名函数 最后一行 ,
该 Lambda 表达式 / 匿名函数 / 闭包 的含义是 ,
如果 name
变量 字符串非空白, 将其转为首字母大写 , 并返回 ,
如果 name
变量 字符串为空白, 设置 Hello
值为返回值 ;
fun main() {
var name: String? = "tom"
name = name?.let {
// let 函数返回 匿名函数 最后一行
if(it.isNotBlank()) {
// 如果字符串非空白, 将其转为首字母大写
it.capitalize()
} else {
// 如果字符串为空白, 设置默认值
"Hello"
}
}
println(name)
}
执行结果 :
Tom
Kotlin 中的 可空类型 变量 , 在运行时 可以选择 不启用 安全调用 操作 ,
在调用 可空类型 变量 成员 与 方法 时 , 使用 非空断言操作符 !!
,
如果 可空类型 变量为 空 , 则 直接抛出 空指针异常 KotlinNullPointerException
;
代码示例 : 在下面的代码中 , name
变量是 String?
可空类型 ,
变量值为 null
,
如果使用 name?.count()
的方式调用 , 则会先判定 name
是否为空 , 如果为空则该代码不会执行 ,
如果使用 name!!.count()
的方式调用 , 不会判定 name
是否为空 ,
如果 为空 抛出 KotlinNullPointerException
异常 ;
fun main() {
var name: String? = null
println(name!!.count())
}
执行结果 :
Exception in thread "main" kotlin.KotlinNullPointerException
at HelloKt.main(Hello.kt:3)
at HelloKt.main(Hello.kt)
在 Kotlin 中 , 对于 可空类型 变量的调用 , 除了使用
?
!!
之外 , 还可以使用 Java 语言中的传统判空方式 ,
即 if
语句判断 变量 是否为 null
;
空安全调用操作符?
与 使用 if 语句判空操作 对比 :
二者的效果是等价的 ;
代码示例 1 : 下面的代码是 使用 if 语句判空 的示例 ;
fun main() {
var name: String? = null
var count: Int? = null
if(name != null) {
count = name.count()
}
println(count)
}
执行结果 :
null
代码示例 2 : 下面的代码 与 代码示例 1 的 效果是等价的 , 显然本代码更加简洁 ;
fun main() {
var name: String? = null
var count: Int? = name?.count()
println(count)
}
执行结果 :
null
空合并操作符?:
用法 :
表达式 A ?: 表达式 B
如果 表达式 A 的值 不为 null
, 则 整个表达式的值 就是 表达式 A 的值 ;
如果 表达式 A 的值 为 null
, 则 整个表达式的值 就是 表达式 B 的值 ;
代码示例 : 在下面的代码中 ,
name
变量 被声明为 String?
可空类型的变量 , 为其赋值为 null
,
使用 name ?: "name 变量为空"
代码 , 其效果如下 :
空合并操作符 左侧的 name
表达式如果为 null
, 则 取 右边的 表达式 作为该表达式最终的值 ,
如果 左侧的 name
表达式 不为 null
, 则 取 该 name
变量作为 该表达式最终的值 ;
因此 , 第一次使用 name ?: "name 变量为空"
代码时 , name
为空 , 整个表达式 name ?: "name 变量为空"
返回的是 "name 变量为空"
值 , 打印出来的就是 name 变量为空
内容 ;
之后 为 name
变量赋值 "Tom"
字符串值 , 现在 name
变量不为空 , 使用 name ?: "name 变量为空"
代码返回的是 name
变量的值 , 因此打印出来的就是 Tom
内容 ;
fun main() {
var name: String? = null
println(name ?: "name 变量为空")
name = "Tom"
println(name ?: "name 变量为空")
}
执行结果 :
name 变量为空
Tom
空合并操作符 ?:
与 let 函数 结合使用 , 可以 替代 if .. else ..
语句 ;
代码示例 :
fun main() {
var name: String? = null
name = "tom"
name = name?.let {
it.capitalize()
} ?: "Jerry"
println(name)
}
执行结果 :
Tom
如果 name
变量为 null
, 则 ?:
表达式中 , 会选择 ?:
后面的表达式作为最终结果 ;
对应代码如下 :
fun main() {
var name: String? = null
name = name?.let {
it.capitalize()
} ?: "Jerry"
println(name)
}
执行结果 :
Jerry
在 Kotlin 程序中 , 处理异常 的方式有 :
捕获异常代码示例 : 在下面的代码中 ,
name
变量是可空类型变量 , 其初始值为 null
,
使用 非空断言操作符 !!
调用 变量 成员 , 不会进行 空值检查 ,
如果变量为空 , 则直接抛出 kotlin.KotlinNullPointerException
异常 ;
使用 try .. catch ..
代码块 , 可以捕获并处理异常 ;
import java.lang.Exception
fun main() {
var name: String? = null
// 捕获并处理异常
try {
name!!.count();
} catch (e: Exception) {
println(e)
}
}
执行结果 :
kotlin.KotlinNullPointerException
抛出自定义异常代码示例 : 在下面的代码中 ,
声明了自定义 异常类 MyException
, 其继承了 KotlinNullPointerException
空指针异常类 ,
在调用 name
变量成员时 , 先调用 checkNull
函数 ,
检查该变量是否为空 ,
使用 str ?: throw MyException()
代码 , 其中 空合并操作符 判定 str
是否为空 ,
如果为空 , 则抛出 MyException
异常 ;
import java.lang.Exception fun main() { var name: String? = null // 捕获并处理异常 try { checkNull(name) name!!.count(); } catch (e: Exception) { println(e) } } fun checkNull(str: String?) { str ?: throw MyException() } class MyException: KotlinNullPointerException("空指针")
执行结果 :
MyException: 空指针
在 Kotlin 中提供了一些 内置函数 ,
在这些函数中可以抛出 携带自定义信息的异常 ,
这些函数 就是 " 先决条件函数 " ;
只有满足了 先决条件函数 的 先决条件 , 代码才能继续执行 , 否则就会抛异常 ;
常用的先决条件函数如下 :
checkNotNull 函数 :
null
, 抛出 IllegalStateException
异常 ,/**
require 函数 :
false
, 抛出 IllegalArgumentException
异常 ;/**
requireNotNull 函数 :
null
, 抛出 IllegalArgumentException
异常 ;/**
error 函数 :
null
, 使用给定的 错误信息 抛出 IllegalStateException
异常 ;/**
assert 函数 :
false
, 抛出 AssertionError
异常 , 并进行 断言标记 ;/**
代码示例 : 在执行 name
字符串的 count
函数之前 ,
先使用 checkNotNull(name, {"变量为空"})
先决条件函数 , 判定 name
是否为空 ,
如果为空 , 抛出带信息的 IllegalStateException
异常 信息 ;
fun main() {
var name: String? = null
// 捕获并处理异常
try {
checkNotNull(name, {"变量为空"})
name!!.count();
} catch (e: Exception) {
println(e)
}
}
执行结果 :
java.lang.IllegalStateException: 变量为空
上述使用的 先决条件函数checkNotNull
原型 :
/** * 如果[value]为空,则使用调用[lazyMessage]的结果抛出[IllegalStateException]。否则 * 返回非空值。 * * @sample samples.misc.Preconditions.failCheckWithLazyMessage */ @kotlin.internal.InlineOnly public inline fun <T : Any> checkNotNull(value: T?, lazyMessage: () -> Any): T { contract { returns() implies (value != null) } if (value == null) { val message = lazyMessage() throw IllegalStateException(message.toString()) } else { return value } }
学习网络安全技术的方法无非三种:
第一种是报网络安全专业,现在叫网络空间安全专业,主要专业课程:程序设计、计算机组成原理原理、数据结构、操作系统原理、数据库系统、 计算机网络、人工智能、自然语言处理、社会计算、网络安全法律法规、网络安全、内容安全、数字取证、机器学习,多媒体技术,信息检索、舆情分析等。
第二种是自学,就是在网上找资源、找教程,或者是想办法认识一-些大佬,抱紧大腿,不过这种方法很耗时间,而且学习没有规划,可能很长一段时间感觉自己没有进步,容易劝退。
如果你对网络安全入门感兴趣,那么你需要的话可以点击这里
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。