我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Kotlin构造函数、成员变量和init代码块执行顺序实例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Kotlin构造函数、成员变量和init代码块执行顺序实例分析

本文小编为大家详细介绍“Kotlin构造函数、成员变量和init代码块执行顺序实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“Kotlin构造函数、成员变量和init代码块执行顺序实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

从Java语法的角度分析了Kotlin构造函数、成员变量初始化、init代码块三者的执行顺序:

Kotlin构造函数与成员变量和init代码块执行顺序详细讲解

这次再从字节码的角度分析它们的执行顺序。

还是用之前那个例子:

class InitOrderDemo(name: String) {    val firstProperty = "First property: $name".also(::println)    init {        println("First initializer block that prints ${name}")    }    val secondProperty = "Second property: ${name.length}".also(::println)    init {        println("Second initializer block that prints ${name.length}")    }}

调用InitOrderDemo(“hello”)打印的结果如下:

First property: hello
First initializer block that prints hello
Second property: 5
Second initializer block that prints 5

可以看到执行顺序,是按照它们声明的顺序执行。

将上面Koltin代码转成字节码之后,显示内容如下:

// ================com/devnn/javalib/InitOrderDemo.class =================// class version 52.0 (52)// access flags 0x31public final class com/devnn/javalib/InitOrderDemo {  // access flags 0x12  private final Ljava/lang/String; firstProperty  @Lorg/jetbrains/annotations/NotNull;() // invisible  // access flags 0x11  public final getFirstProperty()Ljava/lang/String;  @Lorg/jetbrains/annotations/NotNull;() // invisible   L0    LINENUMBER 4 L0    ALOAD 0    GETFIELD com/devnn/javalib/InitOrderDemo.firstProperty : Ljava/lang/String;    ARETURN   L1    LOCALVARIABLE this Lcom/devnn/javalib/InitOrderDemo; L0 L1 0    MAXSTACK = 1    MAXLOCALS = 1  // access flags 0x12  private final Ljava/lang/String; secondProperty  @Lorg/jetbrains/annotations/NotNull;() // invisible  // access flags 0x11  public final getSecondProperty()Ljava/lang/String;  @Lorg/jetbrains/annotations/NotNull;() // invisible   L0    LINENUMBER 10 L0    ALOAD 0    GETFIELD com/devnn/javalib/InitOrderDemo.secondProperty : Ljava/lang/String;    ARETURN   L1    LOCALVARIABLE this Lcom/devnn/javalib/InitOrderDemo; L0 L1 0    MAXSTACK = 1    MAXLOCALS = 1  // access flags 0x1  public <init>(Ljava/lang/String;)V    // annotable parameter count: 1 (visible)    // annotable parameter count: 1 (invisible)    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0   L0    ALOAD 1    LDC "name"    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkNotNullParameter (Ljava/lang/Object;Ljava/lang/String;)V   L1    LINENUMBER 3 L1    ALOAD 0    INVOKESPECIAL java/lang/Object.<init> ()V   L2    LINENUMBER 4 L2    ALOAD 0    NEW java/lang/StringBuilder    DUP    INVOKESPECIAL java/lang/StringBuilder.<init> ()V    LDC "First property: "    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    ALOAD 1    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;    ASTORE 2   L3    ALOAD 2    ASTORE 3   L4    LINENUMBER 17 L4    ASTORE 5   L5    ICONST_0    ISTORE 4   L6    LINENUMBER 4 L6   L7    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;    ALOAD 3    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V   L8   L9   L10    GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;    ASTORE 6    ALOAD 5   L11    LINENUMBER 4 L11   L12    ALOAD 2   L13    PUTFIELD com/devnn/javalib/InitOrderDemo.firstProperty : Ljava/lang/String;   L14    LINENUMBER 6 L14    NOP   L15    LINENUMBER 7 L15    NEW java/lang/StringBuilder    DUP    INVOKESPECIAL java/lang/StringBuilder.<init> ()V    LDC "First initializer block that prints "    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    ALOAD 1    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;    ASTORE 2   L16    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;    ALOAD 2    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V   L17   L18    LINENUMBER 8 L18    NOP   L19    LINENUMBER 10 L19    ALOAD 0    NEW java/lang/StringBuilder    DUP    INVOKESPECIAL java/lang/StringBuilder.<init> ()V    LDC "Second property: "    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    ALOAD 1    INVOKEVIRTUAL java/lang/String.length ()I    INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder;    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;    ASTORE 2   L20    ALOAD 2    ASTORE 3   L21    LINENUMBER 17 L21    ASTORE 5   L22    ICONST_0    ISTORE 4   L23    LINENUMBER 10 L23   L24    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;    ALOAD 3    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V   L25   L26   L27    GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;    ASTORE 6    ALOAD 5   L28    LINENUMBER 10 L28   L29    ALOAD 2   L30    PUTFIELD com/devnn/javalib/InitOrderDemo.secondProperty : Ljava/lang/String;   L31    LINENUMBER 12 L31    NOP   L32    LINENUMBER 13 L32    NEW java/lang/StringBuilder    DUP    INVOKESPECIAL java/lang/StringBuilder.<init> ()V    LDC "Second initializer block that prints "    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    ALOAD 1    INVOKEVIRTUAL java/lang/String.length ()I    INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder;    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;    ASTORE 2   L33    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;    ALOAD 2    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V   L34   L35    LINENUMBER 14 L35    RETURN   L36    LOCALVARIABLE p1 Ljava/lang/Object; L5 L10 3    LOCALVARIABLE $i$a$-unknown-InitOrderDemo$firstProperty$1 I L6 L10 4    LOCALVARIABLE p1 Ljava/lang/Object; L22 L27 3    LOCALVARIABLE $i$a$-unknown-InitOrderDemo$secondProperty$1 I L23 L27 4    LOCALVARIABLE this Lcom/devnn/javalib/InitOrderDemo; L0 L36 0    LOCALVARIABLE name Ljava/lang/String; L0 L36 1    MAXSTACK = 3    MAXLOCALS = 7}

