Kotlin Primer · 第一章 · 基础语法与面向对象思想

简介: Kotlin Primer · 第一章 · 基础语法与面向对象思想

image.png

改不完的 Bug,写不完的矫情。公众号 小木箱成长营 现在专注移动基础平台开发 ,涵盖音视频, APM和信息安全等各个知识领域;只做全网最 Geek 的公众号,欢迎您的关注!精彩内容不容错过~

一. kotlin简介

Kotlin 拥有强大的生态,因为Kotlin是一门跑在Java虚拟机上的函数式语言,完全符合JVM的设计规范,如: 类型擦除,装箱和拆箱等等。所以也可以像Java一样支持 Android原生环境开发,服务端,甚至大前端方向。那么Kotlin和Java有什么共同点呢?

二. kotlin和java8的相同点

kotlin和java8的相同点我总结了三个,第一个是: 它们都是面向对象和函数式编程语言,第二个是: 它们都是强类型静态语言,最后一个就是它们都符合JVM设计规范

image.png

三. kotlin和java8的不同点

kotlin和java8的不同挺多的,我简单的归纳了一下:

  1. Kotlin可以用操作符简洁的判空
  2. Kotlin 不需要 findViewById
  3. Kotlin 默认给你写好 setter 和 getter方法了
  4. Kotlin 去掉了 static 关键字
  5. Kotlin 进行 自动强制类型转换
  6. Kotlin 省去了 类型推断
  7. Kotlin 不支持类型检查
  8. Kotlin 有协程支持
  9. image.png

四. kotlin 和 java 互转

4.1 kotlin 转 java

image.png

image.png

4.2 java 转 kotlin

image.png

查看Kotlin字节码

image.png

五. Kotlin 基础语法

5.1 kotlin方法

5.1.1 kotlin方法声明

