Android学习笔记3 - Kotlin语法学习

Kotilin是官方推荐的第一语言,所以本章大概记录一下他和别的语言的区别和特点。

运行环境

Kotilin可以使用InterliJIDEA,是JetBrains的期间IDE来运行。或者使用try.lotilinlang.org在线运行。我比较懒还是在AS上运行就可以了。

第一次写Kotilin代码

我们还是在上一节的HelloWorld里写代码运行吧。我们在MainActivity位置,鼠标右键添加Kotilin File/Class,我们建立一个.kt的文件,我这里取名Comm.kt
在这里插入图片描述

我写入代码如下:

package com.example.helloworld
import android.util.Log
fun main(){
    println("main run");
    Log.d("first","main run");
}

增加了main函数,你会发现函数前面出现一个运行的绿色箭头,如下图
在这里插入图片描述

点击箭头就可以运行程序了
在这里插入图片描述
我们在输出窗口Run里可以看到运行结果,println输出了main run,而Log函数报错了,因为我们运行的这段Kotlin代码和Android无关。这就是在AS里单独运行Kotlin的方法,后面都按照这个来进行。

上一章和本章的代码我都加了分号,Kotilin是不用加分号的,可能C#写习惯了。

变量声明

val abc = 10	//val是不可变的的变量
var abc = 10	//var是可变变量
val abc : Int = 10	// 显示声明了变量类型

函数声明

import kotlin.math.max


fun main(){
    println("main run")
    //Log.d("first","main run")
    println("max : "+methodName(1,2))
    println("max2 : "+methodName(3,4))
}
//一般的书写
fun methodName(param1 : Int, param2 : Int) : Int
{
    return max(param1,param2)
}

//特殊的书写
fun methodName2(param1 : Int, param2 : Int) = kotlin.math.max(param1,param2)

max引用了math库,可以鼠标悬浮在max上,点击导入。

条件

	//普通用法
    if(2>1)
    {
        println(" > ")
    }
    else
    {
        println(" < ")
    }

    //if可以赋值
    var abc = if(2>1) 2 else 1
    println("abc :"+abc)

    //if赋值可以直接给函数当返回值
    println("methodName3 :"+methodName3(5,6))

	fun methodName3(param1 : Int, param2 : Int) = if(param1>param2) 2 else 1

when

这里我们还是写一个特殊的写法。

println("abc :"+methodName4("Li"))

fun methodName4(name:String) = when(name)
{
    "Liu" -> 88
    "Mao" -> 78
    "Li" -> 99
    else -> 0
}

循环

	//循环从0到10(包含10)11个
    for(i in 0..10)
    {
        println("for1:"+i)
    }

    //循环0到10,不包含10
    val count = 0 until 10  //0-9
    for(i in count)
    {
        println("for2:"+i)
    }

    //每次加2
    for(i in count step 2)
    {
        println("for3:"+i)
    }

    //降序(从10到0)11个
    for(i in 10 downTo 0)
    {
        println("for4:"+i)
    }

执行结果

for1:0
for1:1
for1:2
for1:3
for1:4
for1:5
for1:6
for1:7
for1:8
for1:9
for1:10
for2:0
for2:1
for2:2
for2:3
for2:4
for2:5
for2:6
for2:7
for2:8
for2:9
for3:0
for3:2
for3:4
for3:6
for3:8
for4:10
for4:9
for4:8
for4:7
for4:6
for4:5
for4:4
for4:3
for4:2
for4:1
for4:0


类的使用

基本使用

	class FirstRun {
    var name = ""   //必须初始化
    fun run()
    {
        println("run : "+name)
    }
}

调用缺少了new关键字,调用构造函数表示new

	val obj = FirstRun()
    obj.name = "Jason"
    obj.run()

继承

被继承的类要加open关键字,类似于val一样,继承可以传递主构造函数的参数。

package com.example.helloworld

open class FirstRun(val nm:String) 
{
    var name = ""   //必须初始化
    init //init这里是主构造函数
    {
        name = nm
    }
    open fun run()
    {
        println("run : "+name)
    }
}

//这里继承了父类,并且传入了构造函数的参数nm,注意nm不用加val。
class SecRun(val _t:Int,nm:String) : FirstRun(nm)
{
    var t = 0//必须初始化
    init
    {
        t = _t
    }
    override fun run()  //override的父类函数必须要加open关键字
    {
        super.run()
        println("run : "+name+",t:"+t)
    }
}
	val obj = SecRun(10 , "Jason")

    obj.run()

运行结果:
run : Jason
run : Jason,t:10

次构造函数

constructor

package com.example.helloworld

open class FirstRun(val nm:String)
{
    var name = ""   //必须初始化
    init //init这里是主构造函数
    {
        name = nm
    }
    open fun run()
    {
        println("run : "+name)
    }
}

//这里继承了父类,并且传入了构造函数的参数nm,注意nm不用加val。
class SecRun(val _t:Int,nm:String) : FirstRun(nm)
{
    var t = 0//必须初始化
    init //init这里是主构造函数
    {
        t = _t
        name = nm
    }
    constructor(nm:String) : this(
        0,nm
    )
    constructor() : this(
        0,""
    )
    override fun run()  //override的父类函数必须要加open关键字
    {
        println("run : "+name+",t:"+t)
    }
}

fun main(){
    val obj1 = SecRun()
    val obj2 = SecRun("Jason")
    var obj3 = SecRun(3,"Jason")
    obj1.run()
    obj2.run()
    obj3.run()
}


运行结果:
run : ,t:0
run : Jason,t:0
run : Jason,t:3
这样增加了两种次构造函数,这样就可以通过三种方式来构造函数了。

接口

