百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

可以用Kotin写项目了--Kotlin基础入门

wptr33 2024-12-03 18:45 29 浏览

1、为什么使用Kotlin开发Android呢?

java被 Oracle收购后,谷歌经常被Oracle告侵权,所以谷歌选择了Kotlin作为Android开发的第一语言,在Android官网上 说Kotlin是免费且开放的,是由一家特别厉害的公司JetBrains开发的静态编程语言,AndroidStudio也是根据他家的IDEA改的,谷歌也贡献了开源代码 Kotlin的优点:

  • 富有表现力且极简洁 Kotlin 的现代语言功能让您可以专注于表达自己的想法,少编写样板代码。
  • 更安全的代码 借助自身类型系统所含的 @Nullable 和 @NonNull,Kotlin 可帮助您避免 NullPointerExceptions。使用 Kotlin 的 Android 应用发生崩溃的可能性降低了 20%。
  • 可互操作 可以和Java代码互通,互相调用
  • 结构化并发 Kotlin 协程可简化异步编程,让您能够轻松高效地执行网络调用和数据库更新等常见任务。

2、基础语法

2.1、变量

类型推导 根据初始化的类型进行类型推导 可变变量定义 var 不可变变量定义val 相当于java的final修饰 Kotlin是一个静态语言 ,编译期就决定的东西

class VariableDemo {
 // var <标识符> : <类型> = <初始化值>
 // val <标识符> : <类型> = <初始化值>
 // var userName:String="爱码士"
    var name="爱码士"//自动推导为字符串
    val age=100//自动推导为 Int
}

decompiledJava(用插件先把Kotlin转为字节码,再翻编译成java文件)后的代码

public final class VariableDemo {
   @NotNull
   private String name = "爱码士";
   private final int age = 100;

   @NotNull
   public final String getName() {
      return this.name;
   }

   public final void setName(@NotNull String var1) {
      Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
      this.name = var1;
   }

   public final int getAge() {
      return this.age;
   }
}

由以上代码可以看出var转为java之后是有get和set方法的,而val用了final修饰之后并且没有set方法,说明了用var修饰的变量可读可写,用val修饰的变量可读不可写

2.2、函数

不带返回值的方法void==Unit 可以省略

  fun testFun(number1:Int,number2:Int):Unit{
        println(number1+number2)
    }

有返回值返回值 和参数的方法

    fun testFun(number1:Int,number2:Int):Int{
        println(number1+number2)
        return number1+number2
    }

一种更高级的写法 方法 = 推导返回值类型

fun add(number1: Int,number2: Int) = number1+number2 //返回值推导成Int
fun add3(number1: Int, number2: Int) = "爱码士"//返回值推导成String

java里可以有可变参数,Kotlin里也有需要用vararg 关键字来修饰 可变参数(可变长的参数)

 fun lenMethod(vararg number:Int){
     println(number.size)
 }

lambda表达式函数(这里先举个例子,以后专门写个文章来学习lambda)

fun main(){
    // lambda表达式函数
    val addMethod : (Int, Int) -> Int = {number1, number2 -> number1 + number2}
    val r= addMethod(9, 9)
    println(r)
}

2.3、字符串模板

写起来会快一点

  val name = "爱码士"
  val age = 28
  val sex = 'M'
  val info = "ABCDEFG"
  println("name:$name,  age:$age,  sex:$sex  info:$info")

三个双引号,原样输出,换行不需要转义字符,

    val infoMesage = """
        AAAAAAAAAAA"aaa"
        BBBBBBBBBBB
        CCCCCCCCCCC
        DDDDDDDDDDD
        EEEEEEEEEEE
    """  // 前置空格
    println(infoMesage)//输出来会有前置空格
     val infoMesage2 = """
        AAAAAAAAAAA
        BBBBBBBBBBB
        CCCCCCCCCCC
        DDDDDDDDDDD
        EEEEEEEEEEE
    """.trimIndent()  // 没空格

trimIndent()去掉前置空格,具体什么效果大家可以敲一敲 去试试 显示$999.99 ${‘$’}999

