kotlin屋

一、数值类型

(1)Kotlin中没有基本数据类型,都是对象,数值类型也是对象。

类型位宽度字节数事例范围
Byte811-128~127
Short1622-32768~32767
Int324123-2147483648~2147483647
Float324123.5f 
Long648123L 

Double

648123.5 

           注: 与java不同的是字符(char)不属于数值类型

                 2进制以0b开头:0b00001011

                 16进制以0x开头 :0x0F

                 8进制不支持

(2)基础数据类型的转换

        由于不同的标识方式,较小类型并不是较大类型的子类型,较小的类型不能隐式转换为较大的类型  

var a:Int=1
var b:Long=a    //报错  request  Long  found   Int

//正确的写法是显示转换
val b:Long=a.toLong();

        每种数据类型都有下面的这些方法:

toByte()     Byte
toShort()    Short
toInt()      Int
toLong()     Long
toFloat()    Float
toDouble()   Double
toChar()     Char
toString()   String

         自动类型转换

var a=1L
var b=a+100    //101    b为Long类型

(3)数字装箱,Int?标示可空引用时,不一定保留统一性(===比较内存地址  ==比较大小)

//情况一
var a:Int=1000
println(a===a)                      //true
//装箱,创建两个不同的对象(内存不一样,值一样)
val boxedA:Int?=a
val boxedAnotherA:Int?=a
println(boxedA===boxedAnotherA)           //false
println(boxedA==boxedAnotherAB)            //true  

//情况二
var  b:Int=5;
val  boxedB:Int?=b
val  boxedAnotherB:Int?=b
println(boxedB===boxedAnotherB)           //true
println(boxedA==boxedAnotherB)            //true

注:数字装箱值在-128到127之间时,是从IntegerCache.cache中拿的,而不在该范围则是每次创建一个Integer对象,所以上面的结果返回的不一致,不一定保留统一性

(4)位操作符

       对于Int和Long类型,还有一系列的位操作符

shl(bits) – 左移位 (Java’s <<)
shr(bits) – 右移位 (Java’s >>)
ushr(bits) – 无符号右移位 (Java’s >>>)
and(bits) – 与
or(bits) – 或
xor(bits) – 异或
inv() – 反向

 事例:

val a = 60
val b = 13
var c = -5
println(a and b)    // 与   12
println(a or b)     // 或   61
println(a xor b)    // 异或   49
println(a.inv())    // 按位取反   -61
println(a.shl(1))   // 左移   120
println(a.shr(1))   // 右移    30
println(a.ushr(1))  // 无符号右移   30

二、字符

        Kotlin中的字符用Char标示,必须是单引号"  ' "包含起来的,不能直接与数字操作,如'0','a'

fun check(c:Char){
   if(c==1){//错误,类型不兼容
   }
}

fun decimalDigitValue(c: Char): Int {
    if (c !in '0'..'9')
        throw IllegalArgumentException("Out of range")
    return c.toInt() - '0'.toInt() // 显式转换为数字
}

       当需要可空引用时,像数字、字符会被装箱,装箱操作不一定会保留同一性。

三、布尔

       布尔用Boolean类型表示  ,它有两个值:true和false

       若需要可空引用布尔会被装箱

        内置的布尔运算有:

||  短路逻辑或
&& 短路逻辑与
逻辑非

四、字符串

  • 字符串是不可变的,方括号[ ]语法可以很不方便的获取字符串的某个字符
  • 遍历字符串
var  a="abc"
for(c in a){
   println(c)
}
  • 多行字符串  ,使用三个引号("""  """)
fun main(args: Array<String>) {
    val text = """
    多行字符串
    多行字符串
    """.trimMargin()
    println(text)   // 输出有一些前置空格,trimMargin方法会删除多余的空格
}
  •  字符串模板$
var  a="abc"
println("a=$a")//a=abc
println("$a.length is${a.length}")//abc.length is3

五、list

(1)list的创建

  • 只读集合listOf 
  • 可变集合mutableListOf      arrayListOf
  • ArrayList
//不可变
var list=listOf("a","b")

//可变方式1
var list=mutableListOf("a","b")
list.add("ccc");

//可变方式2
var list=arrayListOf("a")

//可变方式3
var list= ArrayList<String>(0);

//不可变到可变
var list=listOf("aaa")
var list2=list.toMutableList()

(2)list遍历

  • Iterator
var it=list2.iterator()
while(it.hasNext()){
   println(it.next())
}
  • for  in循环
//通过下标
for(index in list2.indices){
  println(list2[index])
}

//直接通过元素
for(item in list2){
  println(item)
}
  • withIndex()
for((index,value) in list2.withIndex()){
   println("$index,$value")
}
  • forEach
list2.forEach{
  println(it)
}

六、Set

