Kotlin笔记——基础

数据类型

只有引用类型,处于高性能需求,Kotlin编译器会把Int,Byte等在Java字节码中改变成基本数据类型

类型推断:可省略对象的类型(编译的时候会自动检测)

val s = "编译时自动检测出是String类型"

String模板

支持在字符串的引号内放入变量值,使用$或${ }

关键字

const 用于修饰常量的,const val 相当于Java中的 static final

lateinit 延时初始化        obj.isInitialized判断延迟初始化对象是否初始化了

in 关键字判断是否在某个范围内,或者用于遍历范围内的对象   is 判断是否属于某 类型 

条件表达式

when/if else 都可以当作表达式和语句使用,当做表达式的时候都需要需要else语句,代码中有else if分支,都建议改成when表达式
range表达式,结合通过in关键字来定义范围

区间

var a = 1..100          //   [1,100]

var a = 1 until 100   //   [1,100)

a.reversed()     //将数字倒转,相当于  a = 100 .. 0

for循环

var nums = 1 .. 100 

for(num in nums)              //遍历每个值 1,2,3 ... 100

for(num in nums step 2)   //每间隔2个步长遍历 1,3,5,7 ... 99

for(num in nums downTo 0) //递减直到值为0  ,  100,99 ... 0

符号

?   //当前对象可以为空,加在变量名后,系统在任何情况不会报它的空指针异常

?.   //安全的调用某个对象的方法,如果对象为null,则不再调用该方法,直接返回一个null对象,而不会抛空指针异常

var nameStr : String = user?.name

类似Java的:

String namseStr = null;
if (user != null){ 
    namseStr = user.getName();
}

?: //Elvis运算符,安全的调用某个对象的方法,如果对象为null,则返回一个默认的值

var nameStr : String = user?.name?:"hxx";

类似于Java的:

String nameStr ;
if (user != null && user.getName() != null){
    nameStr = user.getName();
} else {
    nameStr = "hxx";
}

!!    //当前对象不为空时执行代码,加在变量名后,如果对象为空,系统报空指针异常NullPointerException

var nameStr = user!!.name!!.trim()

//这样写的前提是,我们确定user和user.name不会为null,否则就像我们Java中获取bean里面的值,却没有判空一样,容易抛异常

::   //把一个方法当做一个参数,传入另一个方法中

例如:

fun money (name: String, y: Int): String {
    return "${name}通过自己的努力,股票赔了${y}¥"
}

fun someBody (name: String, age: Int): String {
    return "${name}今年刚刚年满${age}岁"
}

//前两个参数为变量,第三个参数为方法
fun test( x: String, y: Int ,methed: (a: String, b: Int) -> String) : String{
    return methed(x ,y )
}


//调用:通过test方法,第三个参数传入想要执行的方法名,传入的方法不同,得到的结果不同
var a = test("张三",10000000, :: money)
var b = test("小明",18, :: someBody)
println(a)
println(b)


//结果
张三通过自己的努力,股票赔了10000000¥
小明今年刚刚年满18岁


//效果相当于
var a = money("张三",10000000)
var b = someBody("小明",18)

集合关系图(图片在网上找的) 

Collection interfaces hierarchy

list.indices通过索引遍历数组或集合,in关键字可用于遍历集合

函数

格式:可见性修饰符 函数声明关键字  函数名  函数入参  返回值类型

private   fun    methdName   (param :String)   :  Object  {   }

Unit函数:没有返回值的函数叫Unit函数,它的返回类型为Unit,可以省略(和Java中的Void有点类似)

TODO函数:它的任务就是抛异常,返回的是Nothing类型

默认参数、具名参数

默认参数:于Java不同,kotlin函数可以指定某个参数的默认值,若该参数的值为默认值时,该参数可以不用传入,其他参数以

例如:

 fun test(a : Int = 10, b : Int) : Int{
      return a * b;
   }