Kotlin 定义方式比较简单,括号中是参数,格式: "函数名(参数名称: 参数): 返回类型",返回类型定义在括号外 如:T

    fun <T> reflectField(instance: Any?, name: String): T? {
        if (instance == null) return null
        try {
            val field = instance.javaClass.getDeclaredField(name)
            field.isAccessible = true
            return field.get(instance) as T
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }
5.1.2 kotlin方法调用

image.png

5.1.3 kotlin方法自动传参

Kotlin 可以在 构造方法或者相关函数大括号里面设置默认参数,这样传参就可以使用默认参数了,我们具体看看怎么使用的吧

image.png

第二个参数可以省略,此时会使用默认值

image.png

不省略时跟Java无异

image.png

5.1.4 kotlin named argument

named argument 的中文含义是 可以根据 参数名 进行传递参数,传参顺序不需要严格按照函数定义顺序,这样就可以避免参数误传的问题了

image.png

5.2 kotlin 变量和常量

varible(变量) 通过 var 关键字来声明,格式为 var 变量名[:类型] = [初始值]

    private var mConfig = RabbitConfig()
    lateinit var application: Application
    private var isInit = false
  • val 声明的变量是只读变量,它的引用不可更改,事实上我们依然可以更改其中引用对象的可变成员
  • const 相当于 java里面的 final,表示一旦初始化便立即被主内存看到,不能被二次赋值

当然 kotlin 也有自动拆箱和装箱将Int翻译成Java的int或Integer以提高性能

    private var Int = 8

Kotlin 会自动给属性加上 setter 和 getter 方法

class RabbitConfig(
    var enable: Boolean = true,
    var enableLog: Boolean = true,
    @Transient var uiConfig: RabbitUiConfig = RabbitUiConfig(),
    var storageConfig: RabbitStorageConfig = RabbitStorageConfig(),
    var monitorConfig: RabbitMonitorConfig = RabbitMonitorConfig(),
    var reportConfig: RabbitReportConfig = RabbitReportConfig()
)

用Show Kotlin Bytecode 翻译一下结果如下:

image.png

如果想重写 set() 或 get() 方法 可以这么做

data class RabbitConfig(
    var enable: Boolean = true,
    var enableLog: Boolean = true,
    @Transient var uiConfig: RabbitUiConfig = RabbitUiConfig(),
    var storageConfig: RabbitStorageConfig = RabbitStorageConfig(),
    var monitorConfig: RabbitMonitorConfig = RabbitMonitorConfig(),
    var reportConfig: RabbitReportConfig = RabbitReportConfig()
) {
    var age: Int = 10
        set(value) {
            println("setter $value")
            field = value
        }
    val createTimeShow: () -> String
        get() = { this.toString() }
}

5.3 kotlin null 判断

以上声明的变量皆为非空变量,即不允许为空值。如果需要声明一个变量可为空,仅需在变量类型后面加上?

val n: String?=null

声明一个变量可为空,仅需在变量类型后面加上?

// 在使用n的时候,由于n可能为null,直接使用编译器会报错
n.length  
// 正确的使用方式是,在使用前,做判空处理
// 如果变量为空,只需在变量类型后面加上?,这样就不会访问length属性了
n?.length  
// 如果确定一个可空变量不为空
// 可以加!!告诉编译器它不为空
n!!.length  

5.4 kotlin 字符串模板

val i=10
val s="i=$i"//求值结果为:“i=10”
val s="adb"
val str="$s.length is ${s.length}"//执行结果为“adb.length is 3” 

5.5 kotlin 双冒号操作符

双冒号操作符 表示把一个方法(变量)当做一个参数,传递到另一个方法(变量)中进行使用,和Java8类似

   /**
    * 把功能的名字转换为对应存储数据对象
    * */
   fun nameToInfoClass(name: String): Class<*> {
       return when (name) {
           RabbitMonitorProtocol.BLOCK.name -> RabbitBlockFrameInfo::class.java
           RabbitMonitorProtocol.APP_SPEED.name -> RabbitAppStartSpeedInfo::class.java
           RabbitMonitorProtocol.FPS.name -> RabbitFPSInfo::class.java
           RabbitMonitorProtocol.MEMORY.name -> RabbitMemoryInfo::class.java
           RabbitMonitorProtocol.EXCEPTION.name -> RabbitExceptionInfo::class.java
           RabbitMonitorProtocol.NET.name -> RabbitHttpLogInfo::class.java
           RabbitMonitorProtocol.SLOW_METHOD.name -> RabbitSlowMethodInfo::class.java
           RabbitMonitorProtocol.BLOCK_CALL.name -> RabbitBlockFrameInfo::class.java
           RabbitMonitorProtocol.GLOBAL_MONITOR.name -> RabbitAppPerformanceInfo::class.java
           RabbitMonitorProtocol.ANR.name -> RabbitAnrInfo::class.java
           else -> RabbitFPSInfo::class.java
       }
   }

5.6 kotlin 匿名函数

kotlin 正常函数

//---------------------案例一--------------------------
a(fun b(param: Int): String {
  return param.toString()
});
val d = fun b(param: Int): String {
  return param.toString()
}
//---------------------案例二--------------------------
view.setOnClickListener(new OnClickListener() {
  @Override
  void onClick(View v) {
    switchToNextPage();
  }
});

kotlin 匿名函数

//-----------------------案例一------------------------
a(fun(param: Int): String {
  return param.toString()
});
val d = fun(param: Int): String {
  return param.toString()
}
//-----------------------案例二------------------------
fun setOnClickListener(onClick: (View) -> Unit) {
  this.onClick = onClick
}
view.setOnClickListener(fun(v: View): Unit) {
  switchToNextPage()
})

5.7 kotlin lambda 语法糖

view.setOnClickListener() { v: View ->
  switchToNextPage()
}
//-----------------------------------------------
view.setOnClickListener { v: View ->
  switchToNextPage()
}
//-----------------------------------------------
mSimpleListRv.setOnClickListener {
            startActivity(Intent(this, SimpleListActivity::class.java))
        }
//-----------------------------------------------
view.setOnClickListener {
  switchToNextPage()
  it.setVisibility(GONE)
}

5.8 kotlin 表达式

5.8.1 kotlin for循环 和 范围 表达式

5.8.1.1 kotlin for循环
// -----------------------正序遍历-----------------------
for (index in 1..100){
            print(index)
        }
5.8.1.2 范围 表达式
// -----------------------倒序遍历-----------------------
for (index in 100 downTo 1){
            print(index)
        }
// -----------------------不使用1作为遍历的步长-----------------------
 for (index in 1..100 step 2){
            print(index)//会输出1..3..5......
        }
// -----------------------创建一个不包含末尾元素的区间-----------------------
for (index in 1 until 10){
            println(index)//输出1..9
        }
