Kotlin学习之 ---- ? ?: !! 操作符的使用(Kotlin花式空判断)

目录

先抛出个结论:

? ?:的使用方法

? ?:结论:

!!的使用方法

!!总结:


先抛出个结论:

? 问号修饰,两种使用方式

  • ?放在类名后面修饰表示对象可空;
  • ?放在对象后修饰,则代表如果对象为空,则不执行后面的代码

?: 问号冒号修饰符

  • ?:放在对象后面,代表如果对象为空,执行 ?: 后面的代码

!! 叹号修饰符

  • !! 放在对象后面,表示即使对象为空我也要往下执行,可能会抛出空指针异常
  • //用于测试的对象返回器
    class ObjectReturner {
        var r : Boolean = false
        var obj : T? = null
        constructor(r : Boolean , obj: T){
            this.r = r
            this.obj = obj
        }
    
        fun getObjMethod() : T?{
            return obj.takeIf { r }    //如果r为true返回obj,如果r为false返回null
        }
    }
    
    data class Student(val name : String , val age : Int)

    ? ?:的使用方法

  • var obj4: Student? = ObjectReturner(false , stu1).getObjMethod()
    println("obj4.name = ${obj4?.name}")
    obj4.run {
        println(this)
    } ?: println("怎么返回空了呢")

    上面的方法,永远不会执行到 ?: 后面的语句因为getObjMethod()即使返回空也执行到了run方法,最终打印null。

    println("obj4.name = ${obj4?.name}")如果这里不加问号直接访问obj4的属性是编译不过的,因为obj4可能为null。

    而使用obj4.run可以不加问号是可以编译过的(无语了)

    分析这里的原因要看kotlin翻译成java后的代码

    obj4.run{println(this)}的反编译结果

  • Student obj4 = (Student)(new ObjectReturner(false, stu1)).getObjMethod();
    String var5 = "obj4.name = " + (obj4 != null ? obj4.getName() : null);    //看这里
    System.out.println(var5);    //这里是关键
    int var7 = false;
    System.out.println(obj4);

    obj4.run之所以不用加?就可以编译通过,就是因为翻译成java后obj4.run压根就没有使用obj4的任何方法或者属性。因为run方法也不是obj4的成员方法,所以可以正常编译通过,执行也不会报异常。

    obj4?.run{println(this)}的反编译结果

  • Student obj4 = (Student)(new ObjectReturner(false, stu1)).getObjMethod();
    String var5 = "obj4.name = " + (obj4 != null ? obj4.getName() : null);//看这里
    System.out.println(var5);
    if (obj4 != null) {//看这里 是 ? 翻译后的java代码
       int var7 = false;
       System.out.println(obj4);
    } else {    //看这里 是 ?: 翻译后的java代码
       var5 = "怎么返回空了呢";
       System.out.println(var5);
    }

    当加上了?以后调用run方法,翻译后的结果自动加上了 obj4 != null 的判断。

    ? ?:结论:

  • 我们在调用方法或者使用属性之前加上了?,翻译后的java代码其实就是一个if判断,而使用 ?:则翻译后的java代码其实就是加了一个else

!!的使用方法

如果一个对象是用 ? 修饰的,表示此对象可能为空,这时如果你在使用这个对象的时候必须在对象后面加上 "?" 或者 "!!"否则是编译不过的

  • 加上 "?" 上文已经介绍过了,java翻译后会自动加上if判断,如果为空则不执行。
  • 加上 "!!" 则表示你已经非常确定对象是不为空的,强制编译通过。但是如果最终对象是空的,则会抛出空指针异常
  • var obj4: Student? = ObjectReturner(false , stu1).getObjMethod()
    println("obj4.name = ${obj4!!.name}")

    翻译后的java代码:

  • Student obj4 = (Student)(new ObjectReturner(false, stu1)).getObjMethod();
    StringBuilder var11 = (new StringBuilder()).append("obj4.name = ");
    Intrinsics.checkNotNull(obj4);
    String var5 = var11.append(obj4.getName()).toString();

    !!总结:

    如果obj4为空,则checkNotNull会抛出空指针异常。

    加上 "!!" 则表示你已经非常确定对象是不为空的,强制编译通过。但是如果最终对象是空的,则会抛出空指针异常。!!必须慎用啊!!!!

你可能感兴趣的:(kotlin,kotlin,学习,开发语言)