kotlin 慕课网学习笔记

数据类型

Number

Char

不能隐式转换

String

== 和 ===

字符串模板

$变量

${表达式}

转义字符

rawString

类和对象

定义一个类
class Man constructor( name: String,  age: Int) {
    init {//方法体
        println("My name is $name, and My age is $age")
    }
}
复制代码

如果只有一个构造方法,constructor可以省略

class Man ( name: String, age: Int) {
    init {
        println("My name is $name, and My age is $age")
    }

复制代码

如果没有方法,可以省略括号

class Man constructor( name: String,  age: Int) 
复制代码
new 一个对象,注意不需要new关键字
val man = Man("mr wang", 100)
复制代码

更多构造方法: Kotlin学习系列之:Kotlin的构造函数

继承
//父类
open class Person(color: String) {

    init {
        println("My color is $color")
        println("${this.javaClass.simpleName}")//打印对象的类名
    }
}
//子类
class Man(name: String, age: Int, color: String) : Person(color) {//子类的color传递给父类
    init {
        println("My name is $name, and My age is $age")
    }
}

val man = Man("mr wang", 100, "yellow")
println(man is Person)//类似java instanceof

复制代码

My color is yellow Man My name is mr wang, and My age is 100

true

空安全

String?可为空类型,后面.方法,需要先判断空,或者 加?再去.方法

String 不可空类型

fun say(): String? {
    return null
}
复制代码
 //   say()是可null类型,不可以直接.length,处理方式如下:
//    println(say().length)//会报错
复制代码
//    方式一:加?
//   如果 say()为null 则打印null,不然就打印length
    println(say()?.length)
//  如果 say()为null 则打印"---",不然就打印length,第二个?:表示当你为null是要输出的内容
    println(say()?.length ?: "---")
复制代码
//    方式二:!!
//    通知编译器我确定不会是null
    println(say()!!.length )
复制代码

智能类型转换

如果知道p是child不需要强转
// java
Parent p = new Child();
if (p instanceof Child) {
    ((Child) p).hello_in_child();
}
复制代码
//kotlin
val parent: Parent = Child()
if( parent is Child){
// hello_in_child是child的方法,因为判断了parent is Child ,所以不需要强转
   parent.hello_in_child()
}
复制代码
强转写法 as
val p = Parent()
val child: Child = p as Child
这样写会报错,因为明显p的类型是父类Parent ,p是不能转为子类的
复制代码

java.lang.ClassCastException: com.kotlin.www.kotlindemo.Parent cannot be cast to com.kotlin.www.kotlindemo.Child

at com.kotlin.www.kotlindemo.ExampleUnitTest.addition_isCorrect(ExampleUnitTest.kt:46)
复制代码

解决方法:as?

可以强转就强转,不能的话就返回null

val p = Parent()
val child: Child? = p as? Child
println(child)
复制代码

null

// 虽然位于不同包名下,但是这样会报错,提示冲突
import com.kotlin.www.kotlindemo.test.Parent 
import com.kotlin.www.kotlindemo.Parent
复制代码
//要加入as起个别名区分,以后用这个类也必须使用别名
import com.kotlin.www.kotlindemo.test.Parent as TestParent
import com.kotlin.www.kotlindemo.Parent as Parent


  val p1=TestParent()
  val p2=Parent1()
复制代码

区间

val range=1..3 //[1,3]
val range1=1 until 3//[1,3)

复制代码

遍历

for (r in range){
    println(r)
}

复制代码

判断在不在区间内 in 操作符 或者 contains

println(3 in range)
println(3 in range1)
println(range.contains(3))
println(range1.contains(3))

复制代码

true false true false

数组

i

    基本类型内置数组类型
   	val byteArray = byteArrayOf(1, 2, 3)
    val charArray = charArrayOf('a', 'b', 'c')
    val intArray: IntArray = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
    val floatArray: FloatArray = floatArrayOf(0.1f, 0.2f, 0.3f)
    val booleanArray = booleanArrayOf(true, true, true)
    val shortArray = shortArrayOf(1, 2, 3)
    val longArray = longArrayOf(1, 2, 3)
    val doubleArray = doubleArrayOf(0.1, 0.2, 0.3)
    