// -----------------------遍历一个数组/列表,想同时取出下标和元素-----------------------
val array = arrayOf("a", "b", "c")
        for ((index,e) in array.withIndex()){
            println("下标=$index----元素=$e")
        }
        // -----------------------遍历一个数组/列表,只取出下标-----------------------
        val array = arrayOf("a", "b", "c")
        for (index in array.indices){
            println("index=$index")//输出0,1,2
        }
        // -----------------------遍历取元素-----------------------
        val array = arrayOf("a", "b", "c")
        for (element in array){
            println("element=$element")//输出a,b,c
        }

5.8.2 kotlin 枚举和 when 表达式

5.8.2.1 kotlin 枚举

Kotlin中,枚举类型以类的形式存在,因此叫做枚举类,详细代码如下:

enum class Color {
    RED, GREEN, BLUE
}
//---------------使用-------------------
var color: Color = Color.BLUE
var color2 = Color.GREEN
// 比较两个枚举类型变量
var bool: Boolean = color == color2
//---------------为枚举值指定数值-------------------
enum class Direction private constructor(var value: Int) {
    NORTH(1), WEST(2), EAST(3), SOUTH(4)
}
5.8.2.2 kotlin when 表达式

when 表达式 可以支持自动转型(Auto-casting),详细代码如下:

when (view) {
     is TextView -> toast(view.text)
     is RecyclerView -> toast("Item count = ${view.adapter.itemCount}")
     is SearchView -> toast("Current query: ${view.query}")
     else -> toast("View type not supported")
}

5.8.3 kotlin 中缀表达式

kotlin 中缀表达式只有一个参数,且用infix修饰的函数,这就是我们所说的自定义运算符的中缀表达式,详细代码如下:

// 书
class Book{
   // 传入任意类型,返回一个Boolean类型的参数
    infix fun on(any: Any): Boolean{
        return true
    }
}
// 桌子
class Desk
fun main(args: Array<String>) {
    if(Book() on Desk()){
        println("书在桌上")
    }
}

5.8.3 kotlin 复合表达式

5.8.3.1 '?.'

image.png

?.表示,如果foo这时候是一个空的,则返回null,否则就返回foo.bar(),详细代码如下:

if (foo != null){
   return foo.bar()
}else{
   return null
}
5.8.3.2 '?:'

image.png

?: 作用是当数据非空时,直接返回数据,而当数据为空时,返回合并到的数据。利用该运算符,可以很容易的把可空类型转换为非空类型,详细代码如下:

 if(foo!=null)
{
    foo
}
else
{
    bar
}
foo?.length?:-1
5.8.3.3 '!!'

image.png

Kotlin 中 !! 表示非空断言运算符,详细代码如下:

if(foo!=null)
{
   foo
}else
{
   return NullPointerException
} 
5.8.3.4 'as?'

image.png

Kotlin 可以使用安全转换操作符as?,它可以在失败时返回null,详细代码如下:

foo as? type
if(foo is Stype)
{
    foo as Type
}else
{
    null
}
5.8.3.5 '?'

image.png

?表示可空类型与非空类型,Kotlin 的类型系统旨在消除来自代码空引用的危险,详细代码如下:

foo?
var foo?="abc"
foo=null
// 编译成功 foo可为空
var foo="abc"
foo=null
// 编译失败 foo不可以为空

六. Kotlin 面向对象

6.1 kotlin 继承和构造

kotlin中继承全部使用“:”,不区分extend或implement,但是有几个规则需要注意一下:

image.png

image.png

image.png

6.2 kotlin 类

6.2.2 kotlin object 类

object 全局声明的对象只有一个,所以他是天生的单例模型

image.png

6.2.2 kotlin data 类

在Kotlin里面声明一个data类需要满足以下条件:

  1. data类必须要有一个构造方法,且包含至少一个参数
  2. 该data类构造参数强制使用 val 或 var 进行声明
  3. data class 之前没有 abstract , open 或 inner 进行修饰

image.png

6.2.3 kotlin 内部类

image.png

6.3 kotlin 接口

image.png

6.4 kotlin 伴生对象

image.png

6.5 kotlin 修饰符

6.5.1 限制修饰符

  • val 翻译成字节码就是 final

image.png

private

image.png

  • internal

image.png

  • by