val price = """
        ${'#39;}99999.99
    """.trimIndent()
    println(price)

2.4 、Kotlin特色之一 null检查机制

var name:String?=null//?会发一个通知,告诉所有调用者,现在这个变量是可以为null的,你们调用者自己去实施补救措施
fun main() {
    //name.length//如果不补救则会编译报错,报下图的错
}

一共三种补救措施 第一种就是方法内允许返回空值,在返回值返回的后边加一个?,这样的话就将补救措施交给了返回值的调用者

fun main() {
    var testStr=test()
    //testStr.length
}
fun test():String?{
    return null
}

这种写法testStr.length报的错误和上面一样的,如果把test方法返回值的?去掉,则这个方法是不允许返回null的,testStr.length是不会报错的 第二种补救措施 调用的这个属性的时候,点前边加一个?,表示如果这个属性为null,则后边的代码不执行

fun main() {
    var testStr=test()
    testStr?.length//如果testStr为null,则.length不执行
}
fun test():String?{
    return null
}

第三种补救措施在调用的时候,点前面加两个!!,表示这个属性一定不为null,后面的一定执行

fun main() {
    var testStr=test()
    testStr!!.length//如果testStr为null,则.length不执行
}
fun test():String?{
    return null
}

第三种补救措施一定要慎用,在确定这个属性为百分之百不为null的情况下可以这样用,否则会出现空指针异常的情况

2.5、区间

fun sectionTest(){
    //区间 ..  只能从小数到大数
    for (index in 1..10){
        print(index)
    }
    println("")
    //区间 down to  只能从大数到小数
    for (index in 10 downTo 1){
        print(index)
    }
    println("")
    //step 步幅
    for (index in 1..10 step 4){
        print(index)
    }
    //in 和 downTo是闭区间 unitl 半闭半开区间
    //半闭半开区间 也是只能从小数到大数
    for(index in 1 until 10){
        print(index)
    }
}

输出结果:

3、比较与数组

==比较值本身相当于,equals也能用,但是有黄色波浪线 ===比较对象地址

    val name1: String = "爱码士"
    val name2: String = "爱码士"

    // --- 比较值本身
    // == 等价 Java的equals
    println(name1.equals(name2))
    println(name1 == name2)


    // ---  比较对象地址
    val test1:Int? =  10000
    val test2:Int? =  10000
    println(test1 === test2) // false