(1)Set的创建

  • 只读集合 set      setOf
  • 可变集合MutableSet    mutableSetOf
//不可变
var set1=setOf("aaa","bbb")

//可变
var set3=mutableSetOf("aaaa")

(2)set遍历

  • for in
for(item in set2){
  println(item)
}
  • iterator
var it=set2.iterator()
while(it.hasNext()){
   println(it.next())
}
  • forEach
list2.forEach{
  println(it)
}

七、Map

 (1)map的创建

  • 只读集合mapOf
  • 可变集合mutableMapOf
 //to方式
var map1=mapOf("key1" to "value1","key2" to "value2")

//Pair方式
var map3= mapOf(Pair("key1","value1"),Pair("key2","value2"))
var map4 = mutableMapOf(Pair("key1","value1"),Pair("key2","value2"))

(2)map遍历

  • for  in
for(item in map3){
   println(item.key+""+item.value)
}
  • iterator
var its = map3.iterator() 
while (its.hasNext()) { 
    val item = its.next() 
    println(item.key + "=====" + item.value)  
}
  • forEach
map3.forEach{
   key,value->println(key + "=====" + value)  
}

八、运算

(1)数值运算

  • 相等性检测   a==b   a!=b
  • 比较操作符   a<b   a>b  a<=b   a>=b
  • 检测数字是否在指定区间内,区间格式为 a..b          用法: x in a..b     a !in a..b
val x=0
val a:Int=1
val b:Int=2
    
println(a!=b)    //true
println(a>b)     //false
println(x in a..b)   //false

九、控制流

(1) if表达式

// 传统用法
var max = a 
if (a < b) max = b

// 使用 else 
var max: Int
if (a > b) {
    max = a
} else {
    max = b
}
 
// 作为表达式
val max = if (a > b) a else b


//可以把 IF 表达式的结果赋值给一个变量
val max = if (a > b) {
    print("Choose a")
    a
} else {
    print("Choose b")
    b
}

(2)when表达式(类似java的switch)    

   when(a){
       1->println("aaa")
       2->println("bbbb")
       else->{
           println("ddd")
       }
    }

    注:在when中,else同switch的defalult

  • 很多分支需要相同的方式处理,可以把多个分支条件放在一起,用逗号分隔
when(a){
       1->println("aaa")
       2,3->println("bbbb")
       else->{
           println("ddd")
       }
    }
  • 分支是任意表达式
   when(a){
       a-b->println("aaa")   //a-b这的表达式结果还是when中参数a的类型
       else->{
           println("ddd")
       }
    }
  • in或者!in
   when(a){
       in 1..10->println("aaa")
       else->{
           println("ddd")
       }
    }
  •    检测一个值是(is)或者不是(!is)一个特定类型的值
fun hasPrefix(x: Any) = when(x) {
    is String -> x.startsWith("prefix")
    else -> false
}

(3)for循环

(4)while      do...while

        do...while循环至少会执行一次

    while (x > 0) {
        println( x--)
    }
    println("----do...while 使用-----")
    var y = 5
    do {
        println(y--)
    } whi

(5)break和continue、return

        return  默认从最直接包围它的函数或者匿名函数返回

        break  终止最直接包围它的循环

        continue  继续洗一次最直接包围它的循环

(6)break和continue标签

         在Kotlin中任何表达式都可以用标签label来标记,格式:表示符@,如abc@

loop@ for (i in 1..100) {
    for (j in 1..100) {
        if (……) break@loop
    }
}

十、开发基础

(1)包声明,引入类

   代码文件开头一般为包的声明:

package com.example.ktolindemo

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

(2)注释

// 这是一个单行注释

/* 这是一个多行的
   块注释。 */

(3)常量与变量

  • var <标识符>  :<类型>=<初始值>   
  • val <标识符> : <类型> = <初始化值>   val关键字申明的常量只能赋值一次   
  • 变量和常量是没有默认值的,通过赋值就可以确定它类型,类型一旦确定这个类型就不可变;
  • 变量和常量在成员上定义时必须初始化,在方法中可以先定义,然后初始化,但是在使用前必须初始化
  • 要是变量持有null值,它必须可为null类型,需要在变量后面加上?后缀,将变量指定为可为null
//成员申明
var  num:Int=2   //指定数据类型,不能赋值为其他类型
var n=2          //根据=后面的值自动推断类型为Int,不能赋值为其他类型

fun  main(){
   var  n:Int     //局部申明,先定义,后面再初始化
   n=1
}

var num:String=null     //这是错误的
var num:String?    //申明可以null类型,对num进行操作时要注意其为null的时候

(4)NULL检查机制