    通用定义方式为:
    val array: Array<Parent1> = arrayOf(Parent1(), Parent1(), Parent1())
    val array1: Array<String> = arrayOf("hello","nihao","dajiahao")
    val arrayOf:Array<Int> = arrayOf(1, 2, 3)

复制代码
val intArray: IntArray = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
// 切片
val slice = intArray.slice(1..3)

复制代码

[2, 3, 4]

程序结构

val

val定义的不可变,基本类似于java的final,要想完全一样,要加上const

函数

一般函数
fun say(): String? {
    return "djh"i
}

// 一般函数
fun sum(a: Int, b: Int) = print(a + b)
sum(1, 2)


复制代码

匿名函数
// 匿名函数
val sum1 = fun(a: Int, b: Int) = print(a + b)
sum1(1, 2)

复制代码

lambda表达式

写法
// lamda表达式
val sum2 = { a: Int, b: Int ->
    println("$a+$b=${a + b}")
    a + b
}

复制代码

lambda表达式作为参数传递
        val arrayInt = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9)

//           接收一个lambda表达式  ( (Int) -> Unit )
        arrayInt.forEach({ it: Int -> println(it) })
//          只有一个参数时候,it可以省略
        arrayInt.forEach { println(it) }
//           还可以更省略
        arrayInt.forEach(::println)

复制代码
注意事项,lambda表达式return会return整个函数
private fun xunhuan() {
    val arrayInt = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

    arrayInt.forEach {
        if (it == 3) {
            return//因为lambda是表达式,这里return 会让整个xunhuan函数返回,最后的一句话不会打印
        }
        println(it)
    }

    println("dajiahao")
}

复制代码

如何解决问题呢

private fun xunhuan() {
    val arrayInt = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

    arrayInt.forEach forEach@{
        if (it == 3) {
            return@forEach//这样写,最后的一句话会打印
        }
        println(it)
    }

    println("dajiahao")
}

复制代码

lambda表达式是有类型的

lambda表达式的简化使用方法

定义属性

构造方法写在类名字后面

属性访问控制 get set

java的get set 方法

想写kotlin的get set方法怎么办 ,默认有的get set

属性初始化

运算符

class Student(var age: Int) {
//    运算符"+"相当于plus函数,注意必须是plus名称的函数才对应+,参数个数必须是一个,其他没要求
    operator fun plus(s: Student): Student {
        return Student(age + s.age)
    }
}

        val s1 = Student(1)
        val s2 = Student(2)
        val s3 = s1 + s2
//        val s3 = s1.plus(s2)//等同于上面
        print(s3.age)//输出3

复制代码
中缀表达式

class Student(var age: Int) {
    infix fun on(i: Any):Boolean {
        return true
    }
}

复制代码
s1.on(1)
s1 on 1//上面的式子可以简写成 s1 on 1,中缀表达式多用于dsl,一般不用,因为表达不是太清楚

复制代码

分支表达式

if 表达式

每个分支的最后的值是返回值

when表达式 替代switch

when也可以是表达式,也就是可以把他赋值给变量,每个分支最后一个值就是返回值

循环

异常

异常写法

异常表达式

具名参数

变长参数

test(1,2,3,4,5,6,7,8,9,s="fds")
fun test(vararg ints:Int,s:String):Int{
    println(ints[0])
    return ints[0]
}

复制代码
展开操作符*

val arr = intArrayOf(1, 2, 3)
test(*arr, s = "fff")

复制代码

默认参数

 val arr = intArrayOf(1, 2, 3)
 test(ints = *arr, s = "fff")//由于使用了默认参数double(没传递),第一个参数会有歧义,这时候需要指定具名参数
    
 fun test(double: Double = 1.0, vararg ints: Int, s: String): Int {
        println(ints[0])
        return ints[0]
    }

复制代码

面向对象

继承

![image-20190414194650600](/Users/apple/Library/Application Support/typora-user-images/image-20190414194650600.png)

一个类必须open才能被继承

abstract抽象类和interface接口默认含有open,所以可以直接被继承

