草庐IT

Kotlin中空安全操作符,异常处理和自定义异常,以及先决条件函数详解

路宇 2023-07-24 原文

博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家
👉点击跳转到教程

一、Kotlin的可空性

null 在java中我们司空见惯的空指针异常NullPointerException,带给了我们很多麻烦。
Kotlin作为更强大的语言,势必会基于以往的语言设计经验对其进行改良。Kotlin更多
地把运行时可能会出现的null问题,以编译时错误的方式,提前在编译期强迫我们重视起来,
而不是等到运行时报错,防范于未然,提高了我们的程序的健壮性。

二、Kotlin中的安全调用操作符,非空断言操作符,空合并操作符的详解,代码中已经给出详细注释

fun main() {
    /**
     * 可空性:?
     * 对于null值问题,Kotlin反其道而行之,除非另有规定,变量不可为null值,这样一来,
     * 运行时崩溃问题从根源上得到解决。
     *
     * Kotlin的null类型:
     * 为了避免NullPointerException,Kotlin的做法是不让我们给非空类型变量赋null值,
     * 但null在Kotlin中依然存在。
     */
    var str: String? = "butterfly"
    str = null
    println(str)

    /**
     * null安全:
     * 1.Kotlin区分可空类型和非可空类型,所以,你要一个可空类型变量运行,而它又可能
     * 不存在,对于这种潜在危险,编译器时刻警惕着。为了应对这种风险,Kotlin不允许你在
     * 可空类型值上调用函数,除非你主动接收安全管理。
     */
    /**
     * 选项一: 安全调用操作符:?.
     * 这次Kotlin不报错了,编译器看到有安全调用操作符,所以它知道如何检查null值。如果
     * 遇到null值,它就跳过函数调用,而不是返回null。
     */
    println(str?.capitalize())
    str = "butterfly"
    str = str?.let {
        //非空白的字符串
        if (it.isNotBlank()) {
            it.capitalize()
        } else {
            "butterfly test"
        }
    }
    println(str)

    /**
     * 选项二:使用非空断言操作符:
     * 1.!!.又称感叹号操作符,当变量值为null时,会抛出KotlinNullPointerException
     */
//    str = null
//    println(str!!.capitalize())

    /**
     * 选项三:使用if判断null值情况
     * 我们可以使用if判断,但是相比之下安全调用操作符用起来更灵活,代码也更简洁,我们
     * 可以用安全操作符进行多个函数的链式调用。
     */
    if (str != null) {
        str.capitalize()
    } else {
        println("str 是空的")
    }

    str = str?.capitalize()?.plus(" is great.")
    println(str)

    /**
     * 使用空合并操作符
     * ?:操作符的意思是,如果左边的求值结果为null,就使用右边的结果值
     */
    str = null
    println(str ?: "str is null")

    /**
     * 空合并操作符也可以和let函数一起使用来代替if/else语句
     */
    str = null
    str = str?.let {
        it.capitalize()
    } ?: "butterfly"
    println(str)
}

输出结果如下:

null
null
Butterfly
Butterfly is great.
str is null
butterfly

三、异常处理和自定义异常,先决条件函数

fun main() {
    var number: Int? = null
    try {
        checkOperation(number)
        number!!.plus(1)
    } catch (e: Exception) {
        println(e)
    }
}

fun checkOperation(number: Int?) {
//    number ?: throw UnSkilledException()
    /**
     * 先决条件函数
     * Kotlin标准库提供了一些便利函数,使用这些内置函数,你可以抛出带自定义
     * 信息的异常,这些便利函数叫做先决条件函数,你可以用它定义先决条件,条件必须满足
     * 目标代码才能执行。
     */
    checkNotNull(number) {
        "Something is not good"
    }
}

/**
 * 自定义异常
 * IllegalArgumentException 有一个是java.lang包下的
 * 另外一个是kotlin下面的,kotlin下面的其实只是一个别名等于java.lang包下的
 * @SinceKotlin("1.1") public actual typealias IllegalArgumentException = java.lang.IllegalArgumentException
 */
class UnSkilledException() : IllegalArgumentException("操作不当")

输出结果如下:

java.lang.IllegalStateException: Something is not good

