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 }}}
}
其中关于?:操作符,如果 ?: 左侧表达式非空,就返回其左侧表达式,否则返回右侧表达式。 请注意,当且仅当左侧为空时,才会对右侧表达式求值。
相关文章:
Kotlin和Java 单例模式
Java 和Kotlin的单例模式其实很像,只是Kotlin一部分单例可以用对象类和委托lazy来实现 Java /*** 懒汉式,线程不安全*/ class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (insta…...
软考 系统分析师系列知识点之信息系统战略规划方法(9)
接前一篇文章:软考 系统分析师系列知识点之信息系统战略规划方法(8) 所属章节: 第7章. 企业信息化战略与实施 第4节. 信息系统战略规划方法 7.4.5 信息工程方法 信息工程(Information Engineering,IE&…...
政安晨:示例演绎TensorFlow的官方指南(一){基础知识}
为什么要示例演绎? 既然有了官方指南,咱们在官方指南上看看就可以了,为什么还要写示例演绎的文章呢? 其实对于初步了解TensorFlow的小伙伴们而言,示例演绎才是最重要的。 官方文档已经假定了您已经具备了相当合适的…...
node - 与数据库交互
在Web开发中,与数据库交互是常见的需求,用于持久化存储、检索和操作数据。不同的后端技术和数据库类型(如关系型数据库和非关系型数据库)有着不同的交互方式。下面介绍几种常见的数据库交互方法。 关系型数据库 关系型数据库(如MySQL、PostgreSQL、SQLite)使用结构化查…...
速盾:2024年cdn在5g时代重要吗
在2024年,随着5G技术的普及与应用,内容分发网络(Content Delivery Network,CDN)在数字化时代中的重要性将进一步巩固和扩大。CDN是一种用于快速、高效地分发网络内容的基础设施,它通过将内容部署在全球各地…...
微信小程序(四十一)wechat-http的使用
注释很详细,直接上代码 上一篇 新增内容: 1.模块下载 2.模块的使用 在终端输入npm install wechat-http 没有安装成功vue的先看之前的一篇 微信小程序(二十)Vant组件库的配置- 如果按以上的成功配置出现如下报错先输入以下语句 …...
所有设计模式大全及学习链接
文章目录 创建型设计模式结构型设计模式行为型设计模式 创建型设计模式 一种创建对象的设计模式,它们提供了一种灵活的方式来创建对象,同时隐藏了对象的创建细节。以下是常见的创建型设计模式: 工厂方法模式(Factory Method Patte…...
【Java程序设计】【C00264】基于Springboot的原创歌曲分享平台(有论文)
基于Springboot的原创歌曲分享平台(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的原创歌曲分享平台 本系统分为平台功能模块、管理员功能模块以及用户功能模块。 平台功能模块:在平台首页可以查看首…...
2024年,要特别注意这两个方位
家居风水对每个家庭都非常重要,可在无形中影响到人们的事业、财富以及健康运势。俗话说:“风水轮流转”,2024年为甲辰龙年,斗转星移、九宫飞星将改变宫位,新一年的磁场即将启动,方位的吉凶也会重新变动&…...
【Chrono Engine学习总结】5-sensor-5.1-sensor基础并创建一个lidar
由于Chrono的官方教程在一些细节方面解释的并不清楚,自己做了一些尝试,做学习总结。 1、Sensor模块 Sensor模块是附加模块,需要单独安装。参考:【Chrono Engine学习总结】1-安装配置与程序运行 Sensor Module Tutorial Sensor …...
springboot/ssm学生信息管理系统Java学生在线选课考试管理系统
springboot/ssm学生信息管理系统Java学生在线选课考试管理系统 开发语言:Java 框架:springboot(可改ssm) vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库:mysql 5.…...
three.js 箭头ArrowHelper的实践应用
效果: 代码: <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div></div></el-main></…...
力扣hot2--哈希
推荐博客: for(auto i : v)遍历容器元素_for auto 遍历-CSDN博客 字母异位词都有一个特点:也就是对这个词排序之后结果会相同。所以将排序之后的string作为key,将排序之后能变成key的单词组vector<string>作为value。 class Solution …...
【正在更新】从零开始认识语音识别:DNN-HMM混合系统语音识别(ASR)原理
摘要 | Abstract 这是一篇对语音识别中的一种热门技术——DNN-HMM混合系统原理的透彻介绍。本文自2月10日开始撰写,计划一星期内写完。 1.前言 | Introduction 近期想深入了解语音识别(ASR)中隐马尔可夫模型(HMM)和深度神经网络-隐马尔可夫(DNN-HMM)混合模型&#…...
thinkphp+vue企业产品展示网站f7enu
本文首先介绍了企业产品展示网站管理技术的发展背景与发展现状,然后遵循软件常规开发流程,首先针对系统选取适用的语言和开发平台,根据需求分析制定模块并设计数据库结构,再根据系统总体功能模块的设计绘制系统的功能模块图&#…...
在Ubuntu22.04上部署ComfyUI
ComfyUI 是 一个基于节点流程的 Stable Diffusion 操作界面,可以通过流程,实现了更加精准的工作流定制和完善的可复现性。每一个模块都有特定的的功能,我们可以通过调整模块连接达到不同的出图效果,特点如下: 1.对显存…...
Springboot+vue的社区养老服务平台(有报告)。Javaee项目,springboot vue前后端分离项目
演示视频: Springbootvue的社区养老服务平台(有报告)。Javaee项目,springboot vue前后端分离项目 项目介绍: 本文设计了一个基于Springbootvue的前后端分离的社区养老服务平台,采用M(model&…...
计算机设计大赛 深度学习+opencv+python实现车道线检测 - 自动驾驶
文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数:3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV56 数据集处理7 模型训练8 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 &am…...
机器学习2---逻辑回归(基础准备)
逻辑回归是基于线性回归是直线分的也可以做多分类 ## 数学基础 import numpy as np np.pi # 三角函数 np.sin() np.cos() np.tan() # 指数 y3**x # 对数 np.log10(10) np.log2(2) np.e np.log(np.e) #ln(e)# 对数运算 # log(AB) log(A) logB np.log(3*4)np.log(3)np.log(4) #…...
JVM体系
JVM是一种虚拟的计算机,它模拟了一个完整的硬件系统,并运行在一个完全隔离的环境中。这意味着JVM可以看作是一个在操作系统之上的计算机系统,与VMware、Virtual Box等虚拟机类似。JVM的设计目标是提供一个安全、可靠、高效且跨平台的运行环境…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