父类方法属性也必须open才能被复写,复写必须写override关键字

接口代理

package com.kotlin.www.kotlindemo.daimazai



interface Writer {
    fun write()
}

interface Driver {
    fun drive()
}

class MyWriter : Writer {
    override fun write() {
        println(" I can write")
    }
}


class MyDriver : Driver {
    override fun drive() {
        println("I can drive")
    }
}


//一般接口实现的写法
class Manager : Writer, Driver {
    override fun drive() {
        println("I can Drive")
    }

    override fun write() {
        println("I can write")
    }

}

//接口代理的写法(不要事必躬亲),不需要再次重写接口里的实现方法,而是通过构造函数传递进来一个已经实现接口的实现类对象直接使用这个对象的方法就行
class SeniorManager(private val writer: MyWriter, private val driver: MyDriver) : Writer by writer, Driver by driver

fun test_() {
//    接口代理写法
    val myWriter = MyWriter()
    val myDriver = MyDriver()
    val seniorManager = SeniorManager(myWriter, myDriver)
    seniorManager.write()
    seniorManager.drive()
// 普通实现接口
    val manager = Manager()
    manager.drive()
    manager.write()


}

复制代码

接口方法冲突

package com.kotlin.www.kotlindemo.daimazai
abstract class A {
    open fun hello(): Int = 1
}

interface B {
    fun hello(): Int = 2
}

interface C {
    fun hello(): Int = 3
}

class D(var y: Int) : A(), B, C {
    override fun hello(): Int {

        if (y > 100) {
            return super<A>.hello()//注意使用泛型指明是哪一个接口(抽象类)的方法
        } else if (y > 10) {
            return super<B>.hello()
        } else {
            return super<C>.hello()

        }
    }

}

fun test___(){
    val d = D(1000)
    val hello = d.hello()
    println(hello)
}

复制代码

接口

接口可以有实现方法

可见性

object kotlin的单例写法

他的本质如下

java调用object单例

伴生对象与静态成员

定义

java调用

在定义时候加上注解

java调用更加方便

定义了一个静态成员

java使用kotlin的静态成员

方法重载

下面一个默认参数

kotlin里,不传参代表默认为0,传递了就是传入的值

java如何调用kotlin的默认参数函数呢 必须先改造kotlin写法

java就可以不传参了

扩展成员(方法和属性)

注意:扩展方法定义在了一个Extend.kotlin文件里,不是被扩展的类String里,所以java里如何使用呢

本质是

扩展成员属性

属性代理

属性代理目的

为了让使用属性时候能做更多操作

例如file getfile读文件 setfile 写文件

外界通过访问属性,完成了很多事情

经典例子就是lazy

写代理就是实现getValue和setValue方法,看着下面的class X写就ok

lazy解析

val 只要实现get

var 实现 get set

数据类

加上data,kotlin默认干了很多事情

自己写component

dataclass当做Javabean使用的坑

如何解决呢 使用两个注解

  1. 先 引入依赖

  2. 自定义注解

3.配置自定义注解

4. 使用注解

结果

但是这是在编译期时,操作字节码实现的,所以虽然有无参构造方法,你的代码是在编译期前面写的,此时还没有无参构造方法,但是反射可以拿到

内部类

kotlin默认内部类写法是静态内部类

inner 关键字 实现非静态内部类

匿名内部类

枚举

实例可数

密封类

子类可数

高阶函数

map 几何元素转换

    val list = listOf(1, 2, 3, 4)
    println(list)//[1, 2, 3, 4]

    val list1 = list.map { it * 2 + 3 }//[1, 2, 3, 4]
    val list2 = list.map { it.toDouble() }//[1.0, 2.0, 3.0, 4.0]
    val list3 = list.map(Int::toDouble)//[1.0, 2.0, 3.0, 4.0]
复制代码

flatmap 集合打平

  //集合的集合
    val list = listOf(
        1..10,
        10..13,
        30..37
    )//[1..10, 10..13, 30..37]
    //打平
    val list1 = list.flatMap { it + 100 }
    //[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 10, 11, 12, 13, 100, 30, 31, 32, 33, 34, 35, 36, 37, 100]

