首先介绍下Kotlin在项目里面集成方法,集成方式很简单,只需要按照下面操作就好
在根目录的Build文件里面添加Kotlin支持
buildscript {
ext.kotlin_version = '1.3.31' //kotlin版本号
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
// kt
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
然后在app目录的build文件添加
//这是一个Kotlin的扩展模块,可以让Activity自动关联xml布局中的View而不需要findViewById。
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'
添加lib
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
到此为止Kotlin在Java项目的集成就结束了
下面主要记录Kotlin的基本使用语法
//java main 函数
public static void main(String[] args) {
}
//Kotlin main 函数
fun main(args: Array) {
println("Hello world")//打印功能函数
}
下面解释下kotlin的main函数
- fun:声明函数的关键字
- main:函数名称
- args:args就是参数名,跟java代码中的args一样
- : 冒号,在这里就是参数名称和类型之间的间隔
- Array< String >:Array< T >,相当于java的数组(略微不同),T泛型(代表里面存什么类型数据)。而String和Java里面的String一样(略微不同),整个意思跟java中的一样,一个存放String类型的数组
基本数据类型 和Java基本一样
var a: Byte = 2
var b: Short = 2
var c: Int = 2
var d: Long = 2L //长整型由大写字母L标记
var e: Float = 2f //单精度浮点型由小写字母f或大写字符F标记
var f: Double = 2.0
数组
var int_array:Array = arrayOf(1, 2, 3)
var long_array:Array = arrayOf(1, 2, 3)
var float_array:Array = arrayOf(1.0f, 2.0f, 3.0f)
var double_array:Array = arrayOf(1.0, 2.0, 3.0)
var boolean_array:Array = arrayOf(true, false, true)
var char_array:Array = arrayOf('a', 'b', 'c')
定义局部变量
关键字 var 和 val
var 被它修饰的变量属性可读可写
val 被它修饰的变量属性可读,但是只能被赋值一次(相当于java的final)
声明变量需要在变量名称前加上上面两个关键字中的一个修饰
NULL检查机制
Kotlin的空安全设计对于声明可为空的参数,在使用时要进行空判断处理,有两种处理方式,字段后加!!像Java一样抛出空异常,另一种字段后加?可不做处理返回值为 null或配合?:做空判断处理
//类型后面加?表示可为空
var age: String? = "23"
//抛出空指针异常
val ages = age!!.toInt()
//不做处理返回 null
val ages1 = age?.toInt()
//age为空返回-1
val ages2 = age?.toInt() ?: -1
判断是否为空
if(var_nullable == null)
安全调用
kotlin号称空安全,就是有这个安全调用
var_int?.inc()
?.的意思就是:假如这个变量不是null的话就调用后面的函数(例子就是调用inc函数),否则就不调用
elvis操作符
在java中是不是有这样的三元操作符
int a = 12;
int b = a > 12 ? a : 12;
在kotlin的判空调用就有类似的elvis操作符
val a = var_int?.inc() ?: -1
当var_int不是null的时候就调用inc(),假如是null的话,就返回-1给变量a
是不是跟java很像
!!
var_int!!.inc()
这个操作符的结果就是:当你的var_int 不是null的时候就正常调用inc(),是null的时候就抛出异常(npe)
字符串模板
$ 表示一个变量名或者变量值
$varName 表示变量值
${varName.fun()} 表示变量的方法返回值:
var a = 1
// 模板中的简单名称:
val s1 = "a is $a"
a = 2
// 模板中的任意表达式:
val s2 = "${s1.replace("is", "was")}, but now is $a"
when语法,像极了java中的switch语句,
fun printChar(cr: Char) {
when (cr) {
'a' -> {
println('a')
}
'b' -> {
println('b')
}
else -> {
println("不支持打印该字符")
}
}
}
For 循环
val items = listOf("apple", "banana", "kiwi")
for (item in items) {
println("-----$item")
}
for (i in items.indices) {
println("--hhh---${items[i]}--$i")
}
for (i in 1..10) {
if (i == 3) {
// i 为 3 时跳过当前循环,继续下一次循环
continue
}
// i 为 6 时 跳出循环
if (i > 5) {
break
}
println("循环打印1到10----$i")
}
}
val items = listOf("apple", "banana", "kiwi")
for ((index, value) in items.withIndex()) {
println("TAGthe element at $index is $value")
}
Lambda 表达式实例
Lambda 表达式的简单例子:
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
区间
var nums = 1 until 100 (1 100] 前闭后开
1..100 [1 100] 闭区间
step步长 如下例 每隔2 打印一次
var nums = 1..16
for (i in nums step 2) {
println(i)
}
nums.reversed() 反转数组
//延迟初始化
确定某一个控件不会为空的时候可加上lateinit
private lateinit var refreshLayout: SmartRefreshLayout
下面这种写法和上面一样
private var refreshLayout: SmartRefreshLayout?=null
只是在使用的时候必须要refreshLayout?. 上面的这种写法就可以预防少写?.
函数定义使用关键字 fun,参数格式为:参数 : 类型
fun sum(a: Int, b: Int): Int { // Int 参数,返回值 Int
return a + b
}
fun printSum(a: Int, b: Int): Unit {
print(a + b)
}
// 如果是返回 Unit类型,则可以省略(对于public方法也是这样):
public fun printSum(a: Int, b: Int) {
print(a + b)
}
定义常量与变量
可变变量定义:var 关键字
var <标识符> : <类型> = <初始化值>
不可变变量定义:val 关键字,只能赋值一次的变量(类似Java中final修饰的变量)
val <标识符> : <类型> = <初始化值>
NULL检查机制
Kotlin的空安全设计对于声明可为空的参数,在使用时要进行空判断处理,有两种处理方式,字段后加!!像Java一样抛出空异常,另一种字段后加?可不做处理返回值为 null或配合?:做空判断处理
//类型后面加?表示可为空
var age: String? = "23"
// !!. 抛出空指针异常
val ages = age!!.toInt()
// ?. 为空不做处理返回 null
val ages1 = age?.toInt()
//age为空返回默认值-1
val ages2 = age?.toInt() ?: -1
类型检测及自动类型转换
我们可以使用 is 运算符检测一个表达式是否某类型的一个实例(类似于Java中的instanceof关键字
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// 做过类型判断以后,obj会被系统自动转换为String类型
return obj.length
}
//在这里还有一种方法,与Java中instanceof不同,使用!is
// if (obj !is String){
// // XXX
// }
// 这里的obj仍然是Any类型的引用
return null
}
比较两个数字
在 Kotlin 中,三个等号 === 表示比较对象地址,两个 == 表示比较两个值大小。
When 表达式
在 when 中,else 同 switch 的 default。如果其他分支都不满足条件将会執行 else 分支。
when 也可以用来取代 if-else if链
var x = 1
when (x) {
1 -> {
Log.w("kotlin----", "x == 1")
}
2 -> {
Log.w("kotlin----", "x == 2")
}
else -> { // 注意这个块
Log.w("kotlin----", "\"x 不是 1 ,也不是 2\"")
}
}
//when 中使用 in 运算符来判断集合内是否包含某实例
val items = setOf("apple", "banana", "kiwi")
when {
"orange" in items -> Log.w("kotlin----","juicy")
"apple" in items -> Log.w("kotlin----","apple is fine too")
}
循环
val data = ArrayList()
data.add("apple")
data.add("banana")
data.add("kiwi")
for (item in data) {
Log.w("kotlin----", "-----$item")
}
for (index in data.indices) {
Log.w("kotlin----", "-----" + array[index])
}
for ((index, item) in data.withIndex()) {
Log.w("kotlin----","the at $index is $item")
}
接口
interface testInter {
fun foo() {
print("B")
} // 带{}默认已实现
fun bar()//未实现
}
内联扩展函数之let
let扩展函数的实际上是一个作用域函数,当你需要去定义一个变量在一个特定的作用域范围内,let函数的是一个不错的选择;let函数另一个作用就是可以避免写一些判断null的操作。
object.let{
it.todo()//在函数体内使用it替代object对象去访问其公有的属性和方法
}
//另一种用途 判断object为null的操作
object?.let{//表示object不为null的条件下,才会去执行let函数体
it.todo()
}
内联函数之with
它是将某对象作为函数的参数,在函数块内可以通过 this 指代该对象。返回值为函数块的最后一行或指定return表达式。
var user = UserInfoBean()
user.nickName = "111"
val result = with(user, {
Log.w("TAG", "---my name is " + this.nickName)
1000
})
Log.w("TAG", "--->" + result)
内联扩展函数之run
适用于let,with函数任何场景。因为run函数是let,with两个函数结合体,准确来说它弥补了let函数在函数体内必须使用it参数替代对象,在run函数中可以像with函数一样可以省略,直接访问实例的公有属性和方法,另一方面它弥补了with函数传入对象判空问题,在run函数中可以像let函数一样做判空处理
var user = UserInfoBean()
user.nickName = "111"
val result = user.run {
Log.w("TAG", "--->" + "my name is $nickName")
1000
}
Log.w("TAG", "--->" + result)
--->my name is 111
--->1000
内联扩展函数之apply
从结构上来看apply函数和run函数很像,唯一不同点就是它们各自返回的值不一样,run函数是以闭包形式返回最后一行代码的值,而apply函数的返回的是传入对象的本身。
var user = UserInfoBean()
user.nickName = "111"
val result = user.apply {
Log.w("TAG", "--->" + "my name is $nickName")
1000
}
Log.w("TAG", "--->" + result)
--->my name is 111
--->com.zhenai.base.bean.UserInfoBean@60a7d7a
@JvmOverloads这个注解是用来做什么的呢?
@JvmOverloads注解的作用:在有默认参数值的方法中使用,Kotlin会暴露多个重载方法。
foo()
foo("a")
foo("aa", 1)
foo("aaa", 1, "cc")
@JvmOverloads
fun foo(a: String = "a", b: Int = 0, c: String = "c") {
println(a)
println(b)
println(c)
}
class MyLayout
@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
: RelativeLayout(context, attrs, defStyleAttr) {
/*
@JvmOverloads
constructor(context: Context, attributeSet: AttributeSet? = null, defStyleAttr: Int = 0) : super(context, attributeSet, defStyleAttr)
*/
}
------相当Java中的:是不是很方便,再也不用写那么多重载方法了。
public class MyLayout extends RelativeLayout {
public MyLayout(Context context) {
this(context, null);
}
public MyLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}