var c =  test(b = 8)//c为80
 fun test(a : Int = 7) : Int{
      return a % 2;
   }

var c =  test()//c为1

具名参数:变量名 = 值   的方式传入即可(其中变量名为函数声明时的参数名字,又叫具名参数)。它的好处是不应关注传入参数的顺序,减少了函数的重载。

例如:

fun test(name:String, age:Int, address:String){
 //method body
}


//test
test(address = "BeiJing", age = 18, name = "Hxx")

反引号函数

Kotlin可以使用空格、特殊字符和关键字对函数命名,但是函数名需要用一对反引号括起来

private fun  `h  函数 is`(){}

fun `in`():Int(){}

高阶函数

把一个函数作为参数或者返回值 的函数

上面例子中的test方法就属于高阶函数,下面我们介绍下集合中常用的高阶函数:

maxBy{}   最大值,{}里面条件是某个属性值,返回该属性是最大值的对象

minBy{}   最小值,{}里面条件是某个属性值,返回该属性是最小值的对象

filter{}      过滤特定条件的集合,{}里的条件是布尔表达式,返回过滤后的集合

map{}      根据条件,把某个属性映射成一个新的对象的集合,并返回

any{}       根据条件判断,满足条件返回true,否则返回false

count{}    根据判断条件,返回符合该条件下对象的个数

find{}       根据条件查找第一个满足条件的对象,并返回

groupBy{it.属性}    根据条件(对象的某个属性)将集合中不同值的对象分组并返回该集合

groupBy{it.属性} .get{属性A}   在groupBy{it.属性}返回的集合中,返回该属性值为"属性A"的集合

data class Student(var name: String, var address: String, var age: Int, var sex: String)

val classOne = listOf<Student>(
    Student("李宁", "北京", 43, "男"),
    Student("天霸", "上海", 13, "女"),
    Student("动霸", "苏州", 16, "男"),
    Student("动霸", "上海", 33, "男"),
    Student("竹竿", "苏州", 18, "男"),
    Student("超甜", "上海", 21, "女"),
    Student("胖子", "北京", 27, "男"),
    Student("麦霸", "苏州", 19, "男")
)

fun main() {
    println("maxBy--> "+classOne.maxBy { it.age })//年龄最大的对象
    println("minBy--> "+classOne.minBy { it.age })//年龄最小的对象
    println("filter--> "+classOne.filter { it.address == "苏州" })//过滤出address == "苏州" 的所有对象
    println("any--> "+classOne.any { it.address == "苏州" })//是否有address == "苏州"的对象,返回ture
    println("map--> "+classOne.map { "(${it.name},${it.sex})"})//生成一个只有名字和性别的集合
    println("count--> "+classOne.count { it.age in 18..20 })//年龄在[18,20]之间的个数
    println("find--> "+classOne.find { it.address == "上海" })//第一个上海的对象
    println("groupBy--> "+classOne.groupBy { it.sex })//以性别分组,返回各个组的数据
}

结果

maxBy--> Student(name=李宁, address=北京, age=43, sex=男)
minBy--> Student(name=天霸, address=上海, age=13, sex=女)
filter--> [Student(name=动霸, address=苏州, age=16, sex=男), Student(name=竹竿, address=苏州, age=18, sex=男), Student(name=麦霸, address=苏州, age=19, sex=男)]
any--> true
map--> [(李宁,男), (天霸,女), (动霸,男), (动霸,男), (竹竿,男), (超甜,女), (胖子,男), (麦霸,男)]
count--> 2
find--> Student(name=天霸, address=上海, age=13, sex=女)
groupBy--> {男=[Student(name=李宁, address=北京, age=43, sex=男), Student(name=动霸, address=苏州, age=16, sex=男), Student(name=动霸, address=上海, age=33, sex=男), Student(name=竹竿, address=苏州, age=18, sex=男), Student(name=胖子, address=北京, age=27, sex=男), Student(name=麦霸, address=苏州, age=19, sex=男)], 女=[Student(name=天霸, address=上海, age=13, sex=女), Student(name=超甜, address=上海, age=21, sex=女)]}


 