可以看到上面的构造函数、成员变量初始化和init代码块,按照声明都被放到了字节码的init代码块中了。

字节码的init初始化器其实就是类的构造函数。将Java代码转成字节码也是存在init构造函数。

下面看一个Java示例,加深对字节码的init初始化块的认识。

package com.devnn.javalib;public class JavaInit {    String firstName = "Steven";    {        System.out.println("This is init block");    }    JavaInit(String secondName) {        System.out.println("firstName=" + firstName);        System.out.println("secondName=" + secondName);    }    public static void main(String[] args) {        new JavaInit("Jobs");    }}

运行main函数打印结果如下:

This is init block
firstName=Steven
secondName=Jobs

将上面的JavaInit类转成字节码之后的内容如下:

// class version 51.0 (51)// access flags 0x21public class com/devnn/javalib/JavaInit {  // compiled from: JavaInit.java  // access flags 0x0  Ljava/lang/String; firstName  // access flags 0x0  <init>(Ljava/lang/String;)V   L0    LINENUMBER 10 L0    ALOAD 0    INVOKESPECIAL java/lang/Object.<init> ()V   L1    LINENUMBER 4 L1    ALOAD 0    LDC "Steven"    PUTFIELD com/devnn/javalib/JavaInit.firstName : Ljava/lang/String;   L2    LINENUMBER 7 L2    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;    LDC "This is init block"    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V   L3    LINENUMBER 11 L3    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;    NEW java/lang/StringBuilder    DUP    INVOKESPECIAL java/lang/StringBuilder.<init> ()V    LDC "firstName="    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    ALOAD 0    GETFIELD com/devnn/javalib/JavaInit.firstName : Ljava/lang/String;    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V   L4    LINENUMBER 12 L4    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;    NEW java/lang/StringBuilder    DUP    INVOKESPECIAL java/lang/StringBuilder.<init> ()V    LDC "secondName="    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    ALOAD 1    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V   L5    LINENUMBER 13 L5    RETURN   L6    LOCALVARIABLE this Lcom/devnn/javalib/JavaInit; L0 L6 0    LOCALVARIABLE secondName Ljava/lang/String; L0 L6 1    MAXSTACK = 3    MAXLOCALS = 2  // access flags 0x9  public static main([Ljava/lang/String;)V   L0    LINENUMBER 16 L0    NEW com/devnn/javalib/JavaInit    DUP    LDC "Jobs"    INVOKESPECIAL com/devnn/javalib/JavaInit.<init> (Ljava/lang/String;)V    POP   L1    LINENUMBER 17 L1    RETURN   L2    LOCALVARIABLE args [Ljava/lang/String; L0 L2 0    MAXSTACK = 3    MAXLOCALS = 1}

