Kotlin和Java 单例模式

Java 和Kotlin的单例模式其实很像,只是Kotlin一部分单例可以用对象类和委托lazy来实现

Java

/*** 懒汉式,线程不安全*/
class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}/*** 懒汉式,线程安全*/
class Singleton1 {private static Singleton1 instance;private Singleton1() {}public static synchronized Singleton1 getInstance() {if (instance == null) {instance = new Singleton1();}return instance;}
}/*** 饿汉式*/
class Singleton2 {private static Singleton2 instance = new Singleton2();private Singleton2() {}public static Singleton2 getInstance() {return instance;}
}/*** 双检锁/双重校验锁(DCL,即 double-checked locking)*/
class Singleton3 {private volatile static Singleton3 singleton;private Singleton3() {}public static Singleton3 getSingleton() {if (singleton == null) {synchronized (Singleton3.class) {if (singleton == null) {singleton = new Singleton3();}}}return singleton;}
}/*** 登记式/静态内部类*/
class Singleton4 {private static class SingletonHolder {private static final Singleton4 INSTANCE = new Singleton4();}private Singleton4() {}public static final Singleton4 getInstance() {return SingletonHolder.INSTANCE;}
}/*** 枚举*/
enum Singleton5 {INSTANCE2;public void whateverMethod() {System.out.println("....");}
}

Kotlin

/*** 懒汉式,线程不安全,仿Java*/
internal class Singleton6 private constructor() {companion object {private var instance: Singleton6? = nullfun getInstance(): Singleton6 {if (instance == null) {instance = Singleton6()}return instance!!}}
}/*** 懒汉式,线程不安全*/
internal class Singleton7 private constructor() {companion object {var instance: Singleton7? = nullget() {if (field == null) {field = Singleton7()}return field}}
}/*** 懒汉式,线程安全*/
internal class Singleton8 private constructor() {companion object {@get:Synchronizedvar instance: Singleton8? = nullget() {if (field == null) {field = Singleton8()}return field}}
}/***饿汉式*/
internal object Singleton9 {fun whateverMethod() {println("....")}
}/***饿汉式,仿Java*/
internal class Singleton10 private constructor() {companion object {val instance = Singleton10()}
}/*** 双检锁/双重校验锁(DCL,即 double-checked locking)*/
internal class Singleton12 private constructor() {companion object {val instance: Singleton12 by lazy {Singleton12()}}
}/*** 双检锁/双重校验锁(DCL,即 double-checked locking),仿Java*/
internal class Singleton11 private constructor() {companion object {@Volatilevar instance: Singleton11? = nullget() {if (field == null) {synchronized(Singleton11::class) {if (field == null) {field = Singleton11()}}}return field}}
}/*** 登记式/静态内部类*/
internal class Singleton13 {private object SingletonHolder {val INSTANCE = Singleton13()}companion object {val instance: Singleton13get() = SingletonHolder.INSTANCE}
}/*** 枚举*/
internal enum class Singleton14 {INSTANCE;fun whateverMethod() {println("....")}
}

Kotlin的5种单例模式

前言

最近在学习Kotlin这门语言,在项目开发中,运用到了单例模式。因为其表达方式与Java是不同的。所以对不同单例模式的实现进行了分别探讨。主要单例模式实现如下:

  • 饿汉式
  • 懒汉式
  • 线程安全的懒汉式
  • 双重校验锁式
  • 静态内部类式

PS:该篇文章不讨论单例模式的运用场景与各种模式下的单例模式的优缺点。只讨论在Java下不同单例模式下的对应Kotlin实现。

一、饿汉式实现

//Java实现
public class SingletonDemo {private static SingletonDemo instance=new SingletonDemo();private SingletonDemo(){}public static SingletonDemo getInstance(){return instance;}
}
//Kotlin实现
object SingletonDemo


这里很多小伙伴就吃了一惊。我靠,一个object 关键字就完成相同的功能?一行代码?

Kotlin的对象声明