class FirstRun() : Walk
{
    var name = "Jason"   //必须初始化
    fun run()
    {
        println("run : "+name)
    }
    override fun walk1() {
        println("walk1 : "+name)
    }
}


interface Walk
{
    fun walk1()
    fun walk2(){ println("walk2") } //默认实现
}

	fun main(){
    val obj1 = FirstRun()

    obj1.walk1()
    obj1.walk2()

}

接口Walk两个实现,walk2有默认实现,walk1没有,所以必须要写walk1的实现。

函数修饰符

  • public(所有类可见,默认没有写就是public)
  • private (私有本函数)
  • protected(当前类和子类)
  • internal(模块内部调用)

数据类

数据类定义很简单

data class phone(val brand:String,val price:Int)

上面定义了一个手机,有品牌和价格。

	fun main(){
    val phone1 = phone("MI13",2888)
    val phone2 = phone("MI13",2888)
    println(phone1)
    println("phone1 == phone2 ? "+(phone1 == phone2))
}

输出结果:
phone(brand=MI13, price=2888)
phone1 == phone2 ? true

单例类

一般全局只希望有一个实例化的某个类会使用单例类,其他语言需要用static 关键字定义instance来调用。Kotlin更简单。

object SingleClass
{
    fun Do(){ println("do") }
}

fun main(){
    SingleClass.Do()
}

只用添加object就可以了,看上去好像是静态的,其实Kotlin内部创建了一个单例。

拉姆达

下面是几个Kotlin的Lambda用法。

  • 集合创建法
package com.example.helloworld

import android.util.Log
import kotlin.math.max


fun main(){

    val lista = listOf(1,2,3,2,"a","b")    //创建不可变集合
    for (one in lista)
    {
        println(one)
    }
    println("------华丽的分割线-------")
    val listb = setOf(1,2,3,2,"a","b")    //创建不可变,不可重复集合
    for (one in listb)
    {
        println(one)
    }
    println("------华丽的分割线-------")
    val listc = mutableListOf(1,2,3,"a","b")    //可变集合
    listc.add("c")
    for (one in listc)
    {
        println(one)
    }
    println("------华丽的分割线-------")
    val mapa = mapOf("Mi" to 1,"Apple" to 2,3 to 3) //类似字典类型, mutableMapOf对应是可变的
    for (one in mapa)
    {
        println(one)
    }
    
}

运行结果

1
2
3
2
a
b
------华丽的分割线-------
1
2
3
a
b
------华丽的分割线-------
1
2
3
a
b
c
------华丽的分割线-------
Mi=1
Apple=2
3=3


  • 拉姆达函数用法
    { 参数1:参数类型,参数2:参数类型 -> 函数体 }
fun main(){

    val lista = listOf("Apple",  "Banana" , "Orange" ,"Pineapple")    //创建不可变集合
    val x1 = lista.maxOf() { it.length  }
    println(x1)

    val x2 = lista.filter { it.length > 5 }.map { it.uppercase() }
    println(x2)
}

结果
9
[BANANA, ORANGE, PINEAPPLE]

Java函数的使用

假设有Java接口

public interface Runnable {
	void run();
}

Kotlin调用

Thread(object : Runnable {
	override fun run() {
	println("running")
	}
}).start();

我们创建了一个Runnable接口的匿名类示例,并调用。
这个Lambda是单参数,还可以简化成:

Thread {	println("running")	}.start()

Kotlin可能会经常调用Java接口,例如常用的。

button.setOnClickListener{}

空指针检查

fun doit (firstrun :FirstRun?)
{
	if( firstrun != null)
	{
		firstrun.run()
	}
}

一般Kotlin一般不允许有空,一般变量都有默认值,如果非要传递空,需要添加问号

判空辅助工具

  • 操作符:?.
if(abc != null) abc.run()
可以写作
abc?.run()
  • 操作符:?:
val c = a?:b
//如果a不是null,c=a,否则c=b
  • 操作符:!!

var myname : String? = null
fun main(){
    myname = "Jason"
    run()
}
fun run()
{
    val str = myname!!.uppercase()
    println(str)
}

因为myname是可能为空的,如果run函数里没有!!,编译器会不让通过的,因为可能有风险某人直接调用run函数导致问题。所以!!操作符就好像你给编译器说,我保证这里没问题,绝对不会为空。这就是一个潜在的风险。

把上面的函数写成这样都是编译器不能通过的。

fun run()
{
    if(myname != null)
    {
        val str = myname.uppercase()
        println(str)
    }
}

let函数

class Walk
{
    fun run1(){}
    fun run2(){}
    fun run3(){}
}

fun main(){
    val wk = Walk()
    doWalk(wk)
}
fun doWalk(wk:Walk?)
{
    wk?.run1()
    wk?.run2()
    wk?.run3()
}


这个doWalk函数里进行了3次?.操作,相当于判断了3次是否为空,这里可以用let函数替换。

fun doWalk(wk:Walk?)
{
    wk?.let { work ->
        work.run1()
        work.run2()
        work.run3()
    }
}

小技巧

字符串

	val who : String ="Jason"
    println("hello : ${who} , byebye !")

hello : Jason , byebye !

默认参数

函数可以默认参数,甚至不用是最后几个有默认值,我们可以采用键值的放置传入函数,如下:

fun main(){
    run(p3 = 2.5f, p2 = 90)
}

fun run(p1:String = "Jason",p2:Int,p3:Float=1.7f)
{
    println(p1)
    println(p2)
    println(p3)
}

Jason
90
2.5

语法学习先到这里有个大概的了解,剩下的在工作和学习种再慢慢积累吧。

参考
《第一行代码》Android第三版

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值