fun main(str :String?){  //申明变量str可以null
   
    //对str进行操作
   情况一:  if(str==null){}         //判断为nul的情况
   情况二:  str!!.toInt()           //使用!!断言运算符 如果!!左侧表达式结果为null,也就是这里str为null,则会抛出空指针异常,程序奔溃
   情况三:   str?.toInt()            //使用?符号,如果str为null,则后面的函数不会执行,也不会报错,返回null
   情况四:val ages2 = age?.toInt() ?: -1    //使用Elvis运算符?: 因此如果age为null,那么age2的结果为-1
}
  • ?运算符在申明变量时表示变量可以为null,在使用变量时加?表示当变量为null时,运算符后面的表达式不会运行,也不会报错,变量值为null
  • !!断言运算符  如果!!左侧表达式结果为null,那么会抛出空指针异常,结束进程
  • ?:  使用Elvis运算符,如果有运算符左侧的表达式为null,那么使用运算符右的值

(5)在activity和fragment中初始化view控件,需要先申明,不能总是使用以下方式

class LoginFragment : Fragment() {
   private var statusTextView: TextView? = null

   override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        statusTextView = view.findViewById(R.id.status_text_view)
        statusTextView?.setText(R.string.auth_failed)
       }
  }

所以可以使用lateinit关键词

class LoginFragment : Fragment() {
        private lateinit var statusTextView: TextView

        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
                super.onViewCreated(view, savedInstanceState)

                statusTextView = view.findViewById(R.id.status_text_view)
                statusTextView.setText(R.string.auth_failed)
        }
    }
    

使用lateinit关键字修饰的变量,在外界不能直接判断其是否为null

class Person(name:String,age:Int) {
    lateinit var num:String

    fun numNULL():Boolean{
        return ::num.isInitialized
    }
}

fun main(){
   var person=Person("测试",11)
    if(person.numNUll){
        
    }

}

注:Byte,Short,Int,Long,Float,Double类型变量用lateinit会报错

(6)属性

        在Kotlin定义一个普通属性时,会为该属性生成一个field,gettter和setter,这个field称谓幕后字段,getter和setter在

谁后面就是谁

var(val) 属性名称:属性类型 = 属性初始值
         [<getter>]
         [<setter>]

var  name:String=""
      set(value) {}
      get

val  name:String=""
      get

 Kotlin自动生成了    setter |getter                                      产生幕后字段

重写了                    setter |getter                                      不产生幕后字段

在重写了的             setter |getter中使用了field                  产生幕后字段

  • 自定义
var num: String? = null
    get() {return  field}   //field是指当前变量
    set(value) {
        field = value
    }

//自定义访问修饰符
private val age: Int=12
        private get

 

 

十一、函数

  • 函数定义

        fun  fun_name(参数名 :参数类型;参数名:参数类型) : 返回值类型{

          有返回值时用 return ;

        }

//无返回值使用Unit,可以省略不写,函数体中也不用写return
fun fun(a:Int,b:Int):Unit{
    println(a+b);
}

fun fun(a:Int,b:Int){
    println(a+b);
}


//返回值类型为Int类型
fun funInt(a:Int,b:Int):Int{
    return a+b;
}
  • 当函数体返回单个表达式的结果时直接使用表达式,可以将return关键字替换为赋值运算符,返回结果可以显示申明,也可以由系统自动推断
fun fun1(a:Int,b:Int):Int=a+b
fun fun1(a:Int,b:Int)=a+b

fun generateAnswerString(countThreshold: Int): String = if (count > countThreshold) {
            "I have the answer"
        } else {
            "The answer eludes me"
        }
    
  • 函数参数可变,使用varargs关键字
fun <T> asList(vararg ts:T):List<T>{
    var result=ArrayList<T>()
    for(t in ts){
        result.add(t)
    }
    return result
}

val list=  asList(1,2,3);
  • lambda(匿名函数)

//定义匿名函数   参数为连个Int类型,返回值也为Int类型
val sumLambda: (Int, Int) -> Int = {x,y -> x+y}
println(sumLambda(1,2))  // 输出 3

 高级函数

一个函数将另一个函数作为参数,那么这个函数就是告高阶函数

//返回值是Int类型
//一个参数为String   另一个参数为函数(mapper为函数参数名,函数参数为String,结果为Int,函数体需要调用者写)
fun stringMapper(str: String, mapper: (String) -> Int): Int {
        // Invoke function
        return mapper(str)
    }
   
//调用
stringMapper("Android", { input ->
        input.length
})
     

十二、类

(1)类定义和用法     

//有结构体的类
class  Test{
    
}

//当类没有结构体的时候,大括号可以省略
class Test


//对象的创建
var test=Test()              

 注:对象的创建与java语法不一样,不用new  

(2)类的主构造函数

  • 一个类可以有一个主构造函数,主构造函数是类头的一部分,如果主构造函数没有注解或者可见性修饰符,constructor关键字可以省略;主构造函数中声明的参数,他们默认为类的共有字段,可以直接使用,如果不希望被别的类访问到这个变量,可以用private修饰