//所有数字前加No.  注意不同it代表含义不同
    val list2 = list.flatMap {
        it.map {
            "No.$it"
        }
    }
//    [No.1, No.2, No.3, No.4, No.5, No.6, No.7, No.8, No.9, No.10, No.10, No.11, No.12, No.13, No.30, No.31, No.32, No.33, No.34, No.35, No.36, No.37]

复制代码

reduce 累计操作

val list = listOf(1, 2, 3, 4)
    val reduce = list.reduce { acc, i -> acc + i }//累加  10
    val reduce1 = list.reduce { acc, i -> acc * i }//累乘法   24
    
//拼接字符串
  val list = listOf("java", "kotlin", "c++")
  val ccc= list.reduce { acc, s -> acc+","+s }
  println(ccc)//java,kotlin,c++
复制代码
/**
 * 求阶乘
 */
fun jiecheng(n: Int): Int {

    return if (n == 0) {
        1
    } else {
        (1..n).reduce { acc, i -> acc * i }
    }
}

// 集合map变为阶乘,再循环打印
(0..9).map(::jiecheng).forEach(::println)

// 集合map变为阶乘,再累加集合里的元素
(0..9).map(::jiecheng).reduce { acc, i -> acc + i }
复制代码

fold 累计运算,但是可以指定初始值

(0..9).reduce { acc, i -> acc+i }//45

(0..9).fold(100) { acc, i -> acc+i }//145  (100)为指定的初始值

val c= (0..9).fold(StringBuilder("qwe")){ acc, i ->acc.append(i).append(",") }
println(c)//qwe0,1,2,3,4,5,6,7,8,9,
复制代码

foldRight 从右往左累计运算(指定初始值 )

val list = listOf("java", "kotlin", "c++")
val w=list.foldRight(StringBuilder()){
        s: String, acc: StringBuilder ->
        acc.append(s).append(",")
    }
//c++,kotlin,java,
复制代码

joinToString 连接字符串

    val list = listOf("java", "kotlin", "c++")
    val q=list.joinToString(",")//java,kotlin,c++


复制代码

filter 过滤元素

//    返回偶数(模2为0的数字)的元素
    val filter = (0..10).filter { it % 2 == 0 }
    println(filter)//[0, 2, 4, 6, 8, 10]
复制代码

filterIndexed 过滤索引+元素

//获取奇数位置的数字
    val a: IntArray = intArrayOf(9, 8, 7, 3, 7)
   val ccc= a.filterIndexed { index, i -> index % 2 == 0 }//[9,7,7]
复制代码

takeWhile 和 takeLastWhile


//  取出数组里的奇数元素,遇到不是奇数就停止
    val qwe: IntArray = intArrayOf(17, 9, 8, 19, 3, 7)
    val ok = qwe.takeWhile { it % 2 == 1 }// [17, 9] 从前往后取
    val last = qwe.takeLastWhile {it % 2 == 1   }//[19, 3, 7] 从后往前取值

复制代码

let


data class Cat constructor(var name: String, var age: Int)

fun main() {
    println(100)

//    因为 findCat()?已经非空判断了,所以后面可以直接使用
    findCat()?.let {
        print(it.name)
        print(it.age)
    }
    
//    使用了dataclass的解包操作 component1,2
    findCat()?.let { (name, age) ->
        {
            print(name)
            print(age)
        }
    }
}

fun findCat(): Cat? {
    return null
}

复制代码

apply

package objectori

data class Cat constructor(var name: String, var age: Int) {


    fun work() {

    }

    fun play() {

    }
}

fun main() {
    println(100)

//    因为 findCat()?已经非空判断了,所以后面可以直接使用
    findCat()?.let {
        print(it.name)
        print(it.age)
        it.play()//在let里可以直接用it调用方法
    }


    findCat()?.apply {
        // 在apply里可以直接调用方法,
        work()
        play()
        name
        age

    }
/
}

fun findCat(): Cat? {
    return null
}

复制代码

use with

尾递归优化

函数调用了自己后没有任何操作 关键是分辨什么是尾递归

闭包

对象携带状态