可见,Java类的成员变量初始化、构造函数、构造块同样都被拷贝进了init代码块中。那么它们是否存在顺序问题呢?

将上面JavaInit类的firname成员变量放到初始化块下面试试:

package com.devnn.javalib;public class JavaInit {    {        System.out.println("This is init block");    }    JavaInit(String secondName) {        System.out.println("firstName=" + firstName);        System.out.println("secondName=" + secondName);    }    String firstName = "Steven";    public static void main(String[] args) {        new JavaInit("Jobs");    }}

查看字节码:

// class version 51.0 (51)// access flags 0x21public class com/devnn/javalib/JavaInit {  // compiled from: JavaInit.java  // access flags 0x0  Ljava/lang/String; firstName  // access flags 0x0  <init>(Ljava/lang/String;)V   L0    LINENUMBER 8 L0    ALOAD 0    INVOKESPECIAL java/lang/Object.<init> ()V   L1    LINENUMBER 5 L1    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;    LDC "This is init block"    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V   L2    LINENUMBER 13 L2    ALOAD 0    LDC "Steven"    PUTFIELD com/devnn/javalib/JavaInit.firstName : Ljava/lang/String;   L3    LINENUMBER 9 L3    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;    NEW java/lang/StringBuilder    DUP    INVOKESPECIAL java/lang/StringBuilder.<init> ()V    LDC "firstName="    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    ALOAD 0    GETFIELD com/devnn/javalib/JavaInit.firstName : Ljava/lang/String;    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V   L4    LINENUMBER 10 L4    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;    NEW java/lang/StringBuilder    DUP    INVOKESPECIAL java/lang/StringBuilder.<init> ()V    LDC "secondName="    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    ALOAD 1    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V   L5    LINENUMBER 11 L5    RETURN   L6    LOCALVARIABLE this Lcom/devnn/javalib/JavaInit; L0 L6 0    LOCALVARIABLE secondName Ljava/lang/String; L0 L6 1    MAXSTACK = 3    MAXLOCALS = 2  // access flags 0x9  public static main([Ljava/lang/String;)V   L0    LINENUMBER 17 L0    NEW com/devnn/javalib/JavaInit    DUP    LDC "Jobs"    INVOKESPECIAL com/devnn/javalib/JavaInit.<init> (Ljava/lang/String;)V    POP   L1    LINENUMBER 18 L1    RETURN   L2    LOCALVARIABLE args [Ljava/lang/String; L0 L2 0    MAXSTACK = 3    MAXLOCALS = 1}

可见,Java类的成员变量初始化、构造函数、构造块同样都被拷贝进了字节码init代码块中。Java的成员变量初始化和构造块也是按声明顺序执行。不同的是,Java的构造函数代码始终放在了字节码init代码块的后面。

字节码的init初始化块,其实就是类的真正的构造函数。Kotlin多个init代码块都是按照顺序拷贝进了字节码的init初始化块中,可以理解为它们是构造函数的组成部分。

Java和kotlin成员变量的初始化都是放到字节码的init代码块中,也就是在构造函数中执行的。

读到这里,这篇“Kotlin构造函数、成员变量和init代码块执行顺序实例分析”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Kotlin构造函数、成员变量和init代码块执行顺序实例分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Kotlin构造函数、成员变量和init代码块执行顺序实例分析

本文小编为大家详细介绍“Kotlin构造函数、成员变量和init代码块执行顺序实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“Kotlin构造函数、成员变量和init代码块执行顺序实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路
2023-07-04

Kotlin构造函数、成员变量和init代码块执行顺序是什么

今天小编给大家分享一下Kotlin构造函数、成员变量和init代码块执行顺序是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下
2023-07-04

Kotlin构造函数与成员变量和init代码块执行顺序详细讲解

这篇文章主要介绍了Kotlin构造函数与成员变量和init代码块执行顺序,kotlin里面的构造函数分为主构造函数和次构造函数。主构造函数只能有一个,次构造函数个数不限制,可以有一个或者多个
2022-11-16

Kotlin字节码层探究构造函数与成员变量和init代码块执行顺序

这篇文章主要介绍了字节码层Kotlin构造函数与成员变量和init代码块执行顺序,kotlin里面的构造函数分为主构造函数和次构造函数。主构造函数只能有一个,次构造函数个数不限制,可以有一个或者多个
2022-11-16

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录