Kotlin 中 by 关键字用来简化实现代理 (委托) 模式,不仅可以类代理,还可以代理类属性, 监听属性变化

image.png

6.5.2 可见修饰符

嵌套类的用法: 如果要在 Kotlin 中嵌套一个类,需要在该内部类加 inner修饰

//嵌套类属于静态类和外部类没任何关系
fun main(args : Array<String>){ 
    var ot = OutClass().innerClass()
    ot.hello()
}
class OutClass{
    var name ="李武"
    //inner表示内部类
    inner class innerClass{
        var name = "张三"
        fun hello(){
            println("你好$name")
                        //内部类使用this,访问外部类的变量
            println("你好${this@OutClass.name}")  
        }
    }
}

七. 总结

本文先从kotlin概念带大家进入kotlin语言,然后说了一下kotlin和java8的异同以及相互转换方式,最后对Kotlin基础语法进行一一阐述,如: kotlin 方法和变量使用,kotlin字符串模板, lambada表达式,以及各种表达式的实际运用。好了今天的kotlin就说到这里了,如果大家对此有什么疑问欢迎到评论区留言~






















相关文章
|
14天前
|
人工智能 Dart Java
Kotlin基础语法
Kotlin基础语法
|
NoSQL MongoDB 数据库
开心档-软件开发入门之Kotlin 基础语法
前言 目录 Kotlin 基础语法 包声明 默认导入 函数定义 可变长参数函数 lambda(匿名函数) 定义常量与变量 注释 字符串模板 NULL检查机制 类型检测及自动类型转换 区间 实例测试 实例 本章将会讲解 Kotlin 基础语法 在插入文档时,MongoDB 首先检查固定集合的 size 字段,然后检查 max 字段。
|
安全 Java 编译器
开心档-Kotlin 基础语法
kotlin源文件不需要相匹配的目录和包,源文件可以放在任何文件目录。 以上例中 test() 的全名是 com.kxdang.main.test、Runoob 的全名是 com.kxdang.main.Runoob。 如果没有指定包,默认为 default 包。
开心档-Kotlin 基础语法
|
Kotlin Java Scala
带你读《Kotlin核心编程》之二:基础语法
本书不是一本简单介绍Kotlin语法应用的图书,而是一部专注于帮助读者深入理解Kotlin的设计理念,指导读者实现Kotlin高层次开发的实战型著作。书中深入介绍了Kotlin的核心语言特性、设计模式、函数式编程、异步开发等内容,并以Android和Web两个平台为背景,演示了Kotlin的实战应用。
|
Java Kotlin 编译器
Kotlin 基础语法
Kotlin 文件以 .kt 为后缀。 包声明 包的声明应处于源文件顶部: package my.demo import java.util.* // …… kotlin源文件不需要相匹配的目录和包,源文件可以放在任何文件目录。
1025 0
|
Web App开发 存储 Java
《Kotlin极简教程》第四章 Kotlin基础语法
正式上架:《Kotlin极简教程》Official on shelves: Kotlin Programming minimalist tutorial 京东JD:https://item.
901 0
|
Java Kotlin JavaScript
kotlin 语言入门指南(一)--基础语法
    基于官网的Getting Start的基础语法教程部分,一共三节,这篇是第一节,翻译如下:   基础语法   定义一个包 包的声明必须放在文件头部:   package my.demo import java.util.* // ...   不需要加上package的路径,kotlin可以自动定位package的位置。
1004 0
|
Java 索引 Kotlin
|
1天前
|
持续交付 Android开发 开发者
构建高性能微服务架构:后端开发的终极指南构建高效Android应用:Kotlin与Jetpack的完美结合
【5月更文挑战第28天】 在现代软件开发的浪潮中,微服务架构已经成为了设计灵活、可扩展且易于维护系统的重要模式。本文将深入探讨如何构建一个高性能的微服务架构,涵盖从基础概念理解到实践策略部署的全过程。我们将讨论关键的设计原则、技术选型、性能优化技巧以及安全性考虑,旨在为后端开发者提供一个全面的指南,帮助他们构建出能够适应快速变化的市场需求和技术挑战的系统。 【5月更文挑战第28天】 在移动开发的世界中,效率和性能是衡量一个应用成功与否的关键因素。本文将深入探讨如何通过结合Kotlin语言和Android Jetpack组件,来构建一个既高效又易维护的Android应用。我们将透过实际案例分析