fun main(){
//1.变量引用函数
val f = ::funTest;
f("函数引用",200);
//2.做为函数参数
funTest2("函数作为参数",f)
funTest2("函数作为参数",::funTest)
}
fun funTest(msg:String,code:Int):Unit{
print("msg:${msg},code:${code}")
}
fun funTest2(msg:String,onResult:(String,Int)->Unit){
println("msh:${msg}")
onResult("函数引用",200);
}
函数值作为返回值
//函数作为返回值
fun funTest3(msg:String):(String,Int)->String{
println("msg:${msg}")
//返回匿名函数
return {
name2:String,code:Int-> "xxxxxxxx"
}
}
var funTest3 = funTest3("xxx")("121", 200)
println("funTest3:${funTest3}")
Kotlin语言的可空性特点
1.kotlin在初始化的时候默认不可以为null的
2.可以使用val name String? 来申明变量是可以为null的
3.如果变量可能为null的情况下。,可以使用变量?.方法来避免空指针
Kotlin中的let使用
let可以操作本身。他内部有个it就是本身,可以用let操作符来对变量本身做一些处理判断
fun letTest(){
var name:String? = null;
//name=‘’
name = "";
var name2 = name?.let {
if(it.isBlank()){
"默认值"
}else{
it
}
}
println("name:${name2}")
}
如果xx?:"为null就会执行"
如 var name:String?="xxx"; name = null;name?:"我是null的"
自定义异常处理
//自定义异常
fun funTest5(){
try {
var name:String?=null;
//自定义异常处理
checkException(name);
val length = name!!.length;
}catch (e:Exception){
println("error:${e}")
}
}
fun checkException(name: String?) {
name?:throw MyException()
}
class MyException :RuntimeException("你的代码太垃圾了")
字符串截取 substring
//字符串截取
fun substringTest(){
val msg = "I like Kotlin!";
var indexOf = msg.indexOf("e")
var substring = msg.substring(0, indexOf)
//until 从0直到indexOf
var substring2 = msg.substring(0 until indexOf)
}
字符串分割 split
//字符串分割
fun splitTest(){
var msg = "A,B,C,D";
//类型自动转换为List<String>了
var split = msg.split(",")
//解构 c++和kotlin都有 只有四个但是用了五个会报错
var (v1,v2,v3,v4,v5) = split;
print("v5:${v5}")
}
字符串的替换replace
//字符串的替换
fun replaceTest(){
var msg = "lalalalwwwwfcfdsfsd";
//可以些正则表达式也可以字符串
var msg2 = msg.replace(Regex("[law]")){
//it.value相当于没有替换
it.value
when(it.value){
"l"->"0"
"a"->"1"
"w"->"2"
else->it.value
}
}
}
字符串的遍历
/**
* 字符串遍历
*/
fun strFor(){
var msg = "lalalalwwwwfcfdsfsd";
msg.forEach {
//默认有个it代表每一个字母
println("$it")
}
}
类型转换
/**
* 字符串转int
*/
fun strToInt(){
//toInt字符串换int
val num = "666".toInt();
//这个时候会异常。字符串double类型无法转int
val num2 = "666.66".toInt();
//为了避免这种,可以使用toIntOrNull 异常就返回null
val num3 = "666.33".toIntOrNull();
//double转int
var num4 = 6333.22.toInt();
var num5 = 6333.22.roundToInt();//四舍五入
var num6 = "0.2f".format(62.454)//保留两位小数
}
fun takeifTest(){
//takeIf 主要是判断true和false 如果为false 则返回为null
val n = 10;
var r = n.takeIf {
//结果是false返回null 为true的话返回n本身
n>6
}
println("$r")
//一般takeIf配合空合并使用
var result = n.takeIf {
n>20
}?:"n是小于20的"
println("$result")
}
fun takeUnlessTest(){
//takeUnless和takeIf是相反的
//takeUnless为true返回null,为false返回本身
//takeUnless一般配合isNullOrBlank使用
var str:String? = null;
val r = str.takeUnless {
//it
it.isNullOrBlank()
}?:"str是null的"
println("$r")
}
fun listTest(){
//使用listOf创建集合
var list:List<String> = listOf("A","B","C");
//普通方式获取值 使用下标
var s = list[0]
//使用下标获取很容易导致下标溢出导致崩溃
var s2 = list[9999]
//可以使用getOrElse(下标){匿名函数}
var s3 = list.getOrElse(999){
//下标溢出返回这个
"下标溢出了哦"
}
//还可以使用getOrNull 下标不存在则返回null
var s4 = list.getOrNull(9999)
//一般getOrNull加上空合并一起使用
var s5 = list.getOrNull(9999)?:"下标溢出了哦"
}
//可变集合
fun list2Test(){
//可变集合使用mutableListOf
var list:MutableList<String> = mutableListOf("A","B");
//添加
list.add("C")
list.add(2,"D")
//删除 根据下标
list.removeAt(1)
//删除元素
list.remove("C");
println("$list")
//可变转换成不可变
var list2 = list.toList();
//不可变转换成可变
var list3 = list2.toMutableList();
}
可变集合的mutator特性操作
1.可以使用+来添加元素
2.可以使用-来移除元素
fun mutatorTest(){
val list:MutableList<String> = mutableListOf("A","B","C")
//可以使用+添加元素
list += "C"
list += "D"
//可以使用-移除元素
list -= "A"
//移除元素可以使用removeIf来过滤,为true就会移除
list.removeIf{
//移除掉包含A的元素
it.contains("A")
}
println("$list");
}
集合的遍历
1.使用for(item in list)
2.使用forEach
3.使用forEachIndexed 带索引
//集合的遍历
fun list3(){
var list:List<String> = listOf("A","B","C","D")
//第一种遍历 in
for(item in list){
print("元素$item")
}
println()
//第二种遍历 forEach
list.forEach{
print("元素:$it")
}
//第三种 带下标
list.forEachIndexed(){
index,item-> print("索引:$index,元素:$item")
}
}
结构语法
//解构语法
fun list4(){
val list:List<String> = listOf("A","B","C")
//可以分别复制给v1 v2 v3
val (v1,v2,v3) = list;
println("$v1")
//可以使用_来忽略不接受值
val(_,_,v6) = list;
print("$v6")
}
//set和list转换
fun setToList(){
var list:List<String> = listOf("A","B","C")
//list转set 去重
var set:Set<String> = list.toSet()
//set在转list
var list2 = set.toList()
//可以使用distinct去重
list2.distinct()
}
array数组使用
//数组
fun arrayTest(){
var intArr = intArrayOf(1,2,3,4,5)
var doubleArr = doubleArrayOf(1.2,3.4,5.6)
var longArr = longArrayOf(2.33.toLong(),6.33.toLong(),5.444.toLong())
var shortArray = shortArrayOf(1,2,3,6)
var charArr = charArrayOf('a','b','c')
var floatArr = floatArrayOf(1.2f,5.6f)
var booleanArr = booleanArrayOf(false,false,true)
//可以存放对象
var objectArr = arrayOf("",2,6.55.toLong())
//array转list
var toList = intArr.toList()
//list转array
var toIntArray = toList.toIntArray()
//下标取值
intArr[0]//容易下标溢出
//使用elementAtOrElse 避免下标溢出
intArr.elementAtOrElse(0){1}
//使用elementAtOrNull来获取 下标溢出就为null
intArr.elementAtOrNull(0)
}
map的创建
1.key to value
2.使用Pair(key,value)
//map
fun mapTest(){
//map的创建
var map:Map<String,Int> = mapOf("k1" to 11,"k2" to 22);
//map的创建
var map2:Map<String,Int> = mapOf(Pair("K1",22),Pair("K2",33))
}
//可变集合
fun map3(){
val map:MutableMap<String,Int> = mutableMapOf();
map += "key1" to 12
map += Pair("key2",22)
map.put("12",55)
//2.获取的时候可以使用getOrPut 如果key不存在则会先把22放进map然后在get返回
map.getOrPut("key3"){22}
}
类的创建和get set
1.类的创建
2.自带的get和set
3.field表示的就是当前字段的本身
//类的定义
class User{
var name = "aaaa"
//默认有一个get()和set(value)方法
get()=field//默认返回 field表示的就是name本身
set(value){
field = value
}
}
fun main(){
var u = User();//创建对象
u.name = "bbbbb";//获取对象的属性
print("${u.name}")
}
//类的构造函数
// _xxx都是临时输入类型。不可以直接调用 必须要成为变量才可以使用
class Dog(_name:String,_age:Int){
//成为变量才可以使用
var name = _name
//get不可以私有化
private get()=field
val age = _age
//私有化
private get()=field
//val 是没有set方法的
// set(value){
// field = value
// }
fun info(){
//直接调用是不行的
//println("$_name")
println("$name")
}
}
类的主构造函数(直接声明使用)
1.使用 val 变量名:类型 可以直接使用
//类的构造函数
//var name:String 其实内部相当于做了val name = _name
class Cat(var name:String,val age:Int){
fun eat(){
println("name:$name,age:$age")
}
}
class Body{
var name:String? = null;
//嵌套类
//不可以直接调用外部类的成员
class Header{
var header:String = "头部";
fun printHeader(){
println("头部信息:$header")
}
}
//内部类
//可以直接调用外部类成员信息
inner class Footer{
var footer:String="底部";
fun printFooter(){
println("${name}-->底部信息$footer")
}
}
}
fun main(){
//内部类调用
Body().Footer().printFooter();
//嵌套类调用
Body.Header().printHeader();
}
data 数据类型
1.使用data修饰符修饰数据列。类是java中的havaBean,
2.普通列只是有set和get和构造方法。data类默认除了get和set,构造外、还从写了toString equals copy hashCode等方法
3.数据类不能使用abstract open selead inner等关键字
data class Result(var code:Int,var msg:String):Any()
data class Day92(var name:String,var age:Int){
init {
println("主构造函数执行")
}
constructor(name: String):this(name,20){
println("次构造函数")
}
}
fun main(){
var d = Day92("XiaoA")
var d2 = d.copy()
println("d:$d")
d2.age=30
println("d2:$d2")
println(d==d2)
}
class Day93(var name:String,var age:Int,var sex:Char) {
//注意顺序 必须是component1 从1一次顺序开始 和成员顺序一一对应
operator fun component1() = name;
operator fun component2() = age;
operator fun component3() = sex;
}
fun main(){
//解构 可以一一对应对象的属性
var (name,age,sex) = Day93("A",20,'a');
var (_,age2,_) = Day93("B",20,'a');
}
重载运算法
1.可以使用operator fun 运算符(参数):返回类型{
return xxx;
}
来重载运算符
//运算符重载
data class Day94(var num:Int){
//plus代表+运算
//可以使用operator fun Day94. 查看KT支持的所有重载运算符
operator fun plus(num: Int):Day94{
this.num +=num;
return this;
}
}
fun main(){
println(Day94(20)+52) //Day94(num=72)
}
枚举
1.使用关键字enum calss 名{
枚举值,
}
2.枚举值等于本身
//枚举
enum class Day95{
星期一,
星期二,
星期三
}
fun main(){
//枚举的值等于本身
println(Day95.星期一)
//枚举等于本身
println(Day95.星期一 is Day95) //true
}
枚举的一般用法
1.枚举的参数必须和主构造函数参数一致
//身体信息
data class BodyInfo(var header:String,var height:Int){
}
enum class Day96(var body:BodyInfo){
//枚举的主构造函数必须和枚举参数保持一致
Man(BodyInfo("男人",20)),
Woman(BodyInfo("女人",18));
fun show(){
println("头部:${this.body.header},高度:${this.body.height}")
}
fun update(body: BodyInfo){
this.body = body;
println("更新后${this.body}")
}
}
fun main(){
Day96.Man.show()
Day96.Woman.show()
Day96.Man.update(BodyInfo("xxx",50))
Day96.Woman.update(BodyInfo("xxx",60))
}
//密封类
sealed class Ui{
object show:Ui()
object hide:Ui()
class TranslateX(val x:Int):Ui()
class TranslateY(val x:Int):Ui()
}
fun main(){
var op:Ui = Ui.TranslateX(20);
when(op){
Ui.show-> println("显示组件")
Ui.hide-> println("隐藏组件")
is Ui.TranslateX-> println("偏移量x-->${op.x}")
is Ui.TranslateY-> println("偏移量y-->${op.x}")
}
}
abstract class BaseActivity{
fun onCreate(){
getLayoutId()
initView();
initData();
initXXX();
}
abstract fun getLayoutId():Int
abstract fun initView()
abstract fun initData()
abstract fun initXXX()
}
class LoginActivity :BaseActivity(){
override fun getLayoutId(): Int {
println("获取布局ID")
return 20;
}
override fun initView() {
println("初始化View")
}
override fun initData() {
println("初始化Data")
}
override fun initXXX() {
println("初始化xxx")
}
fun show(){
super.onCreate()
}
}
fun main(){
LoginActivity().show()
}
泛型类的使用
1.和java的泛型类很相似
//使用泛型类
class Day102<T>(val obj:T){
fun show(){
println("万能输出器:${obj}")
}
}
data class Teacher2(var name:String,var age:Int)
fun main(){
var t:Teacher2 = Teacher2("张三",20)
Day102(t).show()
}
泛型方法
fun <A> show(item:A):A?{
val r = item?.apply {
println(this)
item
}?:item
return r
}
泛型实战之类型转换
1.类是rxjava的map操作符
2.可以将任意类型转换成其他任意类型
class Day103<T> (var isMap:Boolean,var input:T){
fun <R> map(mapAction:(T)->R):R? = mapAction(input).takeIf { isMap }
//两种是等价的
fun <R> map2(mapAction:(T)->R): R {
return mapAction(input)
}
}
//高级一点写法
inline fun <I,R> map(input:I,mapAction: (I) -> R):R = mapAction(input)
fun main(){
var d = Day103(true,12212)
var r = d.map {
it.toString()+"5555"
}
println(r)
val r2 = map("95922323"){
it.toInt()
}
println("$r2")
}
open class C1{}
open class C2:C1(){}
class C3:C2(){}
class C4<T:C2>(cls:T):C2(){
fun show(){
println("只有C2的子类以及本身可以访问这个")
}
}
fun main(){
val c1:C1 = C1();
val c2:C2 = C2();
val c3:C3 = C3();
//泛型类型限制只有c2以及他的子类才可以调用
var c4 = C4(c1)
var c5 = C4(c2)
var c6 = C4(c3)
}
不定参数 vararg
1.使用关键字申明vararg
//不定参数
class Day105(vararg var tags:Any){
var data = tags;
fun show(){
for (item in data) println("参数:$item")
}
}
fun main(){
var d = Day105("12",12,-1)
d.show()
}
out 协变
1.修饰的泛型只可以获取,不可以修改
2.修饰后的泛型子类可以赋值给泛型的父类
3.相当于java中的? extends T
4.父类=子类
//生产者
//out修饰的泛型只能输出不能修改
interface Produce<out C>{
//这个时候就会报错。因为使用out标记的泛型不可以修改
// fun updateConsumer(consumer:C){
//
// }
//可以获取泛型
fun getConsumer():C;
}
class Produce1():Produce<Animal>{
override fun getConsumer(): Animal {
return Animal()
}
}
class Produce2():Produce<Man>{
override fun getConsumer(): Man {
return Man()
}
}
class Produce3():Produce<Woman>{
override fun getConsumer(): Woman {
return Woman()
}
}
open class Animal{
}
//为Animal的子类
class Man:Animal(){
}
//为Animal的子类
class Woman:Animal(){
}
class Day109 {
//不加out 不会报错
var p1:Produce<Animal> = Produce1();
//没有out会报错,因为 Produce2接受的泛型是Man但是使用Animal也可以。因为使用了out 相当与java中的 ? extends T
var p2:Produce<Animal> = Produce2();
//没有out会报错
var p3:Produce<Animal> = Produce3();
//泛型的默认情况下,泛型的子类对象不可以赋值给泛型的父类对象 比如Produce<Man>无法赋值给Produce<Animal>
//out 关键字可以吧泛型的自子类对象赋值给泛型的父类对象
}
interface Produce<in C>{
fun updateConsumer(consumer:C){
}
//这里就会报错 in只能修改不可以输出
fun getConsumer():C;
}
class Produce1():Produce<Animal>{
override fun getConsumer(): Animal {
return Animal()
}
}
class Produce2():Produce<Man>{
override fun getConsumer(): Man {
return Man()
}
}
class Produce3():Produce<Woman>{
override fun getConsumer(): Woman {
return Woman()
}
}
open class Animal()
//为Animal的子类
class Man:Animal()
//为Animal的子类
class Woman:Animal();
class Day109 {
//使用关键字in可以泛型的父类可以赋值给泛型的子类
var p1:Produce<Man> = Produce1();
var p2:Produce<Woman> = Produce1();
}
//随机生成三个类。如果生成的类不等于用户规定的泛型类。那么就返回默认值
///申明三个data类
data class D1(var name:String)
data class D2(var name:String)
data class D3(var name:String)
class Day110 {
//使用reified必须加上inline
inline fun <reified T> randomClass(defaultAction:()->T):T?{
val list = listOf<Any>(D1("D1"),D2("D2"),D3("D3"))
var d:Any? = list.shuffled().first()
//这里使用it is T 就必须加上reified关键字
//这里使用后T?是如果it is T为false就返回null null去转换as T 就会报错 所以使用T?
return d.takeIf { it is T } as T? ?:defaultAction()
}
}
fun main(){
val r = Day110().randomClass<D1>{
D1("默认D1")
}
println(r)
}
//扩展属性
var String.myInfo:String
get()="xxxxxxxxxxxx"
set(value) {
}
调用println("xxx".myInfo)
可空类型的扩展
//可空类型的判断
fun String?.info():String{
if(this.isNullOrBlank()){
return "默认值";
}
return this;
}
infix 终缀表式
1.可以简化代码
2.必须要结合扩展使用
3.必须传递一个参数
//终缀表示式infix
//可以简化代码
//1.结合扩展使用
//2.必须要给定传递参数
//写法"yyyy".into(555) 可以简化 "xxxxxx" into 55
infix fun <C1,C2> C1.into(c:C2):C1{
println("接受的参数${c}")
println("this:$this")
return this
}
fun main(){
val r = "xxxxxx" into 55
"yyyy".into(555)
println("r:$r")
}