fun makeFun(): ()->Unit{

    var count =0

//    返回一个函数
    return fun(){
        count++
        println(count)
    }
}
fun main() {
    var x= makeFun()
    x()
    x()
    x()
    x()
}
//1
2
3
4
复制代码
package objectori


/**
 * start;起始步数 
 * step:每次走的步数
 * 
 */
fun makeFun(start: Int, step: Int): () -> Unit {

    var count = start

//    返回一个函数
    return fun() {
        count += step
        println(count)
    }
}

fun main() {
    var x = makeFun(100,2)
    x()
    x()
    x()
    x()
}
102
104
106
108
复制代码

函数的复合


下面是两个函数

add5:把一个值加5

multiplyBy2:把一个值乘以2

fun main() {
    val add = add5(8)
    val multi = multiplyBy2(add)

    println(add) //13
    println(multi)//26
}

//加5
val add5 = { i: Int -> i + 5 }
//乘2
val multiplyBy2 = { i: Int -> i * 2 }
复制代码


fun main() {
    val add = add5(8)
    val multi = multiplyBy2(add)

    println(add) //13
    println(multi)//26


//    val result = add5.andThen(multiplyBy2)
    val result = add5 andThen multiplyBy2
    println(result(8))


}

//加5
val add5 = { i: Int -> i + 5 }
//乘2
val multiplyBy2 = { i: Int -> i * 2 }


infix fun <P1, P2, R> Function1<P1, P2>.andThen(function: Function1<P2, R>): Function1<P1, R> {
    return fun(p1: P1): R {
        return function.invoke(this.invoke(p1))
    }
}
复制代码

科理化

偏函数

协程

参考这篇文

Kotlin1.3版本的协程

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        coroutine.setOnClickListener { click() }
    }

    private fun click() = runBlocking {
        GlobalScope.launch(Dispatchers.Main) {
            coroutine.text = GlobalScope.async(Dispatchers.IO) {
                // 比如进行了网络请求
                // 放回了请求后的结构
                return@async "main"
            }.await()
        }
    }
}
复制代码

更好的入门 www.kotlincn.net/docs/tutori…

与java交互

SAM转换 单一抽象方法 Single Abstract Method

注意:

示例一 kotlin引用java里的函数(sam转换只是默认支持java接口)

  1. 在java里定义一个addTask(参数为接口实现)
public class SamJava {
    public void addTask(Runnable runnable){

    }
}
复制代码
  1. kotlin调用这个方法

 val samJava = SamJava()

    samJava.addTask(object : Runnable {
        override fun run() {
        // do sth            
        }
    })

    samJava.addTask {
        // do sth   
    }

复制代码

示例二 kotlin引用kotlin里的函数(sam转换只是默认不支持kotlin接口)

只能这样调用

  val samKotlin = SamKotlin()
    samKotlin.addTask(object :Runnable{
        override fun run() {
        }

    })
复制代码

如果kotlin接口想使用sam的话

必须加别名

typealias Runnable = () -> Unit
复制代码

完整如下:

typealias Runnable = () -> Unit

class SamKotlin {
    fun addTask(runnable: Runnable) {

    }

}


fun test() {
    val samKotlin = SamKotlin()
    samKotlin.addTask { 
    //  do sth
    }
}
复制代码

为Runnable起了别名后, java调用加别名后的kotlin 方式如下:

        SamKotlin samKotlin=new SamKotlin();
//       为Runnable起了别名后, java调用加别名后的kotlin 
        samKotlin.addTask(new Function0<Unit>() {
            @Override
            public Unit invoke() {
                return null;
            }
        });
//        简写如下:
        samKotlin.addTask(() -> null);

    }
复制代码

正则表达式

java写法

kotlin写法

直接抄java

也可以用有kotlin自己的写法

集合框架

mapOf同理不可变

注意

java认为kotlin listOf定义的list与普通list没区别,支持调用add remove ,但是实际运行会报错

先在kotlin使用listOf定义一个list

java里使用这个list

IO 操作

Java里面

kotlin 代码

自带关闭流

简单文件读写

    File("KotlinDemo.iml").readLines().forEach(::println)

复制代码

装箱与拆箱

注解处理器

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值