Kotlin学习:基础语法姿势

最近在学习kotlin,随便总结一下知识点。有兴趣的同学可以好好看看哦,每一段都有代码示例!!!

一、基础知识

1、声明变量

fun main(){
    //变量
    var a:Int = 1;
    //常量
    val b:Int = 2;
}

这里a、b表示变量的名字,冒号后面表示变量的类型。用val表示常量。

fun main(){
    //不可为空的类型
    var str1:String = "aaa";
    //可以为空的类型
    var str2:String? = null;
    str1 = str2 
    str2 = str1
}

用?表示这个变量可以为null,如果不加表示不可为空,编译会报错。str1 = str2这个是无法通过编译的。

2、函数相关

fun printLen(str:String):String{
	printLn("$str")
	return str;
}

Kotlin中的函数可以不放在类里面,单独提出来。实际上编译后的字节码文件依然是放在一个类里面。printLn("$str")这个$符号,表示这个变量可以放在字符串里,我们就减少了字符串的拼接。

3、与java中的不同

(1)内部类

class Main{
   object Test {
       fun sayMessage(msg: String) {
           println(msg)
       }
   }
    fun main(){
        println(Test.sayMessage("aaa"))
    }
}

Test是一个匿名内部类,在java中,匿名内部类会被单独编译成一个class文件,在外部类的内部有一个单例的对象。

java:
    Test.INSTANCE.sayMessage("aaa")
kotlin:
    Test.sayMessage("aaa")

这其实也是kotlin创造单例对象的方法。

(2)字节码对象

class Main{
   object Test {
       fun sayMessage(msg: String) {
           println(msg)
       }
   }
    fun main(){
        getName(JavaBean::class.java)
        getName(KotlinBean::class)
    }
    fun getName(clazz:Class<JavaBean>){
        println(clazz.simpleName)
    }
    fun getName(clazz:KClass<KotlinBean>){
        println(clazz.simpleName)
    }
}

public class JavaBean {
}


class KotlinBean

在kotlin中获得java的字节码xx::class.java,对于kotlin本身的对象类型是KClass传入的是xx::class。

(3)解决关键字冲突

public class JavaBean {
    
    public static int in = 1;
}

class Main{
    fun main(){
        println(JavaBean.`in`)
    }
}

in 在java中声明为了变量,但是在Kotlin中确是关键字,所以呢,要用``来处理。同时``可以将不合法字符变成合法的,比如:fun `123`{}。

4、kotlin与java互调产生的问题

kotlin 没有封装类,调用java方法,只会执行基本数据类型方法

public interface TestInterface {

    void putNum(int num);

    void putNum(Integer num);
}

public class Impl  implements TestInterface{

    public static TestInterface test = new Impl();
    @Override
    public void putNum(int num) {
        System.out.println("int");
    }

    @Override
    public void putNum(Integer num) {
        System.out.println("Integer");
    }
}
fun main() {
    Impl.test.putNum(123);
}

打印输出的是int。这就是由于kotlin中没有Integer,所以把两个方法并为一个方法了,如果kotlin中实现接口,那么只需要重写一个方法就可以了。

kotlin 类型空值敏感

当kotlin调用java方法的时候,课程会返回一个null,如果我们不处理程序会有安全问题。

public class Temp {
    public static String format(String str){
        return str.isEmpty() ? null : str;
    }
}

fun main() {
    function("")
}
fun function(str:String){
    val fmt1 = Temp.format(str);
    println(fmt1)
    val fmt2:String = Temp.format(str);
    val fmt3:String? = Temp.format(str);
    println(fmt3?.length)

}

fmt2会直接在运行的时候报错,因为format方法返回的就是null值,fmt1是null。fmt3才是安全的所以要用?设置成可控类型的,这样才是安全的。

kotlin 中没有静态变量和静态方法

在java中调用kotlin方法

class StaticDemo{

    object Test{
        fun sayMessage(msg:String){
            println(msg)
        }
    }
}
public class Main1 {
    public static void main(String[] args) {
        StaticDemo.Test.INSTANCE.sayMessage("aaa");
    }
}

那我们能不能在java中像调用静态方法一样方便呢?就是把INSTANCE去掉?答案是可以的

class StaticDemo{

    object Test{

        @JvmStatic
        fun sayMessage(msg:String){
            println(msg)
        }
    }
}

public class Main1 {
    public static void main(String[] args) {
        StaticDemo.Test.sayMessage("aaa");
    }
}

5、判断相等

kotlin             java
a == b             a.equals(b)
a === b            a == b

二、函数和Lambda闭包

1、函数的特性语法

//标准写法
fun echo(name:String){
    println("name:$name")
}
//携带默认参数
fun echo(name:String = "xiaoming"){
    println("name:$name")
}
//简易写法,函数中只有一个语句可以搞
fun echo(name:String) = println("name:$name")

默认参数,在java中调用也需要传参数,在kotlin中不用

2、嵌套函数

fun main() {
    function()
}
fun function(){
    var str ="hello world"
    fun say(count:Int = 10){
        println(str)
        if(count > 0){
            say(count - 1)
        }
    }
    say()
}

