新手建设网站步骤,购物网站要求,国外 创意 网站,湖畔魔豆基金会公益网站开发目录
初识 Kotlin
历史
工作原理
第一个Hello World#xff01;
Kotlin 语法
变量
基本数据类型
函数 和
选择控制#xff08;if、when#xff09;
if
when
循环语句
类和对象
创建和使用
继承
构造
主构造
次构造
接口
定义
实现
权限修饰符
数据类…目录
初识 Kotlin
历史
工作原理
第一个Hello World
Kotlin 语法
变量
基本数据类型
函数 和
选择控制if、when
if
when
循环语句
类和对象
创建和使用
继承
构造
主构造
次构造
接口
定义
实现
权限修饰符
数据类实体类和单例类
数据类
单例类
集合
List
Set
Map
Lambda 的使用
基本认识
list.maxByOrNull
list.map、list.filter、list.any、list.all
空指针检查机制
辅助判空工具
?.
?:
!!
let 函数
内嵌表达式
函数参数默认值 初识 Kotlin 历史
Kotlin由JetBrains公司开发设计2011年公布第一版2012年开源。
2016年发布1.0正式版并且JetBrains在IDEA加入对Kotlin的支持安卓自此又有新的选择。
2019年谷歌宣布Kotlin成为安卓第一开发语言安卓程序员由java转Kotlin已经迫在眉睫。 工作原理
Java 虚拟机只认识 class 文件并不关心是由什么文件编译来的 因此当我们创造一个自己的语法规则时再做一个对应的编译器就可以让我们的语言跑在 Java 的虚拟机上。Kotlin 就是这个原理运行前会先编译成 class在给 Java 虚拟机运行。 第一个Hello World
创建项目只需要注意以下几点即可这里使用 Gradle 构建项目 修改配置文件中的 JDK 版本这里我使用的是 JDK8 如下代码Kotlin 以 main 方法作为程序的入口
fun main() {println(hello world!)
}运行结果如下 接下来进入语法的学习 Kotlin 语法 变量
var 表示可变变量
val 表示不可变变量
a由于 Kotlin 存在类型推导机制因此不用声明具体的数据类型。当然也可以手动指定数据类型如下代码 var a 1 //可变val b 2 //不可变var c: Int 1 //指定数据类型(Kotlin有类型推导机制这里可以不用指明)他们的本质区别就类似 Java 中如下代码 private static int a 1;private static final int b 2;private static int c 3; Kotlin 这样设计是为了防止非 final 类型的滥用也就是说如果一个变量永远不会被修改就有必要给他加上 final让其他人看到代码更好理解。 Ps建议写代码时可以先使用 val如果真的需要修改再改为 var b如何查看 Kotlin 对应的 Java 代码如下 基本数据类型
Kotlin 不存在基本类型全部都是对象类型
Java基本类型Kotlin对象类型对象类型说明intInt整型longLong长整型shortShort短整型floatFloat单精度浮点型doubleDouble双精度浮点型booleanBoolean布尔型charChar字符型byteByte字节型 函数
无参无返回值
fun add1() {}有参有返回值语法如下
fun 方法名(参数名: 类型): 返回值类型 { 函数体 }
fun add2(a: Int, b: Int): Int {return a b
}当函数体只有一行代码时可以直接使用以下方式声明
fun add3(a: Int, b: Int): Int a b
Kotlin 存在类型推导返回值类型也可省略
fun add4(a: Int, b: Int) a b调用的的时候直接写函数名即可
fun add4(a: Int, b: Int) a bfun main() {println(add4(3, 5))
}和
Kotlin 中的 等价于 Java 的 equals比较的是对象里的内容Kotlin 中只有对象类型不存在值比较而 等价于 Java 中 比较的是对象的引用. 选择控制if、when
if
Kotlin 中的 if 和 Java 基本上没有区别
例如实现一个返回最大值的函数有以下多种写法
fun max1(a: Int, b: Int): Int {if(a b) {return a}return b
}fun max2(a: Int, b: Int): Int {return if(a b) a else b //if 也可以直接返回值
}fun max3(a: Int, b: Int) if(a b) a else bwhen
a类似 Java 中的 switch 语句可以进行选择控制
如下代码
fun whenTest(num: Int) {when(num) {1 - println(1)2 - println(2)3 - println(3)4 - println(4)else - println(非法) //else 可有可无}
}解释例如当 num 为 2 时when 就会匹配 num 为 2执行 println(2)程序结束. 与 switch 不同的是这里执行完 num 为 2 逻辑后不需要 break自动跳出 when 语句如果 num 非 1、2、3、4就会执行 else 逻辑.
cwhen 也支持执行代码块
fun whenTest2(name: String) {when(name) {1 - {println(你好1)println(你好2)println(你好3)}2 - println(我好像作用不大)else - println(非法)}
}bwhen 支持参数检查
fun checkNumber(num: Number) {when (num) {is Int - println(Int)is Double - println(Double)else - println(others)}
}
cwhen 也可以不传递参数
fun whenTest3(name: String) {when {name cyk - println(男)name lyj - println(女)else - println(emm...)}
} 循环语句
Kotlin 有两种循环方式while 和 for-in
while 和 Java 中的 while 没有区别因此这里就不再赘述 while 了而 for-in 则是对 for-each 的加强舍弃了 for-i 的写法.
对于 for-in 的写法首先要明确一个 区间 的概念 val range 0..10 //代表区间 [0, 10]前闭后闭afor-in 需要使用区间
fun test1() {val range 0..10 //前闭后闭for(i in range) { //也可以使用 for(i in 0..10)print(${i} )}
}b0..10 表示双闭区间如果想使用左闭右开需要借助 until 关键字
fun test2() {for(i in 0 until 10) { //前闭后开 [0, 10)print(${i} )}
}c上面的代码类似于 iKotlin 也支持跳步
fun test3() {for(i in 0 until 10 step 2) {print(${i} )}
}d以上实现都是升序Kotlin也可以实现降序循环.
fun test4() {for(i in 10 downTo 0) { //前闭后闭print(${i} )}
}for-in 还可以进行集合的遍历后续再演示.
通过 main 函数依次执行以上函数如下
fun main() {test1()println(----------------------)test2()println(----------------------)test3()println(----------------------)test4()println(----------------------)
}执行结果如下 类和对象
创建和使用
创建一个 Person 类具有 name 和 age 属性showInfo 方法打印信息代码如下
class Person {var name var age 0fun showInfo() {println(name: ${name}, age: ${age})}
}对象的创建和使用如下 val person Person()person.name cykperson.age 20person.showInfo()继承
声明 Person 类声明 Student 类并继承 Person 类
open class Person {var name var age 0fun showInfo() {println(name: ${name}, age: ${age})}
}class Student : Person() { //被继承的类需要使用 open 修饰(需要在 Person 类前添加 open)var num 1var grade 0fun study() {println(student: ${name} do homework)}
}注意Person 类默认情况下不能被继承的因为默认情况下类似于 Java 中的 final 修饰的因此。这里需要使用 open 关键字才可以解除 final。否则 IDEA 自动语法检测报错 构造
主构造
在 Kotlin 中分为主构造和次构造。
a主构造直接写在类后面即可如下代码
//主构造(直接写在类后面)
class Student(val num: Int, val grade: String) {
}创建方式如下 var student Student(1, 三年二班)b当 Person 和 Student 都有主构造并且 Student 继承了 Person 类时就需要修改 Student 的主构造附带上父类的参数此时不需要指定 var 或 val如下代码
open class Person(val name: String, val age: Int) {
}class Student(val num: Int, val grade: String, name: String, age: Int):
Person(name, age) {
}fun main() {//创建 Student 对象var student Student(1, 三年二班, cyk, 20)
}
c如果在构造时需要进行一些特殊处理怎么办Kotlin 中提供了 init 结构体主构造的逻辑可以在 init 中进行处理如下代码
class Student(val num: Int, val grade: String, name: String, age: Int):
Person(name, age) {init {println(对主构造中的参数进行了一些特殊处理)println(...)}
}如果一个类想要有多种构造方法该怎么做这就需要用到次构造
次构造
aconstructor 中只需要指定创建该对象时需要的参数也就是说无参构造无需指定任何参数this 中就表明了需要什么样的参数代码如下
class Student(val num: Int, val grade: String, name: String, age: Int):
Person(name, age) {//两个参数的构造constructor(name: String, age: Int) : this(0, , name, age){}//无参构造constructor(): this(0, , , 0) {}
}通过以上构造就有三种创建 Student 对象的方式如下 //创建 Student 对象var student1 Student(1, 三年二班, cyk, 20)var student2 Student(cyk, 20)var student3 Student()b如果类不要主构造那么继承类也无需通过 () 的方式初始化参数子类次构造可以通过 super 来初始化父类的构造器
class Student: Person {constructor(name: String, age: Int, grade: String) : super(name, age){}
}创建对象如下 //创建 Student 对象Student(cyk, 20, 三年二班)接口
定义
和 Java 基本没什么区别
interface Study {fun study()fun sleep()fun doHomework()}
Kotlin 支持接口的方法有默认实现JDK1.8以后支持此功能如果有默认实现则继承类可以重写该方法也可以不重写若重写以重写为主否则执行默认实现.
interface Study {fun study() {println(学习ing )}fun doHomework()
}class Student(val name: String, val age: Int): Study, Other { //多个接口只需要使用逗号隔开// override fun study() { //可以不重写 若重写则执行此方法
// println(学习)
// }override fun doHomework() {TODO(Not yet implemented)}override fun sleep() {TODO(Not yet implemented)}}实现
Kotlin 和 Java 一样支持一个类实现多个接口需要实现所有方法若接口的方法有默认实现则可以不重写该方法
class Student(val name: String, val age: Int): Study, Other { //多个接口只需要使用逗号隔开override fun study() {TODO(Not yet implemented) //TODO 表明该方法未被实现因此实现该方法时需要将这一行删除}override fun doHomework() {TODO(Not yet implemented)}override fun sleep() {TODO(Not yet implemented)}}权限修饰符
Java 和 Kotlin 的异同点.
需要注意的是Kotlin 中移除了 default引入了 internal 修饰.
修饰符JavaKotlinpublic所有类可见所有类可见默认private当前类可见当前类可见protected当前类子类同包下类可见当前类子类可见default同包下类可见默认无internal无同模块下的类可见
使用方式和 Java 没什么区别
//类上
public open class Solution(val name: String, val number: Int) {//变量上private val key 1//方法上private fun test() {}}数据类实体类和单例类
数据类
数据类则只处理数据相关实体类与Java Bean类似通常需要实现其getsethashCodeequalstoString等方法
例如一个用户实体类Java 代码如下
public class UserJava {private Integer id;private String username;private String password;public UserJava() {}public UserJava(Integer id, String username, String password) {this.id id;this.username username;this.password password;}public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getUsername() {return username;}public void setUsername(String username) {this.username username;}public String getPassword() {return password;}public void setPassword(String password) {this.password password;}Overridepublic boolean equals(Object o) {if (this o) return true;if (o null || getClass() ! o.getClass()) return false;UserJava userJava (UserJava) o;return Objects.equals(id, userJava.id) Objects.equals(username, userJava.username) Objects.equals(password, userJava.password);}Overridepublic int hashCode() {return Objects.hash(id, username, password);}Overridepublic String toString() {return UserJava{ id id , username username \ , password password \ };}}而 Kotlin 实现以上实体类只需要一个新建一个 kt 文件选择创建 Data Class 类型一行代码即可搞定虽然一行可以搞定但是建议还是分行写可读性高如下
data class UserKotlin(val id: Int,val username: String,val password: String
)若无data关键字上述方法hashCodeequalstoString无法正常运行. 单例类
Java 最广泛使用的单例如下
public class Singleton {private static final Singleton singleton new Singleton();public static Singleton getSingleton() {return singleton;}private Singleton() {}/*** 测试方法*/public void test() {}}而 Kotlin 中实现单例模式只需要 object 修饰即可如下代码
object Singleton {fun test() {println(hello)}
}使用如下
fun main() {Singleton.test() //等同于 Java 中 Singleton.getSingleton.test
}集合
List
fun listTest() {//常规创建//list1 类型ArrayListIntvar list1 ArrayListInt()list1.add(1)list1.add(2)list1.add(3)//创建不可变类型创建后不可进行增加和删除操作只能进行查询//list2 类型: ListIntval list2 listOfInt(1, 2, 3)//创建可变类型创建后可以继续增删改查//list3 类型: MutableListIntvar mutableListOf mutableListOfInt()mutableListOf.add(1)mutableListOf.add(2)for(value in list1) {print($value )}
}Set
fun setTest() {//常规创建//set1 类型: HashSetIntvar set1 HashSetInt()set1.add(1)set1.add(2)set1.add(3)//创建不可变类型创建后不可进行增加和删除操作只能进行查询//set2 类型: SetIntvar set2 setOfInt(1,2,3)//创建可变类型创建后可以继续增删改查//set3 类型: MutableListIntvar set3 mutableSetOfInt()set3.add(1)for(value in set1) {print($value )}
}Map
fun mapTest() {//常规创建//map1 类型: HashMapString, Stringvar map1 HashMapString, String()map1.put(name, cyk)map1.put(age, 20)//Kotlin 中 map 支持下表的赋值和访问map1[id] 1map1[gender] 男//创建不可变类型创建后不可进行增加和删除操作只能进行查询//map2 类型: mapOfString, Stringvar map2 mapOfString, String(name to cyk, age to 20)//创建可变类型创建后可以继续增删改查//set3 类型: MutableListIntvar map3 mutableMapOfString, String()map3.put(name, cyk)map3.put(age, 20)map3[id] 1map3[gender] 男for((key, value) in map3) {println($key $value);}}Lambda 的使用
基本认识
方法在传递参数时都是普通变量而Lambda可以传递一段代码
Lambda表达式的语法结构
{参数名1 参数类型 参数名2参数类型 - 函数体} list.maxByOrNull
Kotlin 的 list 提供了 maxByOrNull 函数参数就是一个 lambda 表达式用来返回当前 list 中 xx 最大的元素xx 是我们定义的条件可能为长度可能是别的.
这里拿长度来举例例如我有一个 list现在要找出 list 中长度最大的元素如下代码
fun test1() {//找出 list 中长度最大的元素val list listOfString(a, abc, abcd, ab)//写法1val lambda {str: String - str.length}var maxStr list.maxByOrNull(lambda)//写法2maxStr list.maxByOrNull {str: String - str.length}//写法3maxStr list.maxByOrNull() {str: String - str.length}//写法4: 基于 Kotlin 的类型推导机制Lambda 可以省略参数类型maxStr list.maxByOrNull {str - str.length}//写法5: 若 Lambda 只有一个参数可以使用 it 代替参数名maxStr list.maxByOrNull {it.length}println(maxStr)
}list.map、list.filter、list.any、list.all //创建一个 list后续操作都以此展开var list listOf(a, ab, abc, abcd)//map 用于返回一个新的集合例如将集合中的元素都换成大写val mapList list.map { it.toUpperCase() }//filter 过滤返回一个新集合例如对集合中的元素进行筛选(筛选出长度大于 3 的元素)val filterList list.filter { it.length 3 }//any 返回 Boolean用来判断集合中是否有元素满足 Lambda 条件只要有任意一个满足返回 true否则返回 falseval anyList list.any {it.length 3} //存在一个字符串长度大于 3因此返回 true//all 返回 Boolean集合中元素是否全部都满足 Lambda 的条件全都满足才返回true有任意一个不满足就返回 falseval allList list.all { it.length 4 } //所有元素长度都满足字符串长度小于等于 4 因此返回 true空指针检查机制
国外统计程序出现最多的异常为空指针异常Kotlin存在编译时检查系统帮助我们发现空指针异常。 Kotlin把空指针异常的检查提前到了编译期若空指针则编译期就会崩溃避免在运行期出现问题因此在 Kotlin 中任何变量和参数都不允许为空. a参数为空报错
fun study(study: Study) {study.doHomework() //正确study.readBook() //正确
}fun main() {study(null) //报错study(Study()) //正确
}
b如果有需求就是要传入 null那么可以通过 ? 来对传入可能为 null 的参数在类型后进行声明
fun study(study: Study?) {study.doHomework() //报错study.readBook() //报错
}fun main() {study(null) //正确study(Study()) //正确
}
c?的意思则是当前参数可为空如果可为空的话则此对象调用的方法必须要保证对象不为空上面代码没有保证则报错修改如下
fun study(study: Study?) {if(study ! null) {study.doHomework() //正确study.readBook() //正确}
}fun main() {study(null) //正确study(Study()) //正确
} 辅助判空工具
?.
表示 前面对象不为空才执行.后面的方法
fun study(study: Study?) {study?.doHomework() study?.readBook()
}?:
表示 前不为空则返回问号前的值为空则返回后的值
fun test1(a: Int, b: Int) {val c a ?: b //a 不为空返回 a为空返回 b
}!!
如果想要强行通过编译就需要依靠!!这时就是程序员来保证安全
fun study(study: Study?) {study!!.doHomework()study!!.readBook()
}let 函数
let 是一个函数提供了函数式 API 接口会将调用者作为参数传递到 Lambda 表达式调用之后会立马执行 Lambda 表达式的逻辑.
aaa.let { it - // it 就是 aaa调用者//执行业务逻辑
}
例如原本函数的逻辑是这样的
fun study(study: Study?) {if(study ! null) {study.doHomework()study.readBook()}
}通过 let 则可以改为
fun testLet(study: Study?) {//此时通过 ?.就保证了 study 不为空的时候才会执行 let 函数study?.let { it -it.doHomework()it.readBook()}
}a好处1最常用的就是使用 let 函数处理一个可 null 的对象做统一判空处理例如上述代码.
b好处2在有限的范围内引入局部变量提高代码的可读性. 内嵌表达式
以前我们拼接字符串可能是这样的如下
fun printTest() {val name cykval age 20println(name: name age: age)
}a通过 Kotlin 提供的内嵌表达式就不需要拼接了只需要如下代码
fun printTest() {val name cykval age 20println(name: $name, age: $age)
}b内敛表达式还支持复杂的操作语法为 ${表达式}
fun printTest() {val name cykval age 20println(name: ${if (2 1) cyk else lyj}, age: $age)
}函数参数默认值
aKotlin 支持函数默认值如下
fun study(name: String, age: String 男) {println(name: $name, age: $age)
}fun main() {study(cyk)study(lyj, 女)
}运行结果 b如果方法的第一个参数设置成默认值那么传入的第一个实参就会匹配第一个形参因此就可能出现以下问题.
fun study(age: String 男, name: String) {println(name: $name, age: $age)
}fun main() {study(cyk) //报错
}你可能会这样想因为第一个设置了默认值而我又想让我传入的实参就不匹配设置了默认值的形参了...
如果一定要这么做Kotlin 也提供了键值对的形式来匹配形参解决上述问题如下
fun study(age: String 男, name: String) {println(name: $name, age: $age)
}fun main() {study(name cyk) //报错
}