数组 arrayOf泛型 类型推导

 val numbers = arrayOf(1, 2, 3, 4, 5, 6, 7, 8)
 //取值numbers[index]
 numbers[0]
 //方式二
  val numbers2 = Array<String>(10,  {value: Int -> ("aaa") })
 // val numbers2 = Array<String>
 						(10,//数组大小
 						  {value: Int //数组下标-
 						  > ("aaa")//给下标为value的赋值aaa })

也可以这样写

 val numbers2 = Array<String>(10,  {value: Int -> if(value==5) ("666") else ("aaa") })
    for (value in numbers2) {
        println(value)
    }

decompiledJava后的代码

public static final void main() {
      byte var1 = 10;
      String[] var2 = new String[var1];

      boolean var5;
      for(int var3 = 0; var3 < var1; ++var3) {
         var5 = false;
         String var8 = var3 == 5 ? "666" : "aaa";
         var2[var3] = var8;
      }

      String[] var11 = var2;
      int var4 = var2.length;

      for(int var10 = 0; var10 < var4; ++var10) {
         String value = var11[var10];
         var5 = false;
         System.out.println(value);
      }

   }

4、条件控制

表达式比大小

    val age=5;
    val age1=10;
    val maxValue=if (age>age1) age else age1

区间判断

val age=5;
 if(age in 1..18){
        println("未成年")
    }else{
        println("已成年")
    }

switch的升级版when

val age=5;
 when(age){
        in 1..18->{//判断是否在1到18之间
            
        }
        19,21,22,24->{//满足其中一个就执行这个分支
            
        }
        else->{//不满足以上条件 走这个分支
            
        }
    }

when的类型推导

var str= when(age){
        in 1..18->{
            "年龄为$age,未成年"
        }
        19,21,22,24->{
            "年龄为$age,成年了"
        }
        else->{
            "年龄为$age,其他"
        }
    }
    println(str)

如果各个分支的返回类型不相同,str则会被推导成Any类型,相当于Java当中的Object

5、循环与标签

在 Kotlin 中任何表达式都可以用标签来标记。 标签的格式为标识符+ @ 符号,例如:aaa@、bottom@都是有效的标签, 要为一个表达式加标签,我们只要在其前加标签即可。 标签的应用 break

 tttt@ for (i in 1..20) {

        for (j in 1..20) {
            println("i:$i, j:$j")
            if (i == 5) {
                // break // j循环 给break
                break@tttt // i循环 给break
            }
        }

return

fun testLabel(){
    var numbers= arrayOf(1,2,3,4,5,6)
    testFor@numbers.forEach {
        when(it){
            5->{
//                return //不打印aaa
               return@forEach//打印aaa
            }
        }
    }
    println("aaa")
}

this

class SafeDemo {
    val name="爱码士"
    inner class SafeDemoInner{
        val name="inner 爱码士"
        fun test(){
            println(this.name)//inner 爱码士
            println(this@SafeDemo.name)//"爱码士"
        }
    }

}

for循环

 var items  = listOf<String>("李四", "张三", "王五")
    for (item in items) {
        println(item)
    }

    items.forEach {
        println(it)
    }

    for (index in items.indices) {
        println("下标:$index,  对应的值:${items[index]}")
    }

6、类与对象

先来一个空类

//默认public 所以不用写public
class Test {
}

6.1、构造方法

class Test(val age:Int) {//主构造的写法
    constructor():this(5)//次构造       次构造 必须调用主构造
    constructor(name:String):this(5)//次构造
}
//使用的时候不需要new关键字
fun main() {
    Test(0)
}

上面这种写法,转成java之后class 是用final修饰的,所以不能被继承,但是我想写一个父类怎么办呢,class前面用open修饰,这个类就可以被继承了,就去掉了final关键字

open class Test(val age:Int) {//主构造的写法
constructor():this(5)//次构造       次构造 必须调用主构造
    constructor(name:String):this(5)//次构造

}

6.2、属性默认值

在Java中所有的属性值是可以有默认值的,默认为null,是没有什么问题的,但是Kotlini中,如果不给属性赋值,就会报错 解决办法

  • ?=允许为空自己去补救
  • 自己赋予初始值皆大欢喜
  • 用懒加载 lateinit修饰
  	val number=0;
    var id:String ?= null
    lateinit  var url:String//懒加载的时候用的时候一定要初始化,否则会空指针异常

6.3、抽象类和接口

抽象类 和接口 和java的写法相似

interface ICallBack {
    fun onCallBack()
}
abstract class TestAbstract {
    abstract fun initView()
}
//继承和实现接口都使用:然后用逗号隔开,继承抽象类或者 open修饰的类的时候,要声明主构造
 class TestInterface: TestAbstract(),ICallBack{
     override fun initView() {
//         TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
     }

     override fun onCallBack() {
//         TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
     }

 }

6.4、数据Bean

JavaBean的写法,Kotlin中用dataclass代替了JavaBean,还生成了copy函数

data class UserBean(val userName:String,val password:String)

fun main() {
    var user=UserBean("aaa","bbbb")
    var (username,password)=user.copy()
    var (_,amszlk)=user.copy()//只想copypassword
    println("username:$username,password:$password")
    println(amszlk)
}

转成java的代码

public final class UserBean {
   @NotNull
   private final String userName;
   @NotNull
   private final String password;

   @NotNull
   public final String getUserName() {
      return this.userName;
   }

   @NotNull
   public final String getPassword() {
      return this.password;
   }

   public UserBean(@NotNull String userName, @NotNull String password) {
      Intrinsics.checkParameterIsNotNull(userName, "userName");
      Intrinsics.checkParameterIsNotNull(password, "password");
      super();
      this.userName = userName;
      this.password = password;
   }

   @NotNull
   public final String component1() {
      return this.userName;
   }

   @NotNull
   public final String component2() {
      return this.password;
   }

   @NotNull
   public final UserBean copy(@NotNull String userName, @NotNull String password) {
      Intrinsics.checkParameterIsNotNull(userName, "userName");
      Intrinsics.checkParameterIsNotNull(password, "password");
      return new UserBean(userName, password);
   }

   // $FF: synthetic method
   public static UserBean copy$default(UserBean var0, String var1, String var2, int var3, Object var4) {
      if ((var3 & 1) != 0) {
         var1 = var0.userName;
      }

      if ((var3 & 2) != 0) {
         var2 = var0.password;
      }

      return var0.copy(var1, var2);
   }

   @NotNull
   public String toString() {
      return "UserBean(userName=" + this.userName + ", password=" + this.password + ")";
   }

   public int hashCode() {
      String var10000 = this.userName;
      int var1 = (var10000 != null ? var10000.hashCode() : 0) * 31;
      String var10001 = this.password;
      return var1 + (var10001 != null ? var10001.hashCode() : 0);
   }

   public boolean equals(@Nullable Object var1) {
      if (this != var1) {
         if (var1 instanceof UserBean) {
            UserBean var2 = (UserBean)var1;
            if (Intrinsics.areEqual(this.userName, var2.userName) && Intrinsics.areEqual(this.password, var2.password)) {
               return true;
            }
         }

         return false;
      } else {
         return true;
      }
   }
}

6.5、Kotlin的Object和伴生对象companion object

Kotlin的単例模式Object类

object ObjectTest {
    fun showToast(){
    }
}
//调用
fun main() {
    ObjectTest.showToast()
}

转成Java之后的代码

public final class ObjectTest {
   public static final ObjectTest INSTANCE;

   public final void showToast() {
   }

   private ObjectTest() {
   }

   static {
      ObjectTest var0 = new ObjectTest();
      INSTANCE = var0;
   }
}

伴生对象companionobject,为了方便理解咱们先上代码

class CompanionObjectTest {
    companion object{
        val name="爱码士"
        fun show(){ 
        	name.length
        }
    }
}
//调用
fun main() {
    CompanionObjectTest.show()
}

转Java之后

public final class CompanionObjectTest {
   @NotNull
   private static final String name = "爱码士";
   public static final CompanionObjectTest.Companion Companion = new CompanionObjectTest.Companion((DefaultConstructorMarker)null);

   @Metadata(
      mv = {1, 1, 15},
      bv = {1, 0, 3},
      k = 1,
      d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0003\n\u0002\u0010\u0002\n\u0000\b\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u0006\u0010\u0007\u001a\u00020\bR\u0014\u0010\u0003\u001a\u00020\u0004X\u0086D¢\u0006\b\n\u0000\u001a\u0004\b\u0005\u0010\u0006¨\u0006\t"},
      d2 = {"Lsimple01/CompanionObjectTest$Companion;", "", "()V", "name", "", "getName", "()Ljava/lang/String;", "show", "", "kotlindemo"}
   )
   public static final class Companion {
      @NotNull
      public final String getName() {
         return CompanionObjectTest.name;
      }

      public final void show() {
        ((CompanionObjectTest.Companion)this).getName().length();
      }

      private Companion() {
      }

      // $FF: synthetic method
      public Companion(DefaultConstructorMarker $constructor_marker) {
         this();
      }
   }
}
	//调用
  public static final void main() {
      CompanionObjectTest.Companion.show();
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }

所谓的伴生对象,就是伴随着出生的对象,直接在类初始化的时候,这个伴生对象Companion 也跟着实例化了,并且将伴生对象的属性变成了此类的静态变量,调用方法的时候,也是类直接调用静态属性Companion,然后再调用show方法

kotlin的内部类

class Test {

    val I = "AAAA"

    // 这个不是一个内部类,所有拿不到外部类的成员
    // 嵌套类 = 可以在类的里面再写一个类,但是这个类不是内部类
    class Sub {
        fun show() {
            println()
        }
        class A {

            class B {


                class C {

                }

            }

        }

    }

    // 这个才是内部类,用inner修饰之后才是内部类
    inner class Sub2 {

        fun show() {
            println(I)
        }

    }

}



相关推荐

MySQL进阶五之自动读写分离mysql-proxy

自动读写分离目前,大量现网用户的业务场景中存在读多写少、业务负载无法预测等情况,在有大量读请求的应用场景下,单个实例可能无法承受读取压力,甚至会对业务产生影响。为了实现读取能力的弹性扩展,分担数据库压...

Postgres vs MySQL_vs2022连接mysql数据库

...

3分钟短文 | Laravel SQL筛选两个日期之间的记录,怎么写?

引言今天说一个细分的需求,在模型中,或者使用laravel提供的EloquentORM功能,构造查询语句时,返回位于两个指定的日期之间的条目。应该怎么写?本文通过几个例子,为大家梳理一下。学习时...

一文由浅入深带你完全掌握MySQL的锁机制原理与应用

本文将跟大家聊聊InnoDB的锁。本文比较长,包括一条SQL是如何加锁的,一些加锁规则、如何分析和解决死锁问题等内容,建议耐心读完,肯定对大家有帮助的。为什么需要加锁呢?...

验证Mysql中联合索引的最左匹配原则

后端面试中一定是必问mysql的,在以往的面试中好几个面试官都反馈我Mysql基础不行,今天来着重复习一下自己的弱点知识。在Mysql调优中索引优化又是非常重要的方法,不管公司的大小只要后端项目中用到...

MySQL索引解析(联合索引/最左前缀/覆盖索引/索引下推)

目录1.索引基础...

你会看 MySQL 的执行计划(EXPLAIN)吗?

SQL执行太慢怎么办?我们通常会使用EXPLAIN命令来查看SQL的执行计划,然后根据执行计划找出问题所在并进行优化。用法简介...

MySQL 从入门到精通(四)之索引结构

索引概述索引(index),是帮助MySQL高效获取数据的数据结构(有序),在数据之外,数据库系统还维护者满足特定查询算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构...

mysql总结——面试中最常问到的知识点

mysql作为开源数据库中的榜一大哥,一直是面试官们考察的重中之重。今天,我们来总结一下mysql的知识点,供大家复习参照,看完这些知识点,再加上一些边角细节,基本上能够应付大多mysql相关面试了(...

mysql总结——面试中最常问到的知识点(2)

首先我们回顾一下上篇内容,主要复习了索引,事务,锁,以及SQL优化的工具。本篇文章接着写后面的内容。性能优化索引优化,SQL中索引的相关优化主要有以下几个方面:最好是全匹配。如果是联合索引的话,遵循最...

MySQL基础全知全解!超详细无废话!轻松上手~

本期内容提醒:全篇2300+字,篇幅较长,可搭配饭菜一同“食”用,全篇无废话(除了这句),干货满满,可收藏供后期反复观看。注:MySQL中语法不区分大小写,本篇中...

深入剖析 MySQL 中的锁机制原理_mysql 锁详解

在互联网软件开发领域,MySQL作为一款广泛应用的关系型数据库管理系统,其锁机制在保障数据一致性和实现并发控制方面扮演着举足轻重的角色。对于互联网软件开发人员而言,深入理解MySQL的锁机制原理...

Java 与 MySQL 性能优化:MySQL分区表设计与性能优化全解析

引言在数据库管理领域,随着数据量的不断增长,如何高效地管理和操作数据成为了一个关键问题。MySQL分区表作为一种有效的数据管理技术,能够将大型表划分为多个更小、更易管理的分区,从而提升数据库的性能和可...

MySQL基础篇:DQL数据查询操作_mysql 查

一、基础查询DQL基础查询语法SELECT字段列表FROM表名列表WHERE条件列表GROUPBY分组字段列表HAVING分组后条件列表ORDERBY排序字段列表LIMIT...

MySql:索引的基本使用_mysql索引的使用和原理

一、索引基础概念1.什么是索引?索引是数据库表的特殊数据结构(通常是B+树),用于...