Kotlin手记(一):基础大杂烩

Kotlin简介

2011年7月,JetBrains推出Kotlin项目,这是一个面向JVM的新语言

2012年2月,JetBrains以Apache 2许可证开源此项目。

2016年2月15日,Kotlin v1.0发布,这被认为是第一个官方稳定版本。

在Google I/O 2017中,Google宣布在Android上为Kotlin提供最佳支持,取代java成为官方开发语言。

函数和变量

kotlin中的函数和变量可以直接声明在文件中

使用fun关键字声明函数

使用var关键字声明变量,可读可写变量

使用val关键字声明只读变量,不可修改,相当于java中的final

创建对象,只需调用构造器即可,不需要java中的new关键字

kotlin 复制代码
fun main(){
  var age:Int =18
}

fun doubleNumber(x:Int):Int{
  return x*2
}

声明一个数组,使用arrayOf关键字:

kt 复制代码
private val studyList = arrayOf("语文","数学","英语")

静态函数

比如工具类中常用的dp2px()

  1. 直接写在Util.kt文件中
kt 复制代码
private val displayMetrics = Resources.getSystem().displayMetrics
fun dp2px(dp:Float):Float{
  return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,displayMetrics)
}

那么在kotlin中调用的时候直接dp2px(15f)即可。在java中调用使用Utilkt.dp2px(15f),需要在文件名后边加上kt后缀

  1. 使用object关键字声明
kt 复制代码
object Util{
  private val displayMetrics = Resources.getSystem().displayMetrics
  fun dp2px(dp:Float):Float{
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,displayMetrics)
  }
}

在kotlin中调用Util.dp2px(15f),在java中调用Util.INSTANCE.dp2px(15f)

使用object关键字声明,相当于创建了一个类的单例对象

  1. 使用companion关键字 伴生对象
    比如application:
kt 复制代码
class BaseApplication : Application(){
  companion object{
   private lateinit var currentApplication: Context
   fun currentApplication():Context{
     retun currentApplication
   }
  }

  override fun onCreate(){
    super.onCreate()
    currentApplication = this
  }
}

在kotlin中调用BaseApplication.currentApplication(),然后在java中调用BaseApplication.Companion.currentApplication()

依然使用class关键字声明一个类:

kt 复制代码
class User{
  var name:String?=null
  //set,get方法要紧跟成员变量,且里边要使用field关键字
  //set,get方法默认可以不写
  set(value){
    field = value
  }
  get(){
    field
  }

  constructor(){}
  constructor(name: String?){
    this.name = name
  }
}

继承和实现接口只需要一个冒号:,不同的是继承的类需要加上一个括号()

kt 复制代码
class MainActivity:AppcompatActivity(),View.OnClickListener{
  ...
}

但是需要注意的是,如果在类中显式声明了构造器,就不能加上这个括号()

在调用父类的构造器或者本类中其他构造器都要使用:,比如

kt 复制代码
class MyView : View {
  constructor(context:Context):this(context,null){
  }

  constructor(context:Context, attr:AttributeSet?):super(context,attr){
  }
}

另外,对一个类成员的set,get方法的访问,可以直接使用.成员变量名的方式:

kt 复制代码
user.name = "xxxxxx" //进行赋值,相当于调用了setName()方法

如果是在java中去调用,不能使用user.name,只能使用其set,get方法。但是如果使用某一个成员变量,需要在kotlin中声明这个变量的时候,使用@JvmField注解

kt 复制代码
@JvmField
var name:String?=null

匿名内部类

创建一个一个匿名内部类,需要object关键字

比如:

kt 复制代码
call.enqueue(object:Callback){
  override fun onResponse(call:Call, response:Response){}
  override fun onFailure(call:Call, e:IOException)
}

另外在内部类中使用外部类的成员变量,在java中为Class.this.xx,在kotlin中要使用this@Class.xx

静态内部类

  1. 静态内部类可以直接在一个类中使用class声明一个内部类,这个类可以使用伴生对象
  2. 如果要使用普通的嵌套内部类,则需要inner class去修饰
    另外internal关键字可以去修饰类和方法,表示当前module可见,别的module不可见

接口和抽象类,枚举类

接口(interface xxx)和抽象类(abstract class xxx)的声明,与java中相同

但是枚举类不一样:

kt 复制代码
class SdutyList{
    enum class Type{
         MATH{...}
    }
}