学习了Kotlin的小伙伴肯定知道,在Kotlin中类没有静态方法。如果你需要写一个可以无需用一个类的实例来调用,但需要访问类内部的函数(例如,工厂方法,单例等),你可以把该类声明为一个对象。该对象与其他语言的静态成员是类似的。如果想了解Kotlin对象声明的更多内容,可以去看看之前的文章。

到这里,如果还是有很多小伙伴不是很相信一行代码就能解决这个功能,我们可以通过一下方式查看Kotlin的字节码。

查看Kotlin对应字节码


 

我们进入我们的Android Studio(我的Android Studio 3.0,如果你的编译器版本过低,请自动升级) 选择Tools工具栏,选择"Kotlin",选择“Show Kotlin Bytecode"

选择过后就会进入到下方界面:

点击"Decompile" 根据字节码得到以下代码:

public final class SingletonDemo {public static final SingletonDemo INSTANCE;private SingletonDemo(){}static {SingletonDemo var0 = new SingletonDemo();INSTANCE = var0;}
}


通过以上代码,我们了解事实就是这个样子的,使用Kotlin"object"进行对象声明与我们的饿汉式单例的代码是相同的。

二、懒汉式

//Java实现
public class SingletonDemo {private static SingletonDemo instance;private SingletonDemo(){}public static SingletonDemo getInstance(){if(instance==null){instance=new SingletonDemo();}return instance;}
}
//Kotlin实现
class SingletonDemo private constructor() {companion object {private var instance: SingletonDemo? = nullget() {if (field == null) {field = SingletonDemo()}return field}fun get(): SingletonDemo{//细心的小伙伴肯定发现了,这里不用getInstance作为为方法名,是因为在伴生对象声明时,内部已有getInstance方法,所以只能取其他名字return instance!!}}
}


上述代码中,我们可以发现在Kotlin实现中,我们让其主构造函数私有化并自定义了其属性访问器,其余内容大同小异。

三、线程安全的懒汉式

//Java实现
public class SingletonDemo {private static SingletonDemo instance;private SingletonDemo(){}public static synchronized SingletonDemo getInstance(){//使用同步锁if(instance==null){instance=new SingletonDemo();}return instance;}
}
//Kotlin实现
class SingletonDemo private constructor() {companion object {private var instance: SingletonDemo? = nullget() {if (field == null) {field = SingletonDemo()}return field}@Synchronizedfun get(): SingletonDemo{return instance!!}}}


大家都知道在使用懒汉式会出现线程安全的问题,需要使用使用同步锁,在Kotlin中,如果你需要将方法声明为同步,需要添加@Synchronized注解。

四、双重校验锁式(Double Check)

//Java实现
public class SingletonDemo {private volatile static SingletonDemo instance;private SingletonDemo(){} public static SingletonDemo getInstance(){if(instance==null){synchronized (SingletonDemo.class){if(instance==null){instance=new SingletonDemo();}}}return instance;}
}
//kotlin实现
class SingletonDemo private constructor() {companion object {val instance: SingletonDemo by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {SingletonDemo() }}
}


小伙伴们惊不惊喜,感不感动啊。我们居然几行代码就实现了多行的Java代码。其中我们运用到了Kotlin的延迟属性 Lazy。

Lazy是接受一个 lambda 并返回一个 Lazy 实例的函数,返回的实例可以作为实现延迟属性的委托: 第一次调用 get() 会执行已传递给 lazy() 的 lambda 表达式并记录结果,后续调用 get() 只是返回记录的结果。

这里还有有两个额外的知识点。

