流程控制是一门语言中最重要的部分之一,从最经典的if...else...,到之后的switch,再到循环控制的for循环和while循环,都是在开发中离不开的。
之前在第一篇博文中提到了Kotlin中的for循环和foreach循环,从中可以看出Kotlin在这些流程处理中下了很大一片功夫,也进行了人性化的创新。
接下来我们就从最经典的if ... else ...来讲起!
说起if,我们已经非常熟悉了。也许它的执行效率却在某些情况下不是最高的,但是它的实用性绝对是最高的!
最传统的用法咱们不讲,咱们讲讲Kotlin中if创新的用法:
Kotlin在操作符中,没有三元操作符case ? A : B,但是我们仍然有替代方案,那就是Kotlin中的if (case) A else B。在缺少三元操作符这一块上,Kotlin使用类似了python的方法,使用if ... else ...来代替!
fun main() {
val flag = 1 == 2
println(if (flag) "true" else "false")
}
反正只要是三元运算符可以做的,if表达式可以做到!
块,就是代码块,也就是说if后面可以带上代码块,这是Java所做不到的
我们举一个例子
fun main() {
val a = -114
val b = -1919
val max = if (a > b) {
println("$a is larger than $b.")
println("max variable holds value of a.")
a
} else {
println("$b is larger than $a.")
println("max variable holds value of b.")
b
}
println("max = $max")
}
/*
-114 is larger than -1919.
max variable holds value of a.
max = -114
进程已结束,退出代码0
*/
我们发现,{}内中的内容我们也执行了。注意的一点是,代码块中最后一行是返回值,这也是lambda的特性之一!
这里不得不提一句,每次在Java中写三元运算符的时候,总想写一些骚操作,比如在三元运算符的时候执行方法,但是偏篇不行,非得写成4行的if...else...,但是在Kotlin中,方法、代码块都能在if ... else ...中实行了,实在是太方便了!
上述的代码可以转换成这样的:
fun main() {
val a = -114
val b = -1919
val max = if (a > b) shutA(a,b) else shutB(a,b)
println("max = $max")
}
fun shutA(a: Int, b: Int): Int {
println("$a is larger than $b.")
println("max variable holds value of a.")
return a
}
fun shutB(a: Int, b: Int): Int {
println("$b is larger than $a.")
println("max variable holds value of b.")
return b
}
同样的,if块也可以使用if ... else if ... else ...的方式
这个可是Kotlin独有的表达式,可以说是switch的增强版,非常的实用!
在上一篇博文讲解for循环的例子中,我们就简单的使用了when表达式,现在我们来具体分析一下
我们举一个简单的when表达式的例子:
fun main() {
println("输入符号")
val result = when (val operator = readLine()) {
"+" -> 0
"-" -> 1
"*" -> 2
"/" -> 3
else -> -1
}
println("selected index = $result")
}
我们使用when来进行选择,()内是选择的一个对象,这里选择的是我们在控制台写入的一行字符串
对应我们在控制台写入的不同的情况,会给reslut变量赋不同的值
再看一种不用when赋值的情况
fun main() {
val a = 12
val b = 5
println("输入符号 +, -, * , /")
when (val operator = readLine()) {
"+" -> println("$a + $b = ${a + b}")
"-" -> println("$a - $b = ${a - b}")
"*" -> println("$a * $b = ${a * b}")
"/" -> println("$a / $b = ${a / b}")
else -> println("$operator 不是有效符号")
}
}
这种场景就很类似于switch了,只不过 -> 之后可以执行{}区域内的代码块
还有多情况的when选择,也可以使用,隔开表示多种情况
fun main() {
val n = -1
when (n) {
1, 2, 3 -> println("n is a positive integer less than 4.")
0 -> println("n is zero")
-1, -2 -> println("n is a negative integer greater than 3.")
}
}
我们还可以配合is关键字和!is来判断是我们选择的对象是否是某个类
fun main() {
val mutableListOf = mutableListOf("String", false, 1, 'c')
mutableListOf.forEach() {
when(it) {
is String -> println("String")
is Boolean -> println("Boolean")
is Char -> println("Char")
else -> println("Int")
}
}
}
当然,我们还可以判断区间!在刚开始学编程的时候,你肯定做过一种题目,就是考试成绩的打印,多少分到多少分是什么挡位,频繁的if...else...写腻了,为何不试试愉快的when呢?
fun main() {
println("请输入你的分数")
when(readLine()?.toInt()) {
in 0 until 60 -> println("不及格")
in 60 until 80 -> println("良好")
in 80 .. 100 -> println("优秀")
else -> println("请输入正确的成绩")
}
}
还有最后一种when无参的情况,也就是when 中的参数可能并非满足我们的需求,我们可以选择省略该参数
fun main() {
val tmp = "1"
val tmp2 = "2"
when {
tmp == "1" -> println(tmp)
tmp2 == "2" -> println(tmp2)
}
}
这样会打印出"1",到这里when就终止啦,我们可以通过这样的使用方式来进行多个选择
首先因为while循环和大多数语言没有太大的区别,所以这里就不介绍了,直接介绍break和continue
break和continue是配合for循环、while循环使用的控制循环执行的两个关键字。之所以我要讲这两个关键字,是因为在Kotlin中有了更强大的使用方式
最基本的使用方式我这里就不多说了,我直接举一个Kotlin中特有的例子
fun main(args: Array<String>) {
first@ for (i in 1..4) {
second@ for (j in 1..2) {
println("i = $i; j = $j")
if (i == 2)
break@first
}
}
}
/*
i = 1; j = 1
i = 1; j = 2
i = 2; j = 1
*/
看着代码,你应该理解了break@one的含义,没错,中断用one@标注的这一层循环!
瞬间对Kotlin的处理方式佩服的五体投地。在以往要处理各个嵌套循环,因为要控制条件,往往不能这么写,但是Kotlin支持给for循环、while循环添加@标注,然后对标注的循环体进行break和continue,实在是太香了!
那么带标签的continue也是一样的使用方式:
fun main(args: Array<String>) {
here@ for (i in 1..5) {
for (j in 1..4) {
if (i == 3 || j == 2)
continue@here
println("i = $i; j = $j")
}
}
}
/*
i = 1; j = 1
i = 2; j = 1
i = 4; j = 1
i = 5; j = 1
*/
首先说明一点,Kotlin的语言逻辑和C++类似,既可以面向对象,也可以面向过程。
我们这里提及的函数,仅仅是单方面满足处理需求的,并不是与对象相关的方法
不在对象中的,被称之为函数
这是 Kotlin 标准库的链接,可以参阅!
Kotlin中变量的定义在第一篇博文中就讲了,那么如果函数中存在参数,一样的就在()中写入传入的参数变量就可以了
值得注意的是Kotlin中是值传递,而非引用传递,所以更改传递进来的局部变量参数,并不会改变函数之外传入参数的真实值
例如,一个最简单的加法函数的编写:
fun add(a:Int,b:Int) : Int {
return a+b
}
当然,如果函数返回单个表达式,则可以省略函数主体的花括号{ },并在=符号后指定主体,例如
fun add(a:Int,b:Int) : Int = a+b
当然,再省略一点,可以让Kotlin自动推断返回值类型
fun add(a:Int,b:Int) = a+b
中缀函数算是Kotlin的一个特色,用户可以自定义中缀函数来进行操作
我们之前学习过的区间中的 ..,downTo,until,in等,其实都是中缀函数,包括Map中的to也是中缀函数,之前说是关键字,其实并不准确,准确来说是一个中缀函数
同时,在这里得提到,与Java不同,Kotlin中没有按位运河移位运算符,为了解决这种问题,Kotlin官方使用了中缀函数来完成
shl - 符号左移shr - 符号右移ushr - 无符号右移and - 按位和or - 按位或xor - 按位异或inv - 按位反转那么如何创建一个带有中缀符号的函数呢?有下面几个限制
例如我在自己写的一个Student类中,定义一个输出学号的中缀函数callNumber
class Student() {
infix fun callNumber(number: String) = println("学生的学号为$number")
}
fun main() {
val student = Student()
student callNumber "20203199"
}
/*
学生的学号为20203199
*/
或者我们可以在现有的类中添加中缀函数,例如我在Int类型中添加一个add的中缀函数
infix fun Int.add(tmp:Int) = this+tmp
fun main() {
println(1 add 2)
}
/*
3
*/
在Kotlin中,函数传参相比Java得到了非常强的优化,用户体验非常的好,在我看来甚至比python还要好。
Kotlin中运行函数在编写的时候就设置默认参数,所谓默认参数就是拥有默认值的参数,例如
fun add(a:Int = 114, b:Int = 1919) :Int {
println("first == $a second == $b")
return a+b
}
fun main() {
println(add())
}
/*
first == 114 second == 1919
2033
*/
这种情况就是使用了默认的a = 114 b = 1919的情况
那么如果我们仅仅赋值一个参数呢?
fun add(a:Int = 114, b:Int = 1919) :Int {
println("first == $a second == $b")
return a+b
}
fun main() {
println(add(810))
}
/*
first == 810 second == 1919
2729
*/
可以发现Kotlin第一个参数是默认赋值给第一个传参的
那么如果我们想给第二个参数b赋值,而不给a赋值呢?
fun add(a:Int = 114, b:Int = 1919) :Int {
println("first == $a second == $b")
return a+b
}
fun main() {
println(add(b=810))
}
/*
first == 114 second == 810
924
*/
使用指定传参就可以啦!
值得注意的是,Kotlin函数中允许传入函数(方法)这类参数,步骤比Java简单太多了,只需要指定类型为()即可,例如:
fun add(a:Int = 114, b:Int = 1919, myMethod : ()->Unit ) :Int {
myMethod()
println("first == $a second == $b")
return a+b
}
fun main() {
val res = add(myMethod = { println("this is test method") })
println(res)
}
/*
this is test method
first == 114 second == 1919
2033
*/
这里传递进去的第三个参数就可以是一个方法(函数),myMethod : ()->Unit 的含义是:myMethod 是一个返回值为Unit类型的函数,Unit相当于Java中的void类型
上述代码等同于
fun add(a:Int = 114, b:Int = 1919, myMethod : ()->Unit ) :Int {
myMethod()
println("first == $a second == $b")
return a+b
}
fun main() {
val res = add(myMethod = { testMethod() })
println(res)
}
fun testMethod() = println("this is test method")
也可以这样写:
fun add(a:Int = 114, b:Int = 1919, myMethod : ()->Unit ) :Int {
myMethod()
println("first == $a second == $b")
return a+b
}
fun main() {
val res = add() {
println("测试方法")
println("你当然可以在这个方法中写很多内容!")
}
println(res)
}
也就是说,如果函数中只有一个函数参数,我们可以在括号内写lambda表达式来表述方法,也可以在括号外写lambda表达式来表示方法。
如果是两个函数传参呢?可以这样写
fun add(a:Int = 114, b:Int = 1919, myMethod : ()->Unit, myMethod2:()->Unit ) :Int {
myMethod()
myMethod2()
println("first == $a second == $b")
return a+b
}
fun main() {
val res = add(myMethod = {println("测试1")}, myMethod2 = { println("测试2") })
println(res)
}
或者
fun add(a:Int = 114, b:Int = 1919, myMethod : ()->Unit, myMethod2:()->Unit ) :Int {
myMethod()
myMethod2()
println("first == $a second == $b")
return a+b
}
fun main() {
val res = add(myMethod = {println("测试1")}) {
println("测试2")
}
println(res)
}
这样的话,()外层的lambda表达式默认是最后一个函数参数的表述实现
什么叫做动态参数?也就是可以传递很多同类型的但是值不同的参数,例如下面的append()函数
fun myAppend(vararg ch:Char): String {
val res = StringBuffer()
ch.forEach {
res.append(it)
}
return res.toString()
}
fun main() {
val myAppend = myAppend('w', 'o', 'o', 'd', 'w', 'h', 'a', 'l', 'e')
println(myAppend)
}
/*
woodwhale
*/
这里的ch这个参数是不定长的,因为我们使用了vararg修饰
由于篇幅限制,本篇仅仅讲述了Kotlin中的流程控制和函数的部分内容,之后会学习Kotlin的OOP(面向对象)!
前面一篇关于智能合约翻译文讲到了,是一种计算机程序,既然是程序,那就可以使用程序语言去编写智能合约了。而若想玩区块链上的项目,大部分区块链项目都是开源的,能看得懂智能合约代码,或找出其中的漏洞,那么,学习Solidity这门高级的智能合约语言是有必要的,当然,这都得在公链``````以太坊上,毕竟国内的联盟链有些是不兼容Solidity。Solidity是一种面向对象的高级语言,用于实现智能合约。智能合约是管理以太坊状态下的账户行为的程序。Solidity是运行在以太坊(Ethereum)虚拟机(EVM)上,其语法受到了c++、python、javascript影响。Solidity是静态类型
Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法,Linux…感兴趣就关注我吧!你定不会失望。目录1.ls显示当前目录下的文件内内容2.pwd-显示用户当前所在的目录3.cd-改变工作目录。将当前工作目录改变到指定的目录下1.cd-回到上一次待的工作空间2.cd..返回上一层目录1.相对路径:cd../aurora2.绝对路径:cd/home/aurora/lesson1/aurora3.cd~进入用户家目录4.cd/进入root目录4.mkdir-新建目录5.rmdir/rm-删除1.rmdir删除空文件夹2.rm删除1.rm-f2.rm-i3.rm-r1.ls显示当前目
我正在尝试在Kotlin学习功能编程,并且难以使此代码起作用:importjava.util.*funcaseName(br:String,c:Int):String{if(c==0){returnbr.toLowerCase()}else{returnbr.toUpperCase()}}funmapIt(ns:ArrayList,f:(String,Int)->String):List{valcoll:List=ns.map{it->f(it,_)}returncoll}funmain(args:Array){valnames=arrayListOf("Joe","Bill","Murrar
gtest是Google开发的一个开源单元测试框架,代码提供丰富的注释和实例,参考实际用例可以很快上手基本单元测试,丰富的代码注释能够让有兴趣的开发者深入了解gtest的代码结构并做部分针对性的二次开发。gtest主要针对c/c++提供了针对函数接口和类方法丰富测试方法,针对单元测试特有的数据或者代码反复编写的这种特性做了集成和优化,满足当前绝大部分对于单元测试的需求。其有如下特点:自动收集测试用例,无需开发者再次组织提供强大的断言集,支持包括布尔、整型、浮点型、字符串等。提供断言方法自定义扩展提供死亡测试功能使用参数化自动生成多个相似的测试用例可以将公共的用例初始化和清理工作放入测试夹具中,
一鸿蒙简介HarmonyOS是一款面向万物互联时代的、全新的分布式操作系统。在传统的单设备系统能力基础上,HarmonyOS提出了基于同一套系统能力、适配多种终端形态的分布式理念,能够支持手机、平板、智能穿戴、智慧屏、车机等多种终端设备,提供全场景(移动办公、运动健康、社交通信、媒体娱乐等)业务能力。HarmonyOS提供了支持多种开发语言的API,供开发者进行应用开发。支持的开发语言包括Java、XML(ExtensibleMarkupLanguage)、C/C++、JS(JavaScript)、CSS(CascadingStyleSheets)和HML(HarmonyOSMarkupLan
前言在进入软件测试的正式讲解之前,我们需要对这个行业有一个整体的了解。当我们从软件开发转向软件测试的时候,多数公司是欢迎的,而且难度也小。反之,当我们从软件测试转向软件开发的时候,难度将会变得很大。关于互联网的工作大概有以下三种:1、软件开发:进行软件系统的开发,功能实现的工作2、软件测试验证软件功能性的正确性。具体的验证方式分为以下几种:1、手工验证2、自动化验证3、软件测试与开发开发测试工具,开发测试脚本,其目的就是为了提高测试效率。看到开发这两个字,说明是会涉及到编程的。但是难度会比软件开发低一些,没有数据结构中的编程那么难。测试开发这里的编程,都是有着指定规则来编写代码。换句话来说,它
我有一个RecycleView,我想对其进行迭代并在每个输入字符串前添加一个项目符号点。我有以下内容:值.strings.xml•%1$s配置文件列表适配器:funbindSkills(skill:String){itemView.recycleSkillItem.text=String.format(Locale(R.string.skill.toString()),${R.string.skill},skill)}这一遍又一遍地打印相同的int而没有要点。在kotlin中格式化字符串的最佳实践是什么? 最佳答案 您应该先了解
我试图从url链接解析xml,例如:http://a.cdn.searchspring.net/help/feeds/sample.xml,我可以从文件中解析它,但不能从url链接中解析。这是我的代码:importandroidx.appcompat.app.AppCompatActivityimportandroid.os.Bundleimportandroid.widget.SimpleAdapterimportandroid.widget.ListViewimportorg.w3c.dom.Elementimportorg.w3c.dom.Nodeimportorg.xml.sa
我正在编写一个批处理作业来解析XML、提取字段并将它们保存在数据库中。解析XML时,它选取2个根元素,但将所有字段保留为空,因此在我的数据库中我有2个记录将为空字段。似乎无法弄清楚为什么它无法读取元素...TIA@BeanfunxmlFileItemReader(environment:Environment):ItemReader{valxmlFileReader=StaxEventItemReader()xmlFileReader.setResource(ClassPathResource(environment.getRequiredProperty(PROPERTY_XML_S
我正在制作自定义进度条,如下图所示:基本上,我创建了一个可绘制的xml背景文件:然后我将它应用到我正在使用的View中:完全没问题,我可以实现方案1和方案2,但是当条形图接近尾端时,我如何以编程方式设置View右上角和右下角的圆角,直到它看起来就像照片3一样?谢谢。 最佳答案 试试这个publicstaticvoidcustomView(Viewv,intbackgroundColor,intborderColor){GradientDrawableshape=newGradientDrawable();shape.setShape