kotlin中的类默认都是被final关键字修饰的,不能被继承,方法不能被重写,如果想要一个类可以被继承,需要使用abstract关键字修饰,方法需要使用open修饰,才可以重写。

判断语句

if 和 when:

kt 复制代码
if(code in 100..199){}  //表示code是否在100到199,双闭区间

另外使用when关键字,相当于java中的switch

kt 复制代码
when (code){//这里可以支持表达式
     in 100..199->{}
     in 200..299->{}
     else->{}
}

遍历和循环

遍历

除了常规的for遍历一个数组或者集合

kt 复制代码
//比如有一个`users`的集合
var passUsers = ArrayList<User>()
for(user in users){
     if(user.age >= 18){
        passUsers.add(user)
     }
}
可以使用kotlin提供的操作符去简化上述代码:
//使用forEach操作符
users.forEach({user:User->
    if(user.age >= 18){
        passUsers.add(user)
    }
})
//如果forEach()中接收的参数只是一个lambda表达式,可以将{}提到括号外边,且括号可以省略:
users.forEach{user:User->
    if(user.age>=18){
        passUsers.add(user)
    }
}
//另外,也可以使用类型推断,不用声明user的类型
users.forEach{user->
    if(user.age>=18){
        passUsers.add(user)
    }
}
//最后如果一个lambda表达式,只有一个参数,那么这个参数可以省略不写,而会有一个默认的隐式参数it:User
users.forEach{
    if(it.age>=18){
        passUsers.add(it)
    }
}

还有,这个例子中相当于过滤一些user,只要符合条件的user,那么可以使用filter操作符来简化:

kt 复制代码
//这里直接过滤出年龄大于等于18的用户
passUsers.add(users.filter{ it.age >= 18 })

循环

  1. 使用repeat关键字
kt 复制代码
//注意这里是一个隐式参数`it:Int`
repeat(100){
    println(it)
}
  1. for-i循环
kt 复制代码
for(i in 0..99){
   println(i)
}

集合

  1. 使用库函数listOf<>()或者mapOf<>()
  2. 使用对象
kt 复制代码
var studyList:List<Lesson> = ArrayList();
var map:Map<Int, String> = HashMap()

但是需要注意的是上面所创建的集合元素都是不可修改的,无法进行增删

所以如果需要元素可变,一般使用:

  • arrayListOf<>(),mutableListOf<>(),mutableMapOf<>(),hashMapOf<>()
  • var studyList:ArrayList<Lesson> = new ArrayList()

kotlin中的类系统

Java Kotlin
Object Any
void Unit

kotlin中基本数据类型

Kotlin基本数据类型 位宽度
Char (字符型)
Boolean (布尔类型)
Byte 8(字节型)
Short 16(短整型)
Int 32(整型)
Long 64(长整型)
Float 32(浮点型)
Double 64(双精度浮点型)

变量的可空控制

kotlin中将变量分为可空和不可空两种类型。

kt 复制代码
//这里的user是一个不可空类型,如果赋值为null,则会报错
var user:User 
//这里的user是一个可空类型,需要加一个问号?
var user:User?=null;

那么如果想要调用一个可空类型的变量,有两种方式

kt 复制代码
user!!.getName()   //表示强制调用,不管是否为null
user?.getName()   //表示安全调用,如果不为null,才调用

虽然这里可以避免空指针,但是user为null肯定是有问题的,希望在编写代码的时候早发现这些问题。

一个错误的示例:

kt 复制代码
fun a(name:String){
    ...
}
a(user?.getName()!!)
相关推荐
喵叔哟6 分钟前
重构代码中引入外部方法和引入本地扩展的区别
java·开发语言·重构
尘浮生12 分钟前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
hopetomorrow26 分钟前
学习路之PHP--使用GROUP BY 发生错误 SELECT list is not in GROUP BY clause .......... 解决
开发语言·学习·php
小牛itbull36 分钟前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress
请叫我欧皇i44 分钟前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
闲暇部落1 小时前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
GIS瞧葩菜1 小时前
局部修改3dtiles子模型的位置。
开发语言·javascript·ecmascript
chnming19871 小时前
STL关联式容器之set
开发语言·c++
熬夜学编程的小王1 小时前
【C++篇】深度解析 C++ List 容器:底层设计与实现揭秘
开发语言·数据结构·c++·stl·list
GIS 数据栈1 小时前
每日一书 《基于ArcGIS的Python编程秘笈》
开发语言·python·arcgis