用途:(1)在某些条件下,触发递归函数(2)不希望被外部函数访问的函数

!!!不推荐使用

3、扩展函数

class Main{

}
fun Main.aaa() = print("aaa")
fun main() {
    Main().aaa();
}

对一个类的方法进行扩展,类名+ . +方法名。在编译的时候会编译到类里面。

扩展函数是静态的,不具备运行时的多态!

一般应用于第三方的sdk或者系统类。

4、Lambda闭包语法

lambda:

//java8中
 public static void main(String[] args) {
        Thread thread = new Thread(() -> System.out.println("aaa"));
 }
//kotlin中
fun main() {
    var thread = Thread({ -> println("aaaa")})
    thread.start()
}

如果lambda是没有参数的可以更加简化一点:

 var thread1 = Thread({ })
 var thread2 = Thread(){}
 var thread3 = Thread{}

闭包语法:

//lambda闭包
var print = {
    name:String ->  println("name:$name")
}
fun main() {
   print("aaa")
}

最多传入22个参数

5、高阶函数

将函数作为参数传递给另一个函数...。

fun onlyIf(isDebug:Boolean,block:() -> Unit){
    if(isDebug) block();
}
fun main() {
   onlyIf(true){
       println("打印日志")
   }
}
fun onlyIf(isDebug:Boolean,block:() -> Unit){
    if(isDebug) block();
}
fun main() {
    val runnable:Runnable = Runnable {
        print("runnable::run")
    }
    var funn:() -> Unit
    funn = runnable::run
    onlyIf(true,funn)
}

这里面首先创建了一个对象Runnable。然后有一个lambda函数声明,利用::将对象中方法拿出来,赋值给funn,然后再调用。

6、内联函数

inline fun onlyIf(isDebug:Boolean,block:() -> Unit){
    if(isDebug) block();
}
fun main() {
    val runnable:Runnable = Runnable {
        print("runnable::run")
    }
    var funn:() -> Unit 
    funn = runnable::run
    onlyIf(true,funn)
}

kotlin的Lambda是一个匿名对象。可以使用inline修饰方法,在编译的时候会拆解方法的调用为语句调用,进而减少创建不必要的对象。

三、类和对象

1、构造函数

open class Father{

}

class Son:Father(){

}

kotlin类中默认有public final修饰符,默认不允许继承,如果想要继承,必须要用open修饰。继承用:,可以继承一个父类或者多个接口。

open class Father(var num:Int){
    init {
        print("father")
    }
    open fun printClass():Unit{
        println("printClass")
    }
}
open interface FatherInterface{
    fun printInterface()
}

class Son(var a:Int):Father(a),FatherInterface{
    override fun printInterface() {
    }
    
    override fun printClass(){
    }
}

这里面类名后面的()就是构造函数。如果想要在构造函数中执行某些逻辑就写在init方法。override表示重写方法。

多级构造函数

class Test(str:String){
    var str:String = str;
    var num:Int = 0;
    var doub:Double = 0.0;

    constructor(str:String,num:Int):this(str){
        this.num = num;
    } 
    constructor(str:String,num:Int,doub:Double):this(str,num){
        this.doub = doub;
    }
}

利用constructor声明多级构造函数,this()表示调用主构造函数。次级构造函数必须调用主构造函数。

2、访问修饰符

//前三个跟java的一样
private
protected
public
//这个指在模块内能够访问,例如module
internal

3、伴生对象

class StringUtils{

    companion object {
        fun isEmpty(str:String):Boolean{
            return "" == str
        }
    }
}

fun main() {
    println(StringUtils.isEmpty(""))
    println(StringUtils.isEmpty("aa"))
}

有点像java静态方法,跟我们上面说的@JvmStatic注解有点像,在编译的时候为我们创建了一个静态内部对象。

4、单例类

class Single constructor(){
    companion object {
        fun get():Single{
            return Holder.instance
        }
    }
    private object Holder{
        var instance = Single();
    }
}

 

5、类的动态代理

interface Animal{
    fun bark();
}

class Dog:Animal{
    override fun bark() {
        println("wang")
    }
}
class Zoo(animal: Animal):Animal by animal

fun main() {
    Zoo(Dog()).bark()
}

输出wang,如果重写了bark方法,就不会代理了。kotlin中编译的时候用的是静态代理,要比java中的效率高。

6、kotlin特有的类

数据类:

data class User(var id:Long,var name:String)

自动提供toString、equal、hashcode、getter、setter方法。并且类是final。

枚举类:

enum class Command{
    A,B,C,D
}
//下面相当于switch去匹配
fun exec(command: Command) = when (command){
    Command.A -> {}
    Command.B -> {}
    Command.C -> {}
    Command.D -> {}
}

超级枚举:密闭类:

sealed class SuperCommand{
    object A:SuperCommand()
    object B:SuperCommand()
    object C:SuperCommand()
    object D:SuperCommand()
}

fun exec(command: SuperCommand) = when (command){
    SuperCommand.A -> {}
    SuperCommand.B -> {}
    SuperCommand.C -> {}
    SuperCommand.D -> {}
}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值