kotllin基础
-
输入输出
输出
print 不换行
println 换行输出
kotlin里面语句不需要分号
输入
- readLine()
- 返回值是 ?的,表示可能没有想要的数据
- 使用 !! 表示肯定有
fun main{ //从终端接收字符串 var a = readLine()!! //转为Int val temp = readLine!!.toInt }
-
使用阅读器Scanner来接收
//使用阅读器Scanner来接受 //终端 文件 扫描仪 //得到一个扫描仪 val scanner = Scanner(System.`in`) //接收数据 val b = scanner.nextInt() //整数 val c = scanner.nextLine() //字符串 val d = scanner.nextFloat() //字符串
类型和变量定义
常用类型 Int Long Double Float Char Boolean Short
String Any(任意类型)
val:不可变的变量
var:可变的变量
注:变量的作用域从定义开始到对应代码块结束
//类型自动推断 val b = 10 val c = 10.0 val d = 10f val e = 10L val f = 'c' val g = "abc" val h = true //明确指定对应的数据类型 val a1:Int = 10 val f1:String = "abc" //字符串模板 println("this is $a this is $b") println("this is ${a}this is $b")
可选类型
定义变量时最好初始化,不知道如何初始化时,可以定义为可选类型
fun main() { /** 给一个变量赋初值 不知道具体值时,赋值为null 空 */ //可选类型 //有值 //没有值 val name:String? = null println("my name is $name length is ${name?.length}") // println("my name is $name length is ${name!!.length}") 确定有值才可以强制解包 }
异常处理
fun main() { try { //尝试执行这段代码 //一旦代码出现异常 停止执行try里面的代码 val a = readLine()!!.toInt() //NumberFormatException println("here1") }catch (e: Exception){ //如何出现某种类型的异常就捕获 //得到异常之后怎么处理 //打印错误信息 // println(e.message) // e.printStackTrace() } println("here2") }
when语句
fun main() { /** switch(a){ //支持int char case 1: break; case 2: break; default: break; } 1.支持所有类型 */ val a = 10 when(a){ 0 -> println("0") 10 -> println("10") 20 -> println("20") else -> { println("others") } } val name = "jack" when(name){ "jack" -> println("jack") "rose" -> println("rose") else -> println("i don't know") } //区间 when(a){ in 0..10 -> {} in 11..20 -> {} } //不在区间中 when(a){ !in 0..10 -> {} !in 11..20 -> {} else -> {} } //判断变量的类型 val temp:Any? = null when(temp){ is String -> {} is Int -> {} else -> {} } //kotlin 中无非0即真的说法 while (true){ } }
数组和循环
数组的创建
fun main() { //创建一个拥有预留空间的数组,并且给相应的初始化值 val a1: Array<Int> = Array(5,{0}) val a2: Array<Int> = Array(5){0} val a3: Array<Int> = Array(5){it} a1[0] = 1 a2[1] = 2 //创建数组时明确知道数组元素的值 val a4 = arrayOf(1,2,3,4,5) val a5:Array<String> = arrayOf("jack","rose") val a6:Array<Boolean> = arrayOf(true,false) val a7 = arrayOf(a1,a2) }
循环遍历
//遍历 //直接从数组里面取出每一个值 等待操作 //不关心索引 只关心具体的值 for (num in a4){ print("$num ") } a4.forEach { print("$it ") } a4.forEach { num -> print("$num ") } //在一个区间取值 //闭区间 for (i in 0..10){ print("$i") } //改变步调 for (i in 0..10 step 2){ println("$i ") } //开区间 for (i in 0 until 10){ print("$i ") } //关心索引位置 for(i in a4.indices){ // 0..a4.size-1 print("$i - ${a4[i]} ") } //同时获取索引和对应的值 for ((index,num) in a4.withIndex()){ print("$index - $num") } a4.forEachIndexed { index, item -> println("$index - $item") }
函数定义和调用
用函数封装代码块,方便调用
//无参 无返回值的函数 fun foo1(){ } //有参 无返回值的函数 fun foo2(a:Int,b:Int):Unit{ } //有参 有返回值的函数 fun foo3(a:Int,b:Int):Int{ return a + b } /** 类型自动推断 1.代码块里面只有一条执行语句 2.省略函数的返回值用 = 来替代 */ fun foo4(a:Int,b:Int) = a + b //无参 有返回值的函数 fun foo5():Unit{ println("hello foo5") } fun foo6() = println("hello foo6") fun foo7():Int{ println("hello f007") return 10 }
函数的引用
fun main() { val f1Ref:()->Unit = ::f1 val f2Ref:(Int,String)->Boolean = ::f2 //间接访问f1和f2 f1Ref() f2Ref(2,"jack") val funArrary = arrayOf(::f1,::f3) funArrary[0]() // funArrary[0].invoke() invoke直接调用函数 } fun f1(){ println("f1") } fun f2(a:Int,b:String):Boolean{ println("f2") return true} fun f3(){}
fun main() { buy(20,::cook) val names = arrayOf("jack","rose") } fun buy(money:Int,task:()->Unit){ println("拿着${money}去买菜") println("菜买好了") task() } fun cook(){ println("主人 我去烧饭了") } fun baby(){ println("主人 我去看小孩了") }
函数可变参数
fun main() { shouMenu("输入密码") //arrayOf("输入密码") shouMenu("张三","李四") //arrayOf("张三","李四") } //可变参数 在普通参数前加上个 vararg // 此处的menus其实也是字符数组 在传参数时不用加arraryof,更加方便 fun shouMenu(vararg menus:String) { menus.forEach { println(it) } }
函数的引用和高阶引用
package com.example.myapplication fun main() { //1.用中间变量传递函数的引用 val center:()->Unit = ::show doSomething(10,center) //2.直接引用函数 doSomething(20,::show) val a = 10 //3.直接把函数的实现传进来 //最后一个参数是函数,可以把函数移到()的外面 doSomething(30) { println("show") } } //对于函数来说,包就是它的作用域 fun show(){ println("shou") } fun doSomething(money:Int,task:()->Unit){ println("get money $money") task() }
自己用高阶函数实现forEach
fun main() { val nums = arrayOf(1,2,3,4,5) val names = arrayOf("jack","rose") // nums.forEach { // println(it) // } //自己实现forEach nums.myForEach {index,value-> } } //高阶函数:函数的参数类型是函数 fun Array<Int>.myForEach(task:(Int,Int)->Unit){ for((index,value) in this.withIndex()) task(index,value) }
- 使用高阶函数的一大好处是:可以实现数据回调
fun main() { loadData("www.baidu.com",){ data:String?,code:Int?-> if(data != null){ println("获取数据成功") } if(code != null){ println("获取数据失败") if (code == -1){ println("网址错误") } } } } //高阶函数可以实现数据回调 //-1 网址不对 -2网络不行 -3资源不存在 fun loadData(url:String,task:(String?,Int?)->Unit){ if (url.length < 2){ //模拟网址有问题 task(null,-1) return } println("正在获取数据") task("隔壁老王的靓照",null) } //高阶函数:函数的参数类型是函数 fun Array<Int>.myForEach(task:(Int,Int)->Unit){ for((index,value) in this.withIndex()) task(index,value) }
类简介
/** kotlin 一切皆对象 类:对一类事物高度抽象,不实际存在 == 属性和方法的封装 对象:某个类的实例化 实际存在 吃早餐 面向过程:起床 拿起面包 吃 喝牛奶 面向对象: 吃早餐 对象:张三 全麦面包 AD钙 类:Person Bread Milk 属性:Person:name age address Bread:brand type Milk:brand type */
类的定义和实例化
类的定义
关键字:class
Person:类名 首字母大写
对象的创建/类的实例化
val v = Person()
1.用编辑器编写一个类 文件
2.当程序运行起来,并且需要访问这个类的时候,才会将这个类加载到内存中
3.受用Person()实例化一个对象
4.在堆中申请一片内存空间,用于存储这个对象
5.不需要的时候,释放内存空间
注意:声明属性时必须初始化或抽象,如果不确定初始值,可用可选类型
当声明一个属性为var时系统完成了3件事情
1.提供了对应的set方法
2.提供了get方法
3.提供了一个变量用于存数据(backing-filed)
当声明一个属性为val时系统完成了2件事情
1.提供了get方法
2.提供了一个变量用于存数据(backing-filed)
class Person{ //属性必须初始化或抽象 var name:String = "" var name2:String? = null var age:Int = 1 } fun main() { //注意选需要的包中的类 //创建一个对象 类的实例化 val zs = Person() val ls = Person() //注意张三和李四是不同的 zs.name = "zhangsan" zs.age = 20 println("${zs.name} ${zs.age}") }
属性定义和使用
注意:
== 比较对象的值是否相同
=== 比较对象是否相同
字符串常量在内存的常量区分配内存空间
class Person{ //属性必须初始化或抽象 var name:String = "" var name2:String? = null var age:Int = 1 } fun main() { //注意选需要的包中的类 //创建一个对象 类的实例化 val zs = Person() val ls = Person() //注意张三和李四是不同的 zs.name = "zhangsan" ls.name = "zhangsan" zs.age = 20 println("${zs.name} ${zs.age}") val ww = zs val s1 = String(charArrayOf('j','a','c','k')) val s2 = String(charArrayOf('j','a','c','k')) // == 比值 if (s1 == s2){ println("the same") }else{ println("not the same") } // === 比较对象 if (s1 === s2){ println("the same") }else{ println("not the same") } if (zs.name == ls.name){ println("the same") }else{ println("not the same") } if (zs.name === ls.name){ println("the same") }else{ println("not the same") } if (zs == ww){ println("the same") }else{ println("not the same") } }
实战:生成一副牌
扑克牌
A 2 3 4 5 6 7 8 9 10 J P K
每一种牌有四种花色
A♥ A♠ A♣ A♦
//当需要将多个属性结合为一个整体的时候就需要用到类 class Poker{ var number:String = "" var color:String = "" } fun main() { val dotArrary = arrayOf("A","2","3","4","5","6","7","8","9","10","J","Q","k") val colorArrary = arrayOf("♥","♠","♣","♦") //可变数组 数组中元素数量可变 val pokerArray = arrayListOf<Poker>() dotArrary.forEach { num-> colorArrary.forEach { color-> val poke = Poker() poke.number = num poke.color = color pokerArray.add(poke) } } pokerArray.forEachIndexed { index, poker -> print("${poker.number}${poker.color} ") if ((index+1) % 4 == 0){ println() } } }
注意:不能直接调用类中的属性和方法,先要进行类的实例化,即创建 一个对象
补充:
class Car(val brand:String,val color:String){ val price:Int? = null lateinit var engine:String //延迟初始化 但使用前必须要初始化 val speed by lazy { //延迟加载 // 300 } //构建对象的时候,init方法就会被调用 init { println("init 方法被调用了 $brand") } fun start(){ engine = "v8" print("brand:$brand engine: $engine speed:$speed") } } /** * 主构造 Constructor() * 当构建参数时,需要外部传递对应的初始数据 * 次构造 * class Car(brand:String, val color:String) * brand:为临时变量,用来接收外部传递的数据,类内部的方法无法访问这个变量 * 1.将这个变量的值的属性来接收 val tt = brand * 2.在init方法中可以使用 init{} * * 属性:存数据 * 方法/函数: */ fun main() { val bz = Car("奔驰","宝马") //调用构造函数 bz.start() }
/** * 主构造 Constructor() * 当构建参数时,需要外部传递对应的初始数据 * 次构造 * class Car(brand:String, val color:String) * brand:为临时变量,用来接收外部传递的数据,类内部的方法无法访问这个变量 * 1.将这个变量的值的属性来接收 val tt = brand * 2.在init方法中可以使用 init{} * * 属性:存数据 * 方法/函数: */ fun main() { // 直接引用 // // // 间接调用 // 在定义变量时使用函数的引用来初始化 // val result:(msg:String)->Int = ::success // val code = result("成功") // println("get the code $code") // // 在定义变量时直接初始化 // { 这个函数的参数 -> //当只有一个参数时 可以省略 默认是it // 具体实现 // 如果有返回值 不要写return 最后一行就是返回值 // } val result:(String)->Int = { println(it) 200 } result("jack") //传入函数的引用 //load(::success,::failure) //耦合 低耦合高内聚 //传入具体的实现 load({ println("success: $it") 0 }) { println("success: $it") } } fun success(msg:String):Int{ println(msg) return 200 } fun failure(msg:String):Int{ println(msg) return 200 } fun load(right:(String)->Int, wrong: (String) -> Unit){ //.... val code = 200 if (code == 200){ right("成功的数据") }else{ wrong("错误的数据") } }
数组和对象的关系
package com.example.kotlinbasics.day4_class // val names = arrayListOf<String>("jack","rose") // val name = names[0] // names.remove(name) // println(("my name is $name")) /** class Person{ val age:Int // 重写get方法 // get() = 20 //明确知道返回值是什么 get() { println("开始查询数据") println("查询到数据了") return 20 } //lateinit只能修饰var 不能修饰val lateinit var name:String 懒加载 1.节省内存空间 2.只执行一次 -> 创建单例对象 3.只有val类型变量能使用懒加载 class Person{ val name:String by lazy{ "jack" } } 构造函数 当对象被创建时需要调用的函数 Person() 当创建时不需要任何函数,那么(默认/主)构建函数可以省略 什么情况下需要写构建函数 不能省略 1.创建对象时需要提供默认的属性 2.有关键字修饰构建函数 次构造函数 1.可以有多个次构造函数 2.此构造函数必须调用主构造函数(有主构造函数) 3.声明在类的内部,使用construtor构建一个函数 构建对象的顺序 子类 -> 父类1 -> 父类2 -> ... ->Any 创建原始对象 完整对象 <- 赋值(修饰)<- 赋值(修饰)<- 赋值(修饰)<- Any:所有类的父类 Person() -> Person 构造函数 -> 父类构造函数 -> Any */ class Person1 constructor(var name:String, var age:Int){ var address = "" constructor(address:String,name:String,age: Int) : this(name,age){ } var score = 0f fun show(){ println("$name $age") } } fun main() { }
属性getter和setter方法
重写get方法
class Person{ val age:Int //重写get方法 //get() = 20 //明确知道返回值是什么 get() { // println("开始查询数据库") println("查询到数据了") return 20 } } fun main(){ val p = Person() println(p.age) }
重写set方法
class Person{ var height:Float = 0f var age:Int = 0 //重写get和set后 可以做一些额外的事情 //实际上是由field存值 set(value) { if (value == 1){ height = 50f } field = value } } fun main(){ val p = Person() p.age = 1 }
lateinit延迟加载
class Person{ //若到某个时刻才能给一个值 可用延迟加载 //lateinit只能修饰var 不可修饰val lateinit var name:String } fun main() { val p = Person() p.name = "jack" val l = p.name.length }
by lazy 懒加载
class Person{ /** 懒加载 1.节省内存空间 2.只执行一次 -> 创建单例对象 3.只有val类型变量能使用懒加载 */ val name:String by lazy { println("hello") "jack" } } fun main() { val p = Person() println(p.name) println(p.name) println(p.name) }
主构造函数
/** 构造函数 当函数被调用的时候需要调用的函数 Person() 当创建对象时不需要任何参数,那么(默认/主)构造函数可省略 什么时候需要写构造函数 1.创建对象时需要提供默认的属性 2.有关键字修饰构造函数 */ class Person constructor(var name:String, var age:Int){ //val t = "jack" var score = 0f fun show(){ println("$name $age") } } fun main() { val p = Person("jack",20 ) p.name = "jack" p.age = 0 p.score = 99f }
- readLine()
构造函数
-
主构造函数
关键字:Constructor(可省)
用法:当需要外部传入对应的初始值
eg:class Car(brand:String, val color:String)
brand:为临时变量,用来接收外部的数据,类内部的方法无法访问这个变量
1.将这个变量用属性来接收 val tt = brand
2.在init方法中可以使用(init方法在创建对象时就会被调用)
color:属性:随时随地都可以访问
注意:语调val或var时,只是临时变量,不是属性
/**
* 主构造 Constructor 当创建对象时,需要外部传递对应的初始数据
* 次构造
* class Car(brand:String, val color:String)
* brand:为临时变量,用来接收外部的数据,类内部的方法无法访问这个变量
* 1.将这个变量用属性来接收 val tt = brand
* 2.在init方法中可以使用 init{}
* color:属性 随时随地都可以访问
*
*/
//去掉val或var时 只是临时变量,不是属性
class Car(brand:String,val color:String){
val tt = brand
fun start(){
print("brand: $tt color: $color")
}
//创建用户时就会调用init方法
init {
println("init 方法被调用了 $brand")
}
}
fun main() {
val bz = Car("奔驰","黑色")
}
高阶函数实现数据回调
package com.example.kotlinbasics.day4_class
fun main() {
//直接调用
//success("")
//间接调用
//在定义变量时使用函数的引用来初始化
//val result:(String)->Int = ::success
//val code = result("成功")
//println("get the code: $code")
//在定义变量时直接初始化
//{ 这个函数的参数 -> 当只有一个参数时 可以省略 默认是it
// 具体实现
// 如果有返回值,最后一行就是返回值,不要写return
//}
val result:(String)->Int = { msg ->
println(msg)
200
}
//load(::success,::failure) //耦合 低耦合高内聚
load({
println("success: $it")
0
},{ println("failure: $it")
0
})
}
fun downloadSuccess(){
}
fun success(msg:String):Int{
println(msg)
return 200
}
fun failure(msg: String):Int{
println(msg)
return 200
}
fun load(right:(String)->Int,wrong:(String)->Int){
//...
val code = 200
if(code == 200){
right("成功的数据")
}else{
wrong("地址不正确")
}
}
高阶函数作为属性使用
可将高阶函数当作属性使用,扩大作用域
全局变量与局部变量同名,优先调用局部变量 可添加 this. 调用全局变量
//不为null才会调用
callback?.let {
it()
}
扩展
作用:在原有的基础上添加新的属性或者函数
1.直接在类里面添加方法或属性(有源代码)
2.如果时封装好的类/系统默认提供的类(没法更改) -> 可以使用拓展方法或属性
语法:fun 类名.方法名(){
}
var Person.age:Int
set(value) {
println(value)
}
get(){
return 20
}
注意:拓展属性不能存值 没有提供field属性
set和get方法: set:有了这个值,你要干什么
get:怎么给我这个值
package com.example.kotlinbasics.day5_ext
/**
* 扩展Extension:在原有的基础上添加新的属性或者函数
* 1.直接在类里面添加方法或属性(有源代码)
* 2.如果是封装好的类/系统默认提供的类 (没法更改)
*/
class Person{
val name = "jack"
fun test(){
println("test")
}
}
//扩展属性不能存值 没有提供field属性
var Person.age:Int
set(value) {
//有了这个值 你需要干什么
println(value)
}
get(){
//怎么给我这个值
return 20
}
//给Person类添加了一个新的方法 eat
fun Person.eat(){
println("eating...")
test()
}
fun Any.show(){
println(this)
}
fun main() {
val zs = Person()
zs.eat()
val address = "西大"
address.show()
2.show()
zs.show()
2.4f.show()
//let其实就是一个扩展函数
3.let{}
"jack".let { }
/**
* T.let() 给T类型添加的扩展函数 let
* block:(T) -> R 接收一个参数,参数类型是函数
*/
// public inline fun <T, R> T.let(block: (T) -> R): R {
// contract {
// callsInPlace(block, InvocationKind.EXACTLY_ONCE)
// }
// return block(this)
// }
}
继承
package com.example.kotlinbasics.day5_ext
/**
封装 继承 多态
java kotlin: 单继承
默认所有的类都是final 需要使用open才能被继承
子类如果需要重写(重新实现)父类的方法
需要使用override修饰子类重写的方法
父类的方法必须使用open修饰 才能被子类重写
如何封装
public 公有的(默认) 都可以使用
private 私有的 当前这个类可用 子类外部类都无法访问
protected 受保护的 子类可以继承 外部无法访问
*/
open class Father{
var money = 0
private var knowLedge = "博士"
open fun work(){
println("father work $money $knowLedge")
}
}
// :表示继承一个类
class Child:Father(){
//子类重写父类的方法
override fun work(){
println("child work $money")
}
}
fun main() {
val my = Father()
val zs = Child()
zs.money
zs.work()
}
多态
package com.example.kotlinbasics.day5_ext
open class User(var name:String){
open fun work(){
println("$name is working")
}
}
class Teacher(name: String) :User(name){
override fun work(){
//super指的是父类 super.work()
println("开始上课")
}
}
class Student(name: String) :User(name){
override fun work(){
println("开始学习")
}
}
//使用父类接收子类 但在调用时会调用对象本身的方法
fun goToSchool(user:User){
user.work()
}
fun main() {
val zs = Student("张三")
val cc = Teacher("苍苍")
goToSchool(cc)
goToSchool(zs)
}
1.如何从0到1写项目
- 找对象
- 抽类
- 梳理类与类的关系
- 类图
- 梳理类与类的关系
- 类图
- 写功能的时序图
- 写代码
- 迭代
2.阅读别人的代码
- 首先找到入口点
- 理清程序的执行顺序
- 类图 -> 把控全局
- 梳理复杂功能的时序图
使用文件保存数据
-
数据持久化
-
1.将数据保存到服务器
-
2.本地的数据库 Room
-
3.本地(硬盘)
-
文本 txt -> 字符流 -> 字符输入流/字符输出流(字符IO流)
-
二进制 image mp3 mp4 -> 字节流 -> 字节输入流/字节输出流 (字节IO流)
流 :无法一次性完成读写 多次少量读写
-
内存 -> 外部(打印机 硬盘 网络) 输出流
-
外部 -> 内存 输入流
输入输出以内存为对照物
- 字符流:Writer/Reader
- 字节流:OutputStream / InputStream
-
-
-
普通读写文件(一个一个来)
-
创建文件
File类管理文件对象
val file = File("D:","1.txt")
-
打开文件
-
写入文件
//写入数据 file.writeText("hello Android") //writeText会覆盖原有文件内容 file.appendText("I love Android") //在原有内容上追加
-
读取数据
val result = file.readText() println(result)
-
关闭文件
缓冲输入输出
-
创建文件
val file = File("D:","1.txt")
-
写入数据
- 创建BufferwdWriter对象
val bw = BufferedWriter(FileWriter("D:\\1.txt")) //可以简化为这种形式,推荐 //分步 //创建Writer对象 val fileWriter = FileWriter(file) //创建BufferedWriter需要Writer对象,此处是操作File,所以创建了一个FileWriter对象 val bufferedWriter = BufferedWriter(fileWriter)
- 写入数据
bw.write("hello jack") bw.close() //操作完毕后要关闭BufferedWriter对象,节约资源
-
读取数据
-
创建BufferReader对象
val br = BufferedReader(FileReader("D:\\1.txt"))
-
读取数据
val str = br.readText() br.close() //操作完毕后要关闭BufferReader对象 println(str)
-
package com.example.kotlinbasics.day8_file
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.File
import java.io.FileReader
import java.io.FileWriter
import java.io.Writer
/**
* 数据持久化
* 1.将数据保存到服务器
* 2.本地的数据库 Room
* 3.文件(硬盘)
* 文本 txt -> 字符流 -> 字符输入流/字符输出流(字符IO流)
* 二进制 image mp3 mp4 -> 字节流 -> 字节输入流/字节输出流(字节IO流)
*
* 流:无法一次性操作 多次少量读写
* 字符流:Writer/Reader
* 字节流:OutputStream/InputStream
*
* 内存 -> 外部(打印机 硬盘 网络) 输出流
* 外部 -> 内存(变量) 输入流
*
*
* 创建文件
* 打开数据
* 写入数据
* 读取数据
* 关闭文件
*
* File类管理文件操作
*
* 缓冲输入输出流
* BufferedWriter/BufferedReader
*
*
*
*
*/
fun main() {
//objectSaveFileOpt()
//objectReadFileOpt1()
//objectsSave()
objectsRead()
}
//文件基本操作
fun fileOpt1(){
//创建一个文件对象来存取数据
//val file = File("D:\\Users\\wuliner\\Desktop","1.txt")
//写入数据
//file.appendText("I love Android")
//读取数据
//val result = file.readText()
//println(result)
}
//缓冲输入输出操作
fun bufferFileOpt1(){
// val file = File("D:\\Users\\wuliner\\Desktop","1.txt")
// val fileWriter = FileWriter(file)
// val bufferedWriter = BufferedWriter(fileWriter)
//
// val bw = BufferedWriter(FileWriter("D:\\Users\\wuliner\\Desktop\\1.txt"))
// bw.write("Hello Jack")
// bw.close()
val br = BufferedReader(FileReader("D:\\Users\\wuliner\\Desktop\\1.txt"))
val str = br.readText()
br.close()
println(str)
}
class Car(val brand:String,val color:String)
//将一个对象写入文件
/**
* Gson开源库
* 字符串 -> 对象 fromJson
* 对象 -> 字符串 toJson
*/
fun objectSaveFileOpt(){
val car = Car("奔驰","黑色")
//创建FGeson对象
val gson = Gson()
//将对象转化为Json格式的字符串
val jsonString = gson.toJson(car)
//创建文件对象
val file = File("D:\\Users\\wuliner\\Desktop","1.txt")
//将字符串写入文件中
file.writeText(jsonString)
}
fun objectReadFileOpt1(){
//创建文件对象
val file = File("D:\\Users\\wuliner\\Desktop","1.txt")
//读取数据
val string = file.readText()
//创建Gson对象
val gson = Gson()
//将Json格式的字符串转化为对象
val car = gson.fromJson(string,Car::class.java)
println("${car.brand} ${car.color}")
}
fun objectsSave(){
val cars = listOf(
Car("奔驰","黑色"),
Car("宝马","白色"),
Car("保时捷","棕色")
)
//创建gson对象
val gson = Gson()
//将list集合转换为字符串
val jsonString = gson.toJson(cars)
//创建文件对象
val file = File("D:\\Users\\wuliner\\Desktop","1.txt")
//写入数据
file.writeText(jsonString)
}
fun objectsRead(){
//创建文件对象
val file = File("D:\\Users\\wuliner\\Desktop","1.txt")
//读取字符串
val jsonString = file.readText()
//创建gson对象
val gson = Gson()
//将json字符串转化为集合对象
val objectToken = object : TypeToken<List<Car>>(){}
val cars = gson.fromJson<List<Car>>(jsonString,objectToken.type)
cars.forEach{
println("${it.brand} ${it.color}")
}
}
collection
package com.example.kotlinbasics.day10_collection
/**
* 联系人列表
* 陈珊珊 -> chenshanshan
* 陈小红 -> CXH
* A
* B
* C
* 陈珊珊 CSS
* 陈小红 CXH
*
* D
*
* 数据的存储结构
* 小组的存储形式:映射关系 C -> 一组好友
* 数组(好友:name title alphaString )
* 通讯录:数组(每组数据)
* Collection: 接口
* size isEmpty contains iterator toArray
* add remove containsAll addAll removeAll
* clear equals
* List: 接口
* replaceAll sort
* get set
* indexOf lastIndexOf
* subList
* ArrayList: 普通类 实现类
* 如何创建 - 构造方法(Java 方法名和类名相同,Constructor)
* ArrayList(size)
* ArrayList()
* ArrayList(Collection)
*
* Kotlin: List
* 是Kotlin的封装
* 不可变 没有add remove replace
* ListOf()
* emptyList()
*
* Kotlin:MutableList -> List
* 可以增删改 add remove clear
* mutableListOf()
*
* Kotlin:ArrayList -> MutableList
* arrayList()
*
*
*/
fun main() {
// ArrayList -> AbstractList -> AbstractCollection -> Collection -> Iterable
// -> List -> Collection -> Iterable
val nums = arrayListOf(1,2,3,4,5,6,7,8,9,10)
val temps = arrayListOf<Int>()
for (num in nums){
if (num > 5){
temps.add(num)
}
}
val results = nums.filter { it % 2 == 0 }
nums.sortDescending()
val doubleNums = nums.map {
if(it % 2 == 0){
it*10
}else{
it
}
}
println(doubleNums)
//println(results)
// fun <T>ArrayList<T>.myFilter(predicate:(T)->Boolean):List<T>{
// this.forEach{
// val tempList = arrayListOf<T>()
// val result = predicate(it)
// if (result){
// tempList.add(it)
// }
// }
//
// }
fun<T,R> Iterable<T>.myMap(call:(T) -> R):List<R>{
val container = arrayListOf<R>()
this.forEach{
val result = call(it)
container.add(result)
}
return container
}
}
高阶函数
- 常用kotlin扩展函数:let also apply with use
let与also区别
相同点:参数是普通的函数
-
also返回值还是原来的对象
-
let返回值是处理后的结果
apply和with区别
相同点:参数是都是对应类型的扩展函数 ,可以直接在类的内部进行操作
-
apply返回值还是对象本身
-
with返回值是处理后的结果
use:使用use对文件进行操作 内部有try和catch处理异常 操作完成后会自动关闭文件
package com.example.kotlinbasics.day10_collection
import java.io.BufferedWriter
import java.io.FileWriter
class School{
var name:String = ""
var address:String = ""
var level:Int = 211
fun show():Int{
return 0
}
fun test(){}
}
//.also apply use let run with
fun main(){
val xd = School()
xd.name = "xida"
println(xd.name)
//使用also可以使代码更简洁
val xd1 = School().also {//also的返回值是对象本身
it.name = "xida"
println(it.name)
}
//没名字的对象称为匿名对象
//调用后立刻执行also中代码 做了一些事还同时想做其他事
School().show().also {}
// apply 可以直接在对象内部进行操作 也可调用外部 可以创建对象后立刻对属性赋值或调用方法
val xs = School().apply {//apply的返回值是对象本身
name = "jack"
address = "荣昌"
show()
test()
}
School().myApply {
}
//use package com.example.kotlinbasics.day10_collection
import java.io.BufferedWriter
import java.io.FileWriter
class School{
var name:String = ""
var address:String = ""
var level:Int = 211
fun show():Int{
return 0
}
fun test(){}
}
//.also apply use let run with
fun main(){
val xd = School()
xd.name = "xida"
println(xd.name)
//使用also可以使代码更简洁
val xd1 = School().also {//also的返回值是对象本身
it.name = "xida"
println(it.name)
}
//没名字的对象称为匿名对象
//调用后立刻执行also中代码 做了一些事还同时想做其他事
School().show().also {}
// apply 可以直接在对象内部进行操作 也可调用外部 可以创建对象后立刻对属性赋值或调用方法
val xs = School().apply {//apply的返回值是对象本身
name = "jack"
address = "荣昌"
show()
test()
}
School().myApply {
}
//use 使用use对文件进行操作 内部有try和catch处理异常 操作完成后会自动关闭文件
val bw = BufferedWriter(FileWriter("")).use {
}
//let
//let返回值 是let代码块的返回值
val temp = School().let {
20
}
//with with的返回值是代码块的返回值
with(School()) {
}
}
//自己实现also
//注意传入的是普通函数
fun<T> T.myAlso(call:(T)->Unit):T{
call(this)
return this //also的返回值就是对象本身
}
//自己实现apply
//注意传入的参数是对象的扩展函数 就能进入对象的内部
fun<T> T.myApply(call:T.() -> Unit):T{
this.call()
return this //apply的返回值就是对象本身
}
val bw = BufferedWriter(FileWriter("")).use {
}
//let
//let返回值 是let代码块的返回值
val temp = School().let {
20
}
//with with的返回值是代码块的返回值
with(School()) {
}
}
//自己实现also
//注意传入的是普通函数
fun<T> T.myAlso(call:(T)->Unit):T{
call(this)
return this //also的返回值就是对象本身
}
//自己实现apply
//注意传入的参数是对象的扩展函数 就能进入对象的内部
fun<T> T.myApply(call:T.() -> Unit):T{
this.call()
return this //apply的返回值就是对象本身
}
map映射关系
package com.example.kotlinbasics.day10_collection
import java.util.LinkedList
/*
Set与List区别?
Set 集合 无序 唯一 不可重复
List 有序 可以重复
*/
fun main() {
/**
* Map
* 普通好友 -> 普通好友列表
* String -> List<Friend>
* key键 -> value值
* 唯一 不唯一
*/
//ArrayList MutableList List
//HashMap与MutableMap的区别: HashMap用哈希表存值
//HashMap -> MutableMap -> Map
//大量删减数据时候适合使用链表 不适合大量查询
//大量查询 -> ArrayList
//大量增加和删除 -> linkedList
// LinkedList
// LinkedHashMap
val studentMap:HashMap<String,String> = hashMapOf(
Pair("班长","老王"),
Pair("好孩子","老王")
)
//得到所有的键 studentMap.keys
studentMap.keys.forEach{key->
studentMap[key].also {
println("$key - $it")
}
}
//得到所有的值 studentMap.values
studentMap.values
//得到所有的键值对 studentMap.entries
studentMap.entries.forEach{
println("${it.key}-${it.value}")
}
val studentMap2:Map<String,String> = hashMapOf()
}
密封类
package com.example.kotlinbasics.day12_class
/**
* 数据类
* 密封类 Sealed Class
* 外部无法继承 同一个包内可以继承
*/
sealed class NetworkResult {
class Success(val data: String) : NetworkResult()
class Failure(val errorMsg: String) : NetworkResult()
}
fun main() {
val result: NetworkResult = loadData()
when (result) {
is NetworkResult.Success -> {
//val ss = result as NetworkResult.Success
println(result.data)
}
is NetworkResult.Failure -> {
println(result.errorMsg)
}
}
}
fun loadData(): NetworkResult {
//......
//return NetworkResult.Success("结果")
return NetworkResult.Failure("地址不正确")
}
sealed class Animal(val name: String, val voice: String)
class Cat(name: String, voice: String) : Animal(name, voice) {
fun cry() {
println("$name $voice")
}
}
class Dog(name: String, voice: String) : Animal(name, voice) {
fun cry() {
println("$name $voice")
}
}
sealed class A
object B : A()
object C : A()
抽象类
package com.example.kotlinbasics.day12_class
/**
* 抽象类
* 类:拥有类的功能
* 抽象:不能创建对象(统筹规划:某些情况下不做具体的事情,子类来做)
* 为什么要抽象类
* 制定功能模板 -> 子类按照这个模板去做事儿
*
*/
abstract class LoginView{
abstract fun getUserInfo():String
abstract fun checkInfo(str: String):Boolean
abstract fun login(info:String):Boolean
abstract fun startMainView()
abstract fun loginFailure(err:String)
//启动页面
fun startView(){
//获取用户信息
val phoneNumber = getUserInfo()
//验证用户是否正确
if (checkInfo(phoneNumber)){
println("验证成功")
}else{
println("信息格式不正确")
}
//服务器段实现登录校验
if (login(phoneNumber)){
//启动主页面
startMainView()
}else{
//登录失败
loginFailure("用户不存在 ")
}
}
}
class MeituanLoginView: LoginView() {
override fun getUserInfo(): String {
return "18098908987"
}
override fun checkInfo(str: String): Boolean {
return str.length == 11
}
override fun login(info: String): Boolean {
println("登录美团服务器...")
return true
}
override fun startMainView() {
println("启动美团主页面")
}
override fun loginFailure(err: String) {
println("重新进入登录页面")
}
}
abstract class Person(){
abstract val name:String
abstract fun eat()
abstract fun dress()
abstract fun action()
fun live(){
eat()
dress()
action()
}
}
class Xiaowang :Person(){
override var name:String
get() = "jack"
set(value) {}
override fun eat() {
TODO("Not yet implemented")
}
override fun dress() {
TODO("Not yet implemented")
}
override fun action() {
TODO("Not yet implemented")
}
}
fun main() {
MeituanLoginView().startView()
}
接口
/**
* 接口的作用:统一接口
* 在一个类中植入已知方法
* 数据回调 A -> B
* 投影仪 -> HDMI接口 ——> 电脑
* 品牌很多
*/
interface HDMIOutputInterface{
//接口中的方法如没有实现 则默认是抽象方法
fun outputData(data:String)
}
class Projector:HDMIOutputInterface{
val brand = "索尼"
override fun outputData(data: String) {
println("我是${brand} 接收到数据:$data")
}
}
class Computer{
fun enter(){
val projector:HDMIOutputInterface = Projector()
projector.outputData("画面 ")
}
}
fun main() {
Computer().enter()
}
设计模式
MVC设计模式(安卓默认)
-
M :Model: 数据业务
把数据相关处理的用一个类封装,要用时直接访问这个类就行了
-
V :View : layout布局文件 :按钮 文本 图片
-
C :Controller: Activity 控制View和Model之间数据传递
好处:分离 复用性强
弊端:循环引用 ,可能出现无法释放对象 ——> 弱引用 或 变成局部变量,降低作用域
MVP设计模式
View将数据传递给Presenter,在Presenter中通过调用Model处理数据,再通过定义好的接口,将数据传递给View
-
M :Model 专门处理数据
-
V : View Activity
-
P : Presenter 处Model和View的数据交互 通常需要一个接口来定义一些方法
VIew -> (interface)Present -> Model
灵活,使Activity更简洁,一个界面对应一个接口,文件较大,结构复杂
匿名类
语法:object: 类名/接口 {
}
当需要一个类的子类或抽象类或接口的实现类
-
匿名类/对象 -> ,创建的对象只需要使用一次
-
普通类 -> 有名字,这给类会被多次使用
注:构建子类时会先构建父类
//用一个类实现OnClickListener接口
//这个类会被多次使用
test(Button())
//没有创建一个类继承于这个接口
//匿名类/对象
//只需要使用一次
test(object: OnClickListener{
override fun onClick(obj: Any) {
println("按钮被点击了")
}
})
Lambda表达式
Java中,如果参数里面时接口类型,且接口类型里面只有一个方法,满足了lambda表达式
public class MyTestLmabda {
public static void main(String[] args) {
test(obj -> {
//具体的实现
})
}
}
public static void test(BtnClick l) {
}