class  Person  constructor(name:String){
    var name1:String?=name   //方式1,直接赋值
    var name2:String?=null   //方式2,在init块中赋值

    init{  //主构造函数传的参数在init中初始化
        this.name2=name
    }
}

//省略constructor
class Person(name String){
}

//主构造函数有注解或可见性修饰符,这个constructor关键词是必修的,并且修饰符在它前面
class  Person  public  @Inject constructor(name :String){
}
  • 主构造函数没有方法体,如果有额外的代码需要在构造方法中执行,需要放到init代码块(多个init代码块,顺序执行)中执行
class  Person(var name:String) {
   init{

   }
}

(3)类的次级构造函数

  • 类的次级构造函数需要写在类体中,
  • 如果类有主构造函数,每个次构造函数需要委托给主构造函数,可以直接委托或者通过别的次构造函数间接委托
//类有主构造函数
class Person(name:String){
   constructor(name:String, parent :String):this(name){
   }
}
  • 如果类有次级构造函数,没有主构造函数(实际上系统为他创建了空参的主构造函数),一起按自定义主构造函数来处理。
//情况一:没有主构造函数
class  Person{
   constructor(name :String):this(){  
   }
}
  • 如果一个非抽象类没有声明构造函数(主构造函数或次构造函数),它会产生一个没有参数的构造函数。构造函数是public。如果你不想你的类有公共的构造函数,你就得声明一个空的主构造函数

(5)继承

        Kotlin中所有类都继承Any类,它是所有类的超类,对于没有超类型声明的类是默认超类

        Any默认提供了三个函数: equals()    hashCode()    toString()

  •   类被继承,一个类想被继承,要使用open关键词进行修饰 
open  class  Father{
}
  • 属性重写   使用override,属性必须具有兼容类型,每一个声明的属性都可以通过初始化程序或者getter方法被重写。
open  class Person {
    
    open  var  x:Int
}

class  Student : Person{

   override var  x:Int
}
  • 函数覆写,在基类中,函数默认为final修饰,不能被子类重写,如果允许子类重写该函数,需要添加关键字open修饰它,子类重写方法使用关键词override
open  class Person {
    
    open  fun  action(){
        
    }
}

class  Student : Person{

   override  fun  action(){
   }
}

(6)抽象类

abstract   class   Person{
    val TAG = this.javaClass.simpleName  // 自身的属性
    
    // 自身的函数
    fun test(){
        // exp
    }
    abstract var name : String           // 抽象属性
    abstract fun init()                  // 抽象方法
      
}

注:抽象类本身具有普通类特性,以及组成部分,抽象成员只有定义没有实现,都是被abstract修饰符修饰

       抽象类不能被直接实例化

       其抽象子类必须全部重写带abstract修饰的属性和方法

十三、接口

  (1)接口的声明和实现   interface

interface   IPerson{

     fun  cry()
}

十四、委托和代理

十五、Lambda

(1)Lambda表达式的特点

  •   Lambda表达式总是被大括号扩着
  •  其参数(如果存在)在  ----->   之前声明,参数类型可以省略
  •  函数体(如果存在)在  ------>后面

(2)语法

  • 无参数的情况  

       var/val  变量名={操作的代码}

 // 源代码
fun test(){ println("无参数") }

// lambda代码
val test = { println("无参数") }

// 调用
test()  => 结果为:无参数
  • 有参数的情况

       var/val  变量名:(参数类型,参数类型,...)  ->  返回值类型={参数1,参数2,...->操作参数的代码}
       等价于(表达式的返回值类型会根据操作的代码自推到出来)
       var/val  变量名={参数1:类型,参数2:类型,...->操作参数的代码}

// 源代码
fun test(a : Int , b : Int) : Int{
    return a + b
}

// lambda
val test : (Int , Int) -> Int = {a , b -> a + b}
// 或者
val test = {a : Int , b : Int -> a + b}

// 调用
test(3,5) => 结果为:8
  • lambda表达式作为函数中的参数的时候 

       fun  test(a:int,参数名:(参数1:类型,参数2:类型...)->表达式返回类型){
      }

    // 源代码
    fun test(a : Int , b : Int) : Int{
        return a + b
    }

    fun sum(num1 : Int , num2 : Int) : Int{
        return num1 + num2
    }

    // 调用
    test(10,sum(3,5)) // 结果为:18

    // lambda
    fun test(a : Int , b : (num1 : Int , num2 : Int) -> Int) : Int{
        return a + b.invoke(3,5)
    }

    // 调用
    test(10,{ num1: Int, num2: Int ->  num1 + num2 })  // 结果为:18

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值