关键字
var val
var name = "张三"
name = "李四" //true
name = 1//false name初始化时为String类型
val name = "赵五"
name = "你好"//false name 用val修饰不能被改变 应该相当于final
函数
fun test(args:Array<String>):Int{
return 3
}
判断字符串是否相等
fun equalStr(i:String , j:String){
i==j//true
}
equalStr("张三","张三")//true kotlin的==只比较对象是否相等,不比较内存地址值
kotlin提供了一个equals的重载方法,用于忽略大小写的比较 equals(str,true)//true为忽略 false 为不忽略
val ss = fun (name : String) = println("ssdd")// 函数名为ss的函数 默认函数体为一条打印语句
fun 代表为函数 、test为函数名、args为参数名 Array<String>为参数类型 类型为字符串数组 、Int为返回值 返回值为Int类型
字符串模板 ${}
ex:
fun dayin(str:String):String{
return "你的${str}真好"
}//运行该函数时传入的内容会直接显示在返回值里
null关键字
函数参数中加?表示参数可以传null 不加?表示不能传入null值
ex:
fun test(str:String?):String{
return "别"+str
}
如果不加? 则调用函数传入test(null)会报错 加上可以传入空 test(null) -->别null
str : String!! 两个叹号表示一定不为空
!!表示当前对象不为空的情况下执行
when表达式(ex:考试满分10分,9分还不错,6分刚及格,6分一下不及格)
fun checkGrade(score:Int){
when(score){
10 ->println("满分")
9 ->println("还不错")
6 ->println("及格了")
else ->println("不及格")
}
}
fun xx(num:Int):String{
var result = when(num){
1->"一"
2->"二"
else->"三"
}
return result
}
Loop(循环)和Range(区间)
var num = 1 .. 100 // [1,100] 头尾都包含 1~100
var num2 = 1 until 100 // [1,100) 包含头不包含尾 1~99
var result = 0
fun test(){
for(x in num){
result = result+x
}//循环 关键字in
}
step
var num = 1..16
num.count()//总数
for(x in num step 2){
打印结果为 1 3 5 7 9 11 13 15
}
List 和Map
var lists = listOf("你是谁","你在哪","你好啊","我不好")//定义一个集合list
var map = TreeMap<String,String>()
map["一"] = "one"
map["二"] = "two"
map["三"] = "three"
println(map["一"]) //"one"
函数和函数式表达
1、fun add(x:Int, y:Int) : Int = x+y
2、fun add(x:Int,y:Int):Int{
return x+y
}
3、var i = {x : Int ,y : Int -> x+y}//变量i就是一个函数 用时 println( i(2,3))
4、var j : (Int,Int)->Int = {x,y -> x+y}// println(j(2,3))
//如果函数内部只有一句return的语句 2的写法可以省略成1的写法
默认参数和具名参数以及变长参数
val Pi= 3.1415926
fun getRectArea(PI:Float = Pi,radius:Float):Float{
return 2*PI*radius
}
fun main(args:Array<String>){
var area = getRectArea(radius = 2.0f)//具名参数 调用方法后 因为方法已经给出pi是默认参数的默认值 所以直接用具名参数 radius = 2.0f即可调用函数
println(area)//打印圆的周长
}
字符串转数字
var a = "13"
var b = 13
a = b.toString()
b = a.toInt()
异常处理
try{
}catch{
}finally{
}
循环
while(true){
}
var ssList = listOf<T>(x1,x2,x3,x4,x5)//建立一个集合 里面add五个元素
for(name in ssList){
}
forEach循环
fun aa(){
(0..100).forEach{
if(50<= it) return@forEach
println(it)
}
}
递归
fun digui(num:Int):Int{
if(num==1){
return 1;
}else{
return num *digui(num-1)
}
}//阶乘
递归计算100的阶乘 用Long类型也装不下 用BigInteger
fun degui2(n:Int):Int{
if(n==1){
return 1
}else{
return n+degui2(n-1)
}
}//累加
尾递归
tailrec fun weidigui(n:Int ,result :Int):Int{
if(n==0){
return 1
}else{
return weidigui(n-1,result+n)
}
}// tailrec关键词实现尾递归 要求返回值要是函数本身 所以这里用了两个参数来写做累加的函数
面向对象 封装
private fun add(){}
继承
open class father{
var name = "张三"
open fun add(){
}
}
class son : father(){
override fun add(){
}
}
kotlin中继承用:来表示 子类继承父类 父类必须有关键词open 重写父类方法时 父类方法必须有关键词open
子类复写的方法上要有关键词override
重写接口或父类方法都要有override关键字
抽象类
abstract class Human(var name : String){
abstract fun eat()
}
class Man(name : String) : Human(name){
override fun eat(){
println("")
}
}
接口
interface IMan{
fun xiaodidi()
}
class Man : IMan{
override fun xiaodidi(){
println("")
}
}
实现接口不用加括号 继承抽象类要加个括号
class Man:Human(),IMan{
override fun xiaodidi(){
}
override fun eat(){
}
}
var house = listOf<Human>(ren,taijian)
for(p in house){
if(p is Man)
}
委托和代理
kotlin接口代理关键字 by
interface IWashBowl{
fun washing()
}
class 大头儿子 :IWashBowl{
override fun washing(){
洗碗
}
}
class 小头爸爸 :IWashBowl by 大头儿子(){
override fun washing(){
通过by可以调儿子的洗碗方法
大头儿子().washing()
}
}
单例模式
关键字:object
object class 大头儿子{
object关键词修饰后大头儿子类为单例 内存中有且只有一个实例
}
大头儿子() //表示创建了一个大头儿子对象
大头儿子 //表示没有创建大头儿子对象
刚才上面这段代码
class 小头爸爸 :IWashBowl by 大头儿子(){
override fun washing(){
大头儿子().washing()//此处又重新创建了一个大头儿子对象 因为大头儿子类是单例的 所以不用加括号
}
}
class 小头爸爸 :IWashBowl by 大头儿子{
override fun washing(){
大头儿子.washing()//此处又重新创建了一个大头儿子对象 因为大头儿子类是单例的 所以不用加括号
}
}
枚举
enum class Week{
星期一,星期二,星期三,星期四,星期五,星期六,星期天
}
印章类Sealed class
子类类型有限的class
有三个类 小母驴 小公马 小公驴
sealed class Son {//她们三个类生出来的儿子只可能是骡子或驴 所以用sealed指定
fun sayHello(){
println("")
}
class 小小驴() :Son()
class 小骡子() :Son()
}
关键字
lateinit 延迟加载 只能修饰var 不能修饰val, 非kotlin基本类型
companion object 修饰静态类和静态方法
const只能修饰val,不能修饰var 经过const修饰的常量,才是java中理解的常量
const val NUM = 8
internal java里面有public protected private 和默认修饰符, kotlin里多了个internal 被internal修饰的 模块内可见(同一个module下)
as 强制转换 , Kotlin里面,Int类型不能使用as转换为String类型。第二,使用as运算符进行类型转换,如果转换错误,会抛出异常
“?”运算符,是kotlin提供的安全的类型运算符,使用“?.”进行类型转换的时候,如果转换失败,则会返回null,而不会抛出异常
val a = 5
val b = a as? String
多行输入符 三个双引号
val str = """
one
two
"""
Unit 如果函数不会返回任何有用值,那么他的返回类型就是 Unit
this关键字 用this@xx来表示 xx可以是类名也可以是函数名
operator fun ss() //告诉编译器要定义一个运算符的方法了
infix fun xs()// infix 为中缀表达式
可变参数 变长参数 vararg
fun asList<T> (vararg num :T) :List<T>{
}
变长参数相当于java的可变参数 (...)
调用时 asList(1,2) asList(1,2,3) asList(1,2,3,4)
val a = array(1,2,3)
val list = asList(1,2,*a,4) 传递一个 array 的内容给函数,我们就可以使用 * 前缀操作符 这个*只支持对于变长参数的场景 而且只能展开数组
inner 内部类
class xxx{
private inner class xxx{
}
}
字符串与对象地址比较
"11"=="11"//true 相当于equals
new String("123")==="123"//false 相当于== 比较的是内存地址
内联扩展函数之let
let扩展函数的实际上是一个作用域函数,当你需要去定义一个变量在一个特定的作用域范围内,
let函数的是一个不错的选择;let函数另一个作用就是可以避免写一些判断null的操作。
类的构造方法
class 妹子 constructor (var 长相:String,var 性格:String){
init{ //init{}是构造方法的方法体,在每一次创建一个对象的时候都会调用
}
} //只有一个构造方法时constructor可以省略
var 妹儿 :妹子 = 妹子(美,好)//根据构造方法传入参数长相美,性格好 new一个妹子 出来
kotlin里的object 是Any
空类型和智能类型的转换
String?
String!!
包
import com.palmap.activity.sss
import com.palmap.activity.sss as bbb
同一个类下有相同类名的包导入 可以在导包的时候用as 给他起个别名
数组
val arrayOfInt : IntArray = intArrayOf(1,2,3)
val arrayOfChar : charArray = charArrayOf('a','b','c')
val arrayOfString : Array<String> = arrayOf("sss","www","vvv")
常量val和变量var
运行时常量 val name = “你好啊”
编译期常量 const val name = "嗯好"
类型推导
只要编译器可以猜到你定义 的变量或常量的类型 就可以不用写类型
ex val ss = "sss"
val ss = 5
var x = getString()+5//String类型
Lambda表达式
Lambda表达式实际是一个匿名函数
写法:
{[参数列表] - > [函数体,最后一行是返回值]}
val sum = {arg1 :Int,arg2 :Int -> arg1+arg2}
Lambda表达式类型举例
()->Unit //无参,返回值为Unit
(Int) ->Int//传入一个整型,返回一个整型
(String ,(String)->String) -> Boolean //传入字符串,Lambda表达式,返回布尔
调用:
用()调用 == 用invoke调用
println(sum(1,2))
println(sum.invoke(1,2)) //invoke是kotlin里自带的方法
Lambda表达式的简化
args.forEach(::println)简化过程
args.forEach({println(it)})
对于函数来说,如果他的最后一个参数是Lambda表达式,就可以把大括号里的内容移到外面去
args.forEach(){println(it)}
如果小括号里什么也没有,小括号可以省略
args.forEach{println(it)}
如果传入的函数和需要接收的Lambda表达式是完全一样的,还可以进一步简化
args.forEach(::println)
如果Lambda表达式只有一个参数,默认为it
fun main(args : Array){
args.forEach{
if(it=="q")return
println(it)
}
println("完事了")
} //执行以后 打印语句“完事了”执行不到 因为forEach属于Lambda表达式 这里的return是直接return main函数如果想要return循环 可以给循环起个名字
fun main(args : Array){
args.forEach ForEach@{
if(it=="q")return@ForEach
println(it)
}
println("完事了")
}
表达式
条件表达式 中缀表达式
val mode = if(){ xxx }else{ sss } 如果要这样写需要写完整 就是有if也要有else
多层循环嵌套 可以起名告诉编译器要跳出哪个循环
Outter@for(,,,){
Inner@while(,,,){
if(..)break@Outter
}
}
解决两个接口里有相同名字相同返回值相同参数的方法,方法名冲突的问题 用super<>泛型里面加上要调用那个方法的接口名字
网友评论