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的设计目标是提供一个安全、可靠、高效且跨平台的运行环境…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
