您现在的位置是:首页 >其他 >Kotlin网站首页其他
Kotlin
目录
一、简介
Kotlin是一门用于现代多平台应用的静态编程语言,其中被广泛用于Android平台的开发,被称之
为Android世界的Swift。它由大名鼎鼎的JetBrains公司设计开发并开源,著名的IDE 工具IntelliJ
IDEA就是他们的产品,所以无疑他们是对编程语言设计领域最为熟悉的专家。安卓世界的斯威夫
特。它由大名鼎鼎的JetBrains公司设计开发并开源,著名的IDE工具IntelliJ IDEA就是他们的产
品,所以无疑他们是对编程语言设计领域最为熟悉的专家.
Kotlin 从2016年发布1.0的release 版本开始至今,使用的开发者数量快速增长。
1、使用原因
在2019年Google lO大会上,google宣布今后将优先采用Kotlin进行Android开发。
Kotlin是一种新型的静态类型编程语言,不仅可以减少常见代码错误,还可以轻松集成到现有应用
中。
富有表现力且简洁可以使用更少的代码实现更多的功能。少编写样板代码。在使用Kotlin的专业开
发者中,有67%的人反映其工作效率有所提高。
更安全的代码Kotlin有许多语言功能,可帮助避免null指针异常等常见编程错误。包含Kotlin代码
Android应用发生崩溃的可能性降低了20%。
可互操作可以在Kotlin 代码中调用Java 代码,或者在Java代码中调用Kotlin代码。Kotlin 可完全与
Java编程语言互操作,因此可以根据需要在项目中添加任意数量的Kotlin 代码。
结构化并发Kotlin协程让异步代码像阻塞代码一样易于使用。协程可大幅简化后台任务管理,例如
网络调用、本地数据访问等任务的管理。
二、基本语法
1、数据类型
基本数值类型、浮点类型、字符类型、字符串类型、类型强制转换、数字运算
package com.example.fristapp.lesson
fun main() {
var str="123456"
//字符串的模板表达式 以$开始
println("the result is $str")
println("the result is ${str.length}")
println("-----------")
//helloworld3要求它的字符串内容是json格式,
val helloworld3 = "{"key":"value"}"
//"""分解符,字符串内容无需转义,看起来更清爽
val helloworld4 : String = """
|Tell me and I forget
|Teach me and I remember
|{"key1": "value1"}
|{"key2": "value3"}
""".trimIndent()
println("helloworld4"+helloworld4)
println("-----------")
println(helloworld3)
}
2、数组
(1、)创建
arrayOf创建数组
创建一个数组并传递元素值给它,集合中的元素可以是任意类型
//arrayOf创建数组
val arrayNumber:Array<Int> = arrayOf(1,2,3,4,5)
val arrayObjects:Array<Any> = arrayOf(1, "2" , true)//任意类型
//2.使用arrayOfNulls创建空数组,
//创建一个指定大小的、所有元素都为空的数组,但必须指定集合中的元素类型
val arrayOfNulls= arrayOfNulls<String>(5)
arrayOfNulls[0]= "12345"
println(arrayOfNulls)
//3 .利用array的构造函数,动态创建数组
//创建一个 Array<String>初始化为["O","1","4","9","16"]ll i= 0,1,2,3,4
//i*i ="0","1","4","9","16"
//数组创建的时候,会循环5次,i就是数组的下标l/→>右边的表达式的结果,就是数组中当前下表的元素
val asc = Array( 5) { i : Int->(i * i).toString() }
(2、)遍历
3、集合
List是一个有序集合,可通过索引(下标)访问元素。元素可以在 list中出现多次、元素可重复。
Set是唯一元素的集合。一组无重复的对象。一般来说set中元素的顺序并不重要、无序集合。
Map(字典)是一组键值对。键是唯一的,每个键都刚好映射到一个值,值可以重复。
可变集合,显而易见,是指集合创建完成之后,可以对集合进行增删改查操作
不可变集合,显而易见,是指指集合创建完成之后,不能对集合进行增删操作,会抛异常
4、方法
(1、)普通类的方法
class Person{
fun tes(){
println("普通成员方法")
}
}
(2、)静态类的方法
如果我们想实现一个工具util的话,可以借助关键字object来创建一个静态类
object UtilNumber{
fun test2(){
println("静态成员方法")
}
}
(3、)companion object伴生类的方法
class Person{
fun tes(){
println("普通成员方法")
}
companion object{
fun test2(){
println("伴生成员方法")
}
}
}
(4、)方法参数
默认参数
方法参数可以有默认值,当省略相应的参数时使用默认值。与其Java相比,这可以减少重载数量我
们可以通过类型后面的=来设置默认值。
fun read(offset: Int = 0 ,start: Int){
offset+start
}
具名参数
如果一个默认参数在一个无默认值的参数之前,那么无默认值的参数,只能通过使用具名参数调用
该方法来使用:
fun read1(offset: Int= 1,start: Int){
offset+start
}
//offset:int他有一个默认值是为0start:int他没有默认值
//第三个参数是一个方法,参数名叫作,action:()。如果参数的类型是(),说明该参数是一个方法类型//方法参数的返回值使用-> String。
fun read2(offset: Int =2,start: Int,action:()->String){
val ret = action()
println("read2:${ret}")
}
------------------
Person().read1(start = 1)
Person().read2(1,3, action = {
"aaaaa"
})
Person().read2(start = 3){
"括号外传递action参数"
}
可变数量的参数
方法的参数(通常是最后一个)可以用vararg修饰符标记:
fun append(vararg str:Char):String{
val result = StringBuffer()
for (char in str) {
result.append(char)
}
return result.toString()
}
-------------------------------
val appendStr = Person().append('1','3','5')
println("append${appendStr}")
val world = charArrayOf('w','o','r','d')
val result = Person().append('h','e',*world)
只有一个参数可以标注为vararg;
如果vararg 参数不是最后一个参数,可以使用具名参数语法,给后面的参数的传递值.
5、Lambda表达式
在Java 8的时候开始支持Lambda表达式,目前Lambda语法在Java中已经被广泛的运用,Lambda
表达式可以理解为是一种语法糖,值得庆幸的是,Kotlin一经开源成熟就已经支持这种语法。
Lambda表达式的本质其实是匿名方法,因为在其底层实现中还是通过匿名方法来实现的。但是我
们在用的时候不必关心起底层实现。不过Lambda的出现确实是减少了代码量的编写,同时也是代
码变得更加简洁明了。
6、条件控制
(1、)if表达式
if 是一个表达式所以它会返回一个值,表达式的值为表达式作用域内最后一行的值
(2、)when
7、泛型
Kotlin 的泛型与Java一样,都是一种语法糖。泛型(Generics)其实就是把类型参数化,它的引入给
强类型编程语言加入了更强的灵活性。
使用原因
架构开发的一把利器;
使我们的代码或开发出来的框架更加的通用;
增加程序的健壮性,避开运行时可能引发的ClassCastException;
能够帮助你研究和理解别的框架;
自己造轮子需要,能用泛型解决问题;
泛型有:泛型类、泛型接口、泛型方法和泛型属性
(1、)泛型接口/类
定义泛型类型,是在类型名之后、主构造函数之前用尖括号括起的大写字母类型参数指定:
//泛型接口
interface Drink<T> {
fun drink(t: T):String
}
class DrinkApple:Drink<String>{
override fun drink(t: String):String {
println("drink:${t}")
return t
}
}
//泛型类
abstract class Color<T>(val t: T){
abstract fun printColor()
}
class BlueColor(val color: String):Color<String>(color){
override fun printColor() {
println("printColor${color}")
}
}
(2、)泛型方法
//泛型方法
fun <T> fromJson(json:String ,tClass:Class<T>):T?{
val instance:T? =tClass.newInstance()
return instance
}
(3、)泛型约束
//泛型约束(1)
//泛型类型限定-1
//所传递的类型T必须满足是User的子类或User类
class User1{
}
fun <T:User1> fromJson2(json:String ,tClass:Class<T>):T?{
val instance:T? =tClass.newInstance()
return instance
}
//泛型约束(2)
所传递的类型T必须同时满足where子句的所有条件,在下面的示例中,类型丁必须既实现了User,也实现了Comparable
fun <T> fromJson3(json:String , tClass : Class<T>): T? where T :JSONObject ,T:Comparable<T>{
val instance:T? =tClass.newInstance()
return instance
}
class User : JSONObject(),Comparable<User>{
override fun compareTo(other: User): Int {
return 0
}
}
-------------
fromJson2("{}",User1::class.java)
fromJson3("{}",User::class.java)
(4、)泛型中的out与in
out约束泛型参数的类型上限
泛型参数的类型允许传入T,以及T的子类
//out关键字
open class Animal
open class DogAnimal:Animal()
class CatAnimal : Animal()
class WhitDogAnimal: DogAnimal()
fun animaalFuns(){
val animal: Animal = DogAnimal()
//传入的泛型参数可以是 Animal及Animal的子类DogAnimal,CatAnimal,WhitDogAnimal....
// 1。使用处使用out关键字声明--泛型上限
val animalList : ArrayList<out Animal> = ArrayList<DogAnimal>()
// 1。定义处处使用out关键字声明--泛型上限
val animalList2 : ArrayList<Animal> = ArrayList<DogAnimal>()
// 使用处使用in关键字声明,约定泛型的下限,允许传入的泛型类型是DogAnimal及其父类Animal
// 1。使用处使用in关键字声明--泛型下限
val animalList3 : InArrayList<in DogAnimal> = InArrayList<Animal>()
// 1。定义处处使用in关键字声明--泛型下限
val animalList4 : InArrayList<DogAnimal> = InArrayList<Animal>()
}
class ArrayList<out T>{}
class InArrayList<in T>{}
8、Kotlin扩展
(1、)扩展方法
Kotlin的扩展函数可以让你作为一个类成员进行调用的函数。这样可以很方便的扩展一个已经存在
的类,为它添加额外的方法。在Kotlin源码中,有大量的扩展函数来扩展Java,这样使得Kotlin比
Java更方便使用,效率更高。
class Jump{
fun test(){
println("test")
}
}
//扩展方法的定义,就是在方法的前面加上类前缀
fun Jump.doubleJump():String{
return "doubleJump"
}
Java中调用扩展函数
KTExtensionsKt.doubleJump(new Jump( ) );
(2、)泛型扩展方法
//泛型方法定义
fun <T> MutableList<T>.swap(index:Int,index2: Int){
val temp = this[index]
this[index] = this[index2]
this[index2] = temp
}
-----------------
val list = mutableListOf<Int>(1,2,3,4,5)
list.swap(0,3)
for (i in list) {
println("index->${i}")
}
(3、)扩展属性
扩展属性提供了一种方法能通过属性语法进行访问的API来扩展。尽管它们被叫做属性,但是它们不能拥有任何状态,它不能添加额外的字段到现有的Java对象实例。
//扩展属性
val String.lastChar:Char get() = this.get(length -1)
-----------------
val android = "android"
println(android.lastChar)
(4、)let、run、apply
let扩展函数
let扩展函数的实际上是一个作用域函数,当你需要去定义一个变量在一个特定的作用域范围内,那
么let函数是一个不错的选择;let函数另一个作用就是可以避免写一些判断null的操作。
//let扩展函数,类后面加上?代表参数可能为空,使用的时候注意判空
fun testLet(str:String?){
// str.let{
// val str2 = "android"
// println(str2+it)
// }
//判空用法,当str为空,则不会触发闭包里面的逻辑
str?.let {
val str2 = "android"
println(str2+it)
}
}
run函数
run函数只接收一个lambda函数为参数,以闭包形式返回,返回值为最后一行的值或者指定的
return的表达式,在run函数中可以直接访问实例的公有属性和方法。
fun testRun(jump: Jump):String {
jump.run{
test()
println("111111")
return "222"
}
}
apply扩展
apply函数的作用是︰调用某对象的apply函数,在函数范围内,可以任意调用该对象的任意方法,
并返回该对象。
从结构上来看apply函数和run函数很像,唯一不同点就是它们各自返回的值不一样,run函数是以闭
包形式返回最后一行代码的值,而apply函数的返回的是传入对象的本身。
apply一般用于一个对象实例初始化的时候,需要对对象中的属性进行赋值。或者动态inflate出一个
XML的View的时候需要给View绑定数据也会用到,这种情景非常常见。
fun testApply(){
ArrayList<String>().apply {
add("111")
add("222")
}.run{
for (index in indices) {
println("apply->${index}")
}
}
}
三、案例
package com.example.fristapp.lesson
fun main() {
while (true){
println("===================请输入如你的表达式===================")
var input= readLine()//从键盘输入
try {
input?.let {//不为空
val ret = caculate(it)
println("${input}=${ret}")
println("是否继续使用(y/n)")
val cmd = readLine()
cmd?.let {
if (it.equals("n")){
System.exit(-1)
}else{
}
}
}
}catch (ex:java.lang.Exception){
ex.printStackTrace()
}
//结束
}
}
fun caculate(input: String): String {
/*input.trim()//去空格
input.split("")//切割*/
if (input.contains("+")){
val nums = input.trim().split("+")
return operate(nums[0].toDouble(),nums[1].toDouble(),"+").toString()
}else if (input.contains("-")){
val nums = input.trim().split("-")
return operate(nums[0].toDouble(),nums[1].toDouble(),"-").toString()
}else if (input.contains("*")){
val nums = input.trim().split("*")
return operate(nums[0].toDouble(),nums[1].toDouble(),"*").toString()
}else if (input.contains("/")){
val nums = input.trim().split("/")
return operate(nums[0].toDouble(),nums[1].toDouble(),"/").toString()
}else{
return "您输入的程序有误"
}
}
fun operate(num1: Double, num2: Double,operate:String): Double {
return when (operate){
"+" -> num1 + num2
"-" -> num1 - num2
"*" -> num1 * num2
"/" -> num1 /num2
else -> 0.0
}
}