Kotlin伴生对象及其字节码内幕详解
继续面向对象,开撸就是!!
接口:
我们知道对于JDK8之后接口中除了方法的声明之后还可以有default方法的,而在Kotlin中也类似,下面来看一下在Kotlin接口相关的东东:

很显然就是一个方法的声明,接着:

这是方法的具体实现,跟JDK8中的默认方法差不多,只不过在Koltin中的接口中定义具体方法之前不需要用default关键字来声明而已,下面在里面打印一句话:

接下来咱们可以在实现类中来复写接口中实现的方法,如下:

接下来问题来了:既然一个类既可以实现一个接口,又能继承一个类,那如果都定义的是同一个方法,那子类覆写的到底是接口中的方法还是类中的方法呢?下面来试一下:


所以:

接下来提个需求,在C中重写方法中需要融合接口A和类B方法的功能该怎么办呢?如下:

抽象类:
它跟Java类似,所以说明一上语法既可,如下:

伴生对象【companion object】:
在这是Kotlin的新概念,主要也是为了解决某个问题而存在的,具体解决啥问题先不说,因为需要有一些前置的概念先要了解,“object declaration 对象声明”,具体怎么定定义呢?

这就声明了一个对象,而在对象里面也可以像类一样声明属性和方法,如下:

那如何调用它呢?既然已经是对象了,那不直接用.的方式去调用就行了?是的~~不用像class那样还得先生成实例再调用之,如下:

其实有点像JavaScript,任何皆对象。好,学它的目的是为了要学习“伴生对象”而做准备,在Java中是完全没这个概念的,但是!!在像Scala这样的语言也是存在的,那啥叫“伴生对象”呢?其实得从Java的static说起, 我们知道被static修饰的成员变量或者方法是用Class直接去调用的,那是不是跟我们说的定义的对象有点类似,在Kotlin中,与java不同的是,类是没有static方法的,那么问题来了,那在Kotlin中如何表达static的这种作用呢?其实是这样:在大多数情况下,Kotlin推荐的做法是使用包级别的函数来作为静态方法,Kotlin会将包级别的函数当做静态方法来看待。那问题又来了,说的这个包级别的函数跟咱们已经学习的对象声明和既将要学习的伴生对象又有何关系呢?所谓“伴生”其实就是存在于类中的一个对象,它是随类一起伴生的,讲了这么多下面来瞅下它的真面目:

然后在伴生对象里面定义的东东跟在类中定义的差不多,如下:

那这个伴生对象如何使用呢?如下:

直接可以通过类来访问伴生对象里面的方法,但是!!貌似跟java中的static还是没联系上呀,下面再来演变:


这就是伴生对象所起到的作用,可以达到java中的static的效果。
接下来再来脑洞一个情况:假如一个类中有多个伴生对象,而且伴生对象中有相同的方法,那我们直接用类去访问这个方法调的是哪个伴生对象中的方法呢?其实Kotlin已经为我们杜绝了这种可能性,也就是一个类只能有一个伴生对象,不信咱们试试:

另外还有一个细节,就是伴生对象的名字其实是可以省略掉的:

其中报错的需要这样改就不会报错了:

所以“如果不提供伴生对象的名字,那么编译器会提供一个默认的名字叫Companion”,下面咱们还是将伴生对象名称还原:

至此对于Kotlin的伴生对象的使用就已经学完了,但是!!还是有个疑问:它怎么就能实现static的效果呢?编译生成的字节码中是不是真正给加上一个static的关键字呢?好!!接下来就开始对它进行揭密:先来将这个伴生对象给打印一下,看它倒底是啥?

所以需要注意:“虽然伴生对象的成员看起来像是Java中的静态成员,但是在运行期,他们依旧是真实对象的实例成员【因为属于伴生内部对象中的方法,伴生对象在编译后会生成一个静态内部类】”,但是在JVM上,可以将伴生对象的成员真正生成为类的静态方法与属性,这是通过@JvmStatic注解来实现的,如下:

那说是这么说,如何来验证所说的观点呢?其实很简单,查看一下所生成的字节码就知晓了,所以下面来正式探究原理,先来查看一下当前生成类的字节信息,咱们先来看不加@JvmStatic注解的字体码情况:


进一步查看字节信息:

这也论证了“虽然伴生对象的成员看起来像是Java中的静态成员,但是在运行期,他们依旧是真实对象的实例成员【因为属于伴生内部对象中的方法,伴生对象在编译后会生成一个静态内部类】”,好,接下来加上@JvmStatic注解,再来看一下字节码的情况:


真正成为了Mytest中的静态方法了,这也就是这个注解的作用,下面来看一下该注解的说明:

