kotlin基础教程:<8>类的延时成员变量、初始化代码块和陷阱

之前我们讲到了类,怎么创建类,实例化类,类构造函数拥有两种,一种是主要构造函数,另一种是次要构造函数,次构造函数为了方便管理都需要调用一下主构造函数;

那么这一期我们来讲成员变量的延时;我们用到的一个关键字叫lateinit,它是用来延时实例化一个成员变量的时间用的,一般会延时到使用时实例化,当然还有一种是饿汉式:by lazy的组合使用来实现自动化的延时成员变量的实例化时;而且对于kotlin来说不想Java的代码对顺序那么灵活,一旦代码位置错了,就可能出现空指针:

1、加载类时的执行顺序

当我们调用次构造函数使用类时,类里面的成员、构造函数和init代码块是怎样的一个执行顺序呢?

我们知道,执行次构造函数必然需要调用主构造函数,而主构造函数有需要将成员全都初始化好,所以会先执行一气呵成的参数,就是带有val等参数类型的参数,然后执行init和其他的参数初始化,注意参数和init之间的先后顺序看你先写哪一个就限制性,所以我们可以说这些成员参数的执行和init代码块是并行执行的:

 public Tony2(@NotNull String _name, int age, @NotNull String info) {
      Intrinsics.checkNotNullParameter(_name, "_name");
      Intrinsics.checkNotNullParameter(info, "info");
      super();
      this.age = age;
      this.info = info;
      this.name = _name;
      String var4 = "我是init代码块:" + _name;
      System.out.println(var4);
      this.age1 = this.age;
   }

从反编译的Java代码可以看到,这个类调用次构造初始化时限制性了主构造,然后在里面执行了一气呵成的参数age和info,再就是先写的init代码块,最后是最后写的age,最最后执行次构造函数;

 //3.1 设置类构造函数的默认值    /*    * 因为有了默认值,于是我们可以不传参数,但是不传参是调用的是次构造还是    * 主构造呢?答案是主构造优先    * */    Tony3()    //3.2 初始化代码块    Tony2("Tony",4,"在学习kotlin")    Tony3("",4,22)

2、延时初始化成员,有时候我们想要我们的成员变量只有当用到的时候进行初始化,这里就可以使用延时成员变量的操作,含有两种,一种手动的延时,一种是自动的延时,也叫作懒汉式初始化变量:

 //4.1 声明一个延时初始化的成员,不需要赋值
    lateinit var info: String
    //定义一个函数来对成员赋值
    fun getrequest(){
        info = "Tony"
    }
    //打印结果
    fun showresult(){
        //注意这个isInitialized函数只能用在手动的演示初始化里面
        if(::info.isInitialized){
            println("初始化成功:${info}")
        }else{
            println("未被初始化")
        }
    }

主要步骤就是先定义好一个成员变量,注意要是用lateinit关键字表示是延时变量,然后定义一个函数用来给成员赋值,最后是使用这个变量;

第二种自动延时初始化是使用了by lazy:

 //4.2 还可以是by lazy的方式来自动延时初始化
    val info2: String by  lazy {
        getrequest2()
    }
    fun getrequest2(): String{
        return "jerry"
    }
    fun showresult2(){
        println("自动延时初始化:${info2}")
    }

我们在lazy的括号里调用这个赋值函数即可:

    //3.4 自动懒加载(by lazy)和懒加载(手动)
    Tony3().getrequest()
    Tony3().showresult()
    //4.3 使用自动延时初始化,我们就不需要手动调用函数,我们用到时它自己会调用
    Tony3().showresult2()

3、类的陷阱

以为kotlin是严格按照代码生成顺序执行的,所以大家务必对顺序需要了解:

//5.1 在类加载里面的陷阱
    /*
    * 当然,说是陷阱,其实只是对于我们学习了Java的人来说容易犯的错,就是Java对
    * 代码的生成顺序是很灵活的,一般不会有顺序问题,但是kotlin不一样,它严格要求
    * 代码的顺序,如果没有按照顺序写代码,可能非常容易会有空指针异常的问题
    *
    * */
    Tony4("Tony").getinfo()

有时候我们可能会写一个成员是一个函数的返回值,而这个函数的返回值又是一个成员变量的值,不过这个变量是在调用函数的成员变量之后,那么我们会拿到一个null值。因为在他没有实例化的时候调用了它:

class Tony4(_info: String){
    //5.2 试一试不按照顺序的效果
    fun getinfo(){
        println("你传入的字符串长度:"+info.length)
        println("乘法结果:${number}")
        println("取值结果:${info1}")
    }
    //结果我们拿到的info1是一个null,这是因为顺序,info在info1的后面生成
    var info1 = getmethods()
    val info = _info
    //所以当我们调用获取info的值的函数时,info还没有赋值,所以为null
    fun getmethods() = "我拿到了${info}"
    var number = 9
    init {
        number = number.times(9)
    }
}

总之,kotlin当中的代码时严格按照代码顺序来执行,所以我们需要格外注意;那么这一期就到这。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程学渣ズ

谢谢老板

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值