函数递归:尾递归优化

我们在调用递归函数时sum(100000),计算机由于递归次数太多,会报错栈溢出:StackOverflowError

fun sum (n : Int) : Int{
    if(n == 1){
        return 1
    }else {
        return n + sum(n - 1)
    }
}

在Java中,当出现这种问题,我们毫无办法,kotlin中则提出了尾递归的解决办法

fun sum (n : Int, result:Int) : Int{
    if(n == 0){
        return 0
    }else {
        return sum(n - 1, result + n)
    }
}

//调用
var result = 0
sum(10000,result)

open

open修饰的类,可以被继承,如果想要里面的方法或者属性,能够被重写的话,也需要用open来修饰

另外,abstract修饰的抽象类属性和方法,默认都是可以被重写的,不需要显示声明open

可见性修饰符

private,protected,internal,public

public: 默认的修饰符,所有地方都可见

internal: 在相同模块内都可见(模块:指Module,Maven项目,Library等)

protected: 在自己所在的文件内以及子类中可见,只能修饰接口和类中的成员,不能修饰顶层声明

private : 只能被自己所在的文件可见,且外部类不能访问内部类的 private 成员

成员:成员变量、成员方法、内部类、内部接口;

局部声明:局部变量、函数和类不能有可见性修饰符;

包或顶层声明:Java中只能是类、接口,而kotlin的顶层成员,可以是类、接口、函数、属性。

例如:
 
test.kt文件中,可以不需要类和接口的包裹,直接写函数或属性,调用时 文件名.成员  的形式:

package com.mytest

var x = 0

val URL = "http://www.com/"

fun sum (x:Int ,y :Int) :Int{
    return x + y
}

protected class A (){
    ...
}
...


静态类 object、companion object

1.object:用于修饰静态类或者静态内部类,类似于Java中的static修饰符,例如

object A{
    fun action(){
        println("我就是我,天下无双")
    }
}

//调用

A.action()

2.companion object:伴生对象,伴生对象在类中只能有一个。一般在一个非静态类中来声明一个伴生对象,里面的方法和属性都是静态的,可以直接用   类名.方法/属性名   来调用,且伴生对象中,只能调用静态的方法或属性。

class A {
    fun test1(){
        println("test1")
    }

    companion object {
        fun test2(){
            println("test2")
        }
    }
}


//调用
A().test1()
A.test2()

密封类(印章类):seales class :子类类型有限的class

1.密封类里类似于枚举,在类中只能声明有限个内部类,且必须是它的子类,但每个子类可以有多个对象;

2.密封类的所有子类都必须与蜜蜂类在同一个文件中;

3.密封类没有构造函数,不可以直接实例化,只能实例化内部的子类;

4.密封类子类的子类可以在其他文件中定义

sealed class SealedClass{
    class Son1() : SealedClass()

    class Son2() : SealedClass()

    fun eat() {
        println("美食")
    }

}


//调用

var son1 : SealedClass = SealedClass.Son1()
son1.eat()

接口的代理、委托模式(待完善)

关键字  by  

interface Human{
  fun work()
}


object Worker : Human{
 fun work(){
    println("我是工人,勤劳的小蜜蜂")
    }
}



class Boss : Human by Worker{
 fun work(){
    println("我是Boss,有钱不想干活")
    Worker.work()
    }
}

//调用时,只需调用Boss的work方法,但工作还是Worker完成的
//Boss().work()
//结果
//我是Boss,有钱不想干活
//我是工人,勤劳的小蜜蜂

DSL(领域特定语言)

两个前提:

1.扩展函数

2.中缀表达式

扩展函数加上 infix 关键字,就可以用空格代替“.”区调用函数

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值