先决条件函数有如下:


四、substring、split、replace,字符串遍历方法的使用

const val NAME = "I like Android development"
const val WORK = "I,like,Android,development"
fun main() {
    /**
     * substring
     * 字符串截取,substring函数支持IntRange类型(表示一个整数范围的类型)的参数,
     * util创建的范围不包括上限值
     */
    val substring = NAME.substring(7, 14)
    var str = NAME.substring(7 until 14)
    println(substring)
    println(str)

    /**
     * split
     * split函数返回的是list集合数据,List集合数据又支持解构语法特性,它允许你
     * 在一个表达式里给多个变量赋值,解构常用来简化变量的赋值。
     */
    val data = WORK.split(",")
    //data[0] 取集合中的元素
    /**
     * 这就是解构语法
     */
    val (origin, dest, proxy, detail) = WORK.split(",")
    println("$origin $dest $proxy $detail")

    val text = "The people's Republic of China"
    val text2 = text.replace(Regex("[aeiou]")) {
        when (it.value) {
            "a" -> "8"
            "e" -> "6"
            "i" -> "9"
            "o" -> "1"
            "u" -> "3"
            else -> it.value
        }
    }
    println(text)
    println(text2)

    /**
     * 遍历字符串
     */
    "The people's Republic of China".forEach {
        print("$it *")
    }

}

输出结果如下:

Android
Android
I like Android development
The people's Republic of China
Th6 p61pl6's R6p3bl9c 1f Ch9n8
T *h *e *  *p *e *o *p *l *e *' *s *  *R *e *p *u *b *l *i *c *  *o *f *  *C *h *i *n *a *

五、- = =与===的比较

fun main() {
    /**
     * 字符串比较
     * 在kotlin中,用==检查两个字符串的字符是否匹配,用===检查两个变量是否
     * 指向内存堆上同一对象,而java中==做引用比较,做内容比较时用equals方法
     */
    val str1 = "Jason"
    val str2 = "jason".capitalize()
    println(str1 == str2) //true
    println(str1 === str2) //false
}

六、数字类型的安全转换函数,Double转Int类型、以及格式化

fun main() {
    /**
     * 数字类型
     * 和java一样,Kotlin中所有数字类型都是有符号的,也就是说既可以表示正数,也可以表示负数
     *
     */
    /**
     * 数字格式异常 NumberFormatException
     */
//    val number1: Int = "8.98".toInt()
    /**
     * 安全转换函数
     * Kotlin提供了toDoubleOrNull和toIntOrNull这样的安全转换函数,如果数值
     * 不能正确转换,与其触发异常不如干脆返回null值
     */
    val number: Int? = "8.9".toIntOrNull()
    println(number)

    val number2: Double? = "0.91".toDoubleOrNull()
    println(number2)

    val number3: Double? = "1.99".toDouble()
    println(number3)

    /**
     * Double转Int
     * 四舍五入
     */
    println(8.99.roundToInt())
    println(8.49.roundToInt())
    /**
     * Double转Int
     * toInt:精度损失
     */
    println(8.956.toInt())
    /**
     * 格式化字符串是一串特殊字符,它决定该如何格式化数据
     */
    val str = "%.2f".format(8.956)
    println(str)
}

输出结果如下:

null
0.91
1.99
9
8
8
8.96

有关Kotlin中空安全操作符,异常处理和自定义异常,以及先决条件函数详解的更多相关文章

  1. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  2. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  4. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  5. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  6. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

    我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

  7. ruby - 如何安全地删除文件? - 2

    在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?

  8. ruby-on-rails - 如何在 Rails 3 中创建自定义脚手架生成器? - 2

    有这些railscast。http://railscasts.com/episodes/218-making-generators-in-rails-3有了这个,你就会知道如何创建样式表和脚手架生成器。http://railscasts.com/episodes/216-generators-in-rails-3通过这个,您可以了解如何添加一些文件来修改脚手架View。我想把两者结合起来。我想创建一个生成器,它也可以创建脚手架View。有点像RyanBates漂亮的生成器或web_app_themegem(https://github.com/pilu/web-app-theme)。我

  9. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  10. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

随机推荐