再来看一下详细的字节情况:

接下来为了更加清晰的了解,再定义一个类,再查看一下它的字节码信息:


下面调用一下:

所以说,了解一定的Java字节码的知识有助于了解底层~~
Kotlin伴生对象及其字节码内幕详解的更多相关文章
- Java Class 字节码文件结构详解
Class字节码中有两种数据类型: 字节数据直接量:这是基本的数据类型.共细分为u1.u2.u4.u8四种,分别代表连续的1个字节.2个字节.4个字节.8个字节组成的整体数据. 表:表是由多个基本数据 ...
- [转]C语言字节对齐问题详解
C语言字节对齐问题详解 转载:https://www.cnblogs.com/clover-toeic/p/3853132.html 引言 考虑下面的结构体定义: typedef struct{ ch ...
- Hadoop3.1.1源码Client详解 : 写入准备-RPC调用与流的建立
该系列总览: Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览 关于RPC(Remote Procedure Call),如果没有概念,可以参考一下RMI(Remot ...
- Hadoop3.1.1源码Client详解 : 入队前数据写入
该系列总览: Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览 紧接着上一篇: Hadoop3.1.1源码Client详解 : 写入准备-RPC调用与流的建立 先给出 ...
- NopCommerce源码架构详解--初识高性能的开源商城系统cms
很多人都说通过阅读.学习大神们高质量的代码是提高自己技术能力最快的方式之一.我觉得通过阅读NopCommerce的源码,可以从中学习很多企业系统.软件开发的规范和一些新的技术.技巧,可以快速地提高我们 ...
- HTTP 状态响应码 意思详解/大全
HTTP 状态响应码 意思详解/大全 转:http://blog.csdn.net/helin916012530/article/details/29842595 HTTP状态码(HTTP Statu ...
- NopCommerce源码架构详解
NopCommerce源码架构详解--初识高性能的开源商城系统cms 很多人都说通过阅读.学习大神们高质量的代码是提高自己技术能力最快的方式之一.我觉得通过阅读NopCommerce的源码,可以从 ...
- Nop--NopCommerce源码架构详解专题目录
最近在研究外国优秀的ASP.NET mvc电子商务网站系统NopCommerce源码架构.这个系统无论是代码组织结构.思想及分层都值得我们学习.对于没有一定开发经验的人要完全搞懂这个源码还是有一定的难 ...
- Hadoop3.1.1源码Client详解 : Packet入队后消息系统运作之ResponseProcessor(ACK接收)
该系列总览: Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览 紧接着上一篇文章: Hadoop3.1.1源码Client详解 : Packet入队后消息系统运作之D ...
随机推荐
- [LeetCode] 267. Palindrome Permutation II 回文全排列 II
Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empt ...
- [LeetCode] 875. Koko Eating Bananas 可可吃香蕉
Koko loves to eat bananas. There are N piles of bananas, the i-th pile has piles[i] bananas. The g ...
- python使用consul进行服务注册和发现
阅读目录 一.安装启动consul 二.python服务注册 三.golang服务注册 四.通过API的方式获取信息 回到顶部 一.安装启动consul 1.通过docker快速安装 #获取docke ...
- 带CheckBox美化控件的表格全选
带CheckBox美化控件 <table class="positionTable commonListTable" id="positionTable" ...
- ubuntu sh脚本激活conda 虚拟环境
第一步:初始化coda 命令:sudo gedit ~/.bashrc 第二部:复制其中这样一段代码 # >>> conda initialize >>> # !! ...
- Delphi Sysem.JSON 链式写法
链式写法有很多优点:连贯.语意集中.简洁.一气呵成.可读性强.比如要把 3.1415926 中的 59 提取为一个整数:Pi.ToString().Substring(5,2).ToInteger() ...
- Django组件之auth
一.什么是Auth模块 Auth模块是Django自带的用户认证模块,默认使用 auth_user 表来存储用户数据. 二.使用方法 1.创建超级用户 python3 manage.py create ...
- ARM中断深入分析几点
ARM中断深入分析几点 1.程序发生中断后,是如何跳转到中断程序里面的? 2.执行完中断后,如何返回到原来被打断的地方接着执行呢? 3.ARM处理器的流水线结构对中断返回地址的计算有什么影响? 4.A ...
- 原子类 Atomic
@Testpublic void testAtomicBoolean() { AtomicBoolean atomicBoolean = new AtomicBoolean(); boolean b ...
- DevOps 什么是 CI/CD?
CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法.CI/CD 的核心概念是持续集成.持续交付和持续部署.作为一个面向开发和运营团队的解决方案,CI/CD 主要针对在集成新代码时 ...