  • 高阶函数,高阶函数是将函数用作参数或返回值的函数。大家还是看这个 ---​ ​高阶函数​​
  • ​委托属性​​

五、静态内部类式

//Java实现
public class SingletonDemo {private static class SingletonHolder{private static SingletonDemo instance=new SingletonDemo();}private SingletonDemo(){System.out.println("Singleton has loaded");}public static SingletonDemo getInstance(){return SingletonHolder.instance;}
}
//kotlin实现
class SingletonDemo private constructor() {companion object {val instance = SingletonHolder.holder}private object SingletonHolder {val holder= SingletonDemo()}
}

静态内部类的实现方式,也没有什么好说的。Kotlin与Java实现基本雷同。

六、补充

那么如果小伙伴问,如何在Kotlin版的Double Check,给单例添加一个属性,这里给大家提供了一个实现的方式:

class SingletonDemo private constructor(private val property: Int) {
//这里参数可以根据实际需求发生改变companion object {@Volatile private var instance: SingletonDemo? = nullfun getInstance(property: Int) =instance ?: synchronized(this) {instance ?: SingletonDemo(property).also { instance = it }}}
}


其中关于​​?:​​​操作符,如果 ​​?:​​ 左侧表达式非空,就返回其左侧表达式,否则返回右侧表达式。 请注意,当且仅当左侧为空时,才会对右侧表达式求值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2779942.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Unity学习笔记(零基础到就业)|Chapter04:C#篇补充到Unity篇过渡

Unity学习笔记(零基础到就业)|Chapter02:C#篇补充到Unity篇过渡 前言C#总结补充1.值类型和引用类型有什么区别,他们在值的传递上分别有怎样的特性2.string是引用类型,但是他对外表现出值类型的特性,为什么&…

联想thinkpad-E450双系统升级记

早期笔记本联想thinkpad-E450双系统 大约16年花4000多大洋,买了一台thinkpad-L450屏幕是16寸本,有AMD独立显卡,i5cpu,4G内存。 . 后来加了一个同型号4G内存组成双通道, . 加了一个三星固态500G, . 换了一个…

【leetcode热题100】反转链表 II

给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#xff1a;[1,4,3,2…

Java 基于微信小程序的电子商城购物系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

160基于matlab的负熵和峭度信号的盲分离

基于matlab的负熵和峭度信号的盲分离。基于峭度的FastICA算法的收敛速度要快&#xff0c;迭代次数比基于负熵的FastICA算法少四倍以上。SMSE随信噪比增大两种判据下的FastICA算法都逐渐变小&#xff0c;但是基于峭度的算法的SMSE更小&#xff0c;因此基于峭度的FastICA算法性能…

Vue源码系列讲解——模板编译篇【一】(综述)

目录 1. 前言 2. 什么是模板编译 3. 整体渲染流程 4. 模板编译内部流程 4.1 抽象语法树AST 4.2 具体流程 5. 总结 1. 前言 在前几篇文章中&#xff0c;我们介绍了Vue中的虚拟DOM以及虚拟DOM的patch(DOM-Diff)过程&#xff0c;而虚拟DOM存在的必要条件是得先有VNode&…

c++猜数游戏

一.题目要求 系统随机产生1~100的随机数,进行猜数,如果猜的数过大提示猜数过大,过小提出猜数过小,直到猜出正确的数字 二.代码 三.示例

嵌入式电子产品开发感悟!

​ 2023特别深有感触的有以下几个事件&#xff1a; 1. 早在2月底就提交报告&#xff1a;抓紧开一款便携式的空气波压力按摩仪外壳&#xff0c;包括模具费和100台试产物料费用总计不超过22W&#xff0c;保证最迟在4月中旬全部生产好&#xff0c;以供业务参加5月份开始的大健康展…

测试编码规范

0.测试代码和业务代码要分离 把测试代码和业务代码放进各自的所属的"盒子"中&#xff0c;互不干扰 Q:为什么要分离? 分门别类&#xff0c;避免混乱&#xff0c;方便维护 不在试卷上打草稿而是专门准备草稿纸 没人会在客厅做饭吧&#xff0c;不然要厨房干什么 Q:如…

视觉SLAM十四讲学习笔记(二)三维空间刚体

哔哩哔哩课程连接&#xff1a;视觉SLAM十四讲ch3_哔哩哔哩_bilibili​ 目录 一、旋转矩阵 1 点、向量、坐标系 2 坐标系间的欧氏变换 3 变换矩阵与齐次坐标 二、实践&#xff1a;Eigen&#xff08;1&#xff09; 运行报错记录与解决 三、旋转向量和欧拉角 1 旋转向量 …

【OrangePi Zero2 智能家居】需求及项目准备

一、需求及项目准备 二、系统框图 三、硬件接线 四、语音模块配置 五、模块测试 一、需求及项目准备 语音接入控制各类家电&#xff0c;如客厅灯、卧室灯、风扇Socket网络编程&#xff0c;实现Sockect发送指令远程控制各类家电烟雾警报监测&#xff0c; 实时检查是否存在煤气…

谷粒商城【成神路】-【6】——商品维护

目录 &#x1f9c2;1.发布商品 &#x1f953;2.获取分类关联品牌 &#x1f32d;3.获取分类下所有分组和关联属性 &#x1f37f;4.商品保存功能 &#x1f9c8;5.sup检索 &#x1f95e;6.sku检索 1.发布商品 获取用户系统等级~&#xff0c;前面生成了后端代码&#xff…

前端面试题——二叉树遍历

前言 二叉树遍历在各种算法和数据结构问题中都有广泛的应用&#xff0c;如二叉搜索树、表达式的树形表示、堆的实现等。同时也是前端面试中的常客&#xff0c;掌握好二叉树遍历算法对于一名合格的前端工程师来说至关重要。 概念 二叉树遍历&#xff08;Binary Tree Traversa…

自然语言处理(NLP)—— 基本概念

自然语言处理&#xff08;Natural Language Processing&#xff0c;简称NLP&#xff09;是人工智能和语言学领域的一个分支&#xff0c;它涉及到计算机和人类&#xff08;自然&#xff09;语言之间的相互作用。它的主要目标是让计算机能够理解、解释和生成人类语言的数据。NLP结…

73. 矩阵置零(Java)

目录 题目描述&#xff1a;输入&#xff1a;输出&#xff1a;代码实现&#xff1a; 题目描述&#xff1a; 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 输入&#xff1a; matrix [[1,1,1],[1,0,…

Linux操作系统基础(九):Linux用户与权限

文章目录 Linux用户与权限 一、文件权限概述 二、终端命令&#xff1a;组管理 三、终端命令&#xff1a;用户管理 1、创建用户 、 设置密码 、删除用户 2、查看用户信息 3、su切换用户 4、sudo 4.1、给指定用户授予权限 4.2、使用 用户 zhangsan登录, 操作管理员命令…

汉服租赁网站:Java技术的文化应用

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Matplotlib核心:掌握Figure与Axes

详细介绍Figure和Axes&#xff08;基于Matplotlib&#xff09; &#x1f335;文章目录&#x1f335; &#x1f333;引言&#x1f333;&#x1f333; 一、Figure&#xff08;图形&#xff09;&#x1f333;&#x1f341;1. 创建Figure&#x1f341;&#x1f341;2. 添加Axes&am…

【浙大版《C语言程序设计实验与习题指导(第4版)》】实验7-1-6 求一批整数中出现最多的个位数字(附测试点)

定一批整数&#xff0c;分析每个整数的每一位数字&#xff0c;求出现次数最多的个位数字。例如给定3个整数1234、2345、3456&#xff0c;其中出现最多次数的数字是3和4&#xff0c;均出现了3次。 输入格式&#xff1a; 输入在第1行中给出正整数N&#xff08;≤1000&#xff0…

揭秘 LLM 推理:全面解析 LLM 推理性能的关键因素

一、背景介绍 自 OpenAI 一年前发布 ChatGPT 以来&#xff0c;大型语言模型&#xff08;LLM&#xff09;领域经历了前所未有的快速发展。在短短一年时间内&#xff0c;涌现出了数以百计的 LLM 模型&#xff0c;包括开源模型如 LLaMA、Mistral、Yi、Baichuan、Qwen&#xff0c;…