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

kotlin 之单例类详解

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

北京

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

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

看不清楚,换张图片

免费获取短信验证码

kotlin 之单例类详解

object

单例对象的声明:

object  Model{    var temp = "1"    val temp2 = "2"    const val temp3 = "3"}

抛出疑问:使用object修饰的类,是哪种类型的单例模式

这里我们先回顾一下java六种单例模式

1. 饿汉式
public class HungryMan {    private HungryMan(){}    private static HungryMan hungryMan = new HungryMan();    public static HungryMan getInstance(){        return hungryMan;    }}

优点:简单方便,线程安全

缺点:无论是否用到,都会进行实例化,而且在类加载时就会实例化

2. 懒汉式
public class LazyMan {    private static LazyMan lazyMan = null;    private LazyMan() {    }    public static LazyMan getInstatce() {        if (lazyMan == null) {            lazyMan = new LazyMan();        }        return lazyMan;    }}

优点:只有在使用时才会生成对象,能够减少内存开销

缺点:线程不安全,只能在单线程中使用,多个线程访问时,会产生多个对象,

3.懒汉式同步锁
public class LazyMan {    private static volatile LazyMan lazyMan = null;    private LazyMan() {    }    public static LazyMan getInstatce() {        synchronized (LazyMan.class){            if (lazyMan == null) {                lazyMan = new LazyMan();            }        }        return lazyMan;    }}

优点:支持多线程

缺点:每次都会有一个加锁以及释放锁的操作,效率低,可以通过反射破坏单例模式。

4.DCL双检测锁
public class LazyMan {    private static volatile LazyMan lazyMan = null;    private LazyMan() {    }    public static LazyMan getInstatce() {        if(lazyMan == null){            synchronized (LazyMan.class){                if (lazyMan == null) {                    lazyMan = new LazyMan();                }            }        }        return lazyMan;    }}

这里引入一下解释一下DCL双检测锁机制:

DCL双检测锁机制: 用DCL双检测锁机制为什么要用valoatile修饰,因为lazyMan=new LazyMan(), 并非是一个原子操作。事实上在JVM中大概做了3件事。

lazyMan分配内存,

调用构造器来初始化成员变量

lazyMan对象指向分配的内存空间。 但是JVM的即时编译器中存在指令重排序的优化,也就是说上面的第二步,第三步顺序是不 确定的一旦2,3,顺序乱了,这个是有一个线程调用了方法,结果虽然是非null,但是未初 始化,所以直接报错。

优点:效率高,线程安全

缺点:代码复杂,可以通过反射破坏单例

5.静态内部类
public class Singleton {     private Singleton() {}     private static class SingletonInstance {//私有静态内部类        private static final Singleton INSTANCE = new Singleton();    }     public static Singleton getInstance() {        return SingletonInstance.INSTANCE;    }}

优点:类的静态属性只有在第一次加载类的时候初始化,所以线程安全

缺点:代码变得复杂,apk文件增大

6. 枚举单例
public enum SingleTon {    SINGLE_TON;    private String field;    public String getField() {        return field;    }    public void setField(String field) {        this.field = field;    }}

优点:线程安全,不用担心反射破话单例模式

缺点:枚举类占用内存多

解析:object 单例类是什么类型的单例

这里我们直接将kotlin代码转为Java 代码进行查看。

kotlin代码如下

转为Java之后

我们可以看到,该Model类转为Java代码之后,它是一个饿汉式单例。所以使用object的类采用的是饿汉式单例。

companion object伴生对象出现的单例是哪种类型的单例

kotlin代码如下

class  Model{    companion object{        val text = ApiWrapper("11")    }}class ApiWrapper (val api : String){     fun s() {          }}

java代码如下

public final class Model {   @NotNull   private static final ApiWrapper text = new ApiWrapper("11");   @NotNull   public static final Model.Companion Companion = new Model.Companion((DefaultConstructorMarker)null);   public static final class Companion {      @NotNull      public final ApiWrapper getText() {         return Model.text;      }      private Companion() {      }      public Companion(DefaultConstructorMarker $constructor_marker) {         this();      }   }}

可以看的出来,如果直接对text赋值,那么就相当于是一个饿汉式加载

但是如果我们对text进行by lazy延迟赋值,那么会是什么样子呢。

public final class Model {   @NotNull   private static final Lazy text$delegate;   @NotNull   public static final Model.Companion Companion = new Model.Companion((DefaultConstructorMarker)null);   static {      text$delegate = LazyKt.lazy((Function0)null.INSTANCE);   }   public static final class Companion {      @NotNull      public final ApiWrapper getText() {         Lazy var1 = Model.text$delegate;         Model.Companion var2 = Model.Companion;         Object var3 = null;         return (ApiWrapper)var1.getValue();      }      private Companion() {      }      public Companion(DefaultConstructorMarker $constructor_marker) {         this();      }   }}

可以看出,此时变成了懒汉式同步单例

至于为什么是同步单例,这里需要大家去看一下LazyKt.lazy()方法

来源地址:https://blog.csdn.net/weixin_44710164/article/details/127889022

免责声明:

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

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

kotlin 之单例类详解

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

下载Word文档

猜你喜欢

Kotlin 的注解类详解及实例

Kotlin 的注解类详解及实例注解声明注解是将元数据附加到代码的方法。要声明注解,请将 annotation 修饰符放在类的前面:annotation class Fancy
2023-05-31

Kotlin 泛型详解及简单实例

Kotlin 泛型详解概述一般类和函数,只能使用具体的类型:要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的约束对代码的限制很大。而OOP的多态采用了一种泛化的机制,在SE 5种,Java引用了泛型。泛型,
2023-05-31

Kotlin this详解及实例

Kotlin this详解及实例为了表示当前函数的接收者(receiver), 们使用this表达式: 在类的成员函数中,this指向这个类的当前对象实例; 在扩展函数中,或带接收者的函数字面值(function literal) 中,
2023-05-31

Android Kotlin之Coroutine(协程)详解

协程是一种并发设计模式,您可以在 Android 平台上使用它来简化异步执行的代码。 在 Android 上,协程有助于管理长时间运行的任务,如果管理不当,这些任务可能会阻塞主线程并导致应用无响应。 协程的优点: 轻量 您可以在单个线程上运
2023-08-16

Kotlin泛型的型变之路演变示例详解

这篇文章主要为大家介绍了Kotlin泛型的型变之路演变示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-12-21

python 类详解及简单实例

python 类详解 类 1.类是一种数据结构,可用于创建实例。(一般情况下,类封装了数据和可用于该数据的方法)2.Python类是可调用的对象,即类对象3.类通常在模块的顶层进行定义,以便类实例能够在类所定义的源代码文件中的任何地方被创建
2022-06-04

Kotlin 基础语法实例详解

Kotlin 基础语法实例详解包定义和引入Java一样,在文件开头, 行结束不需要” ; “package com.test.helloimport android.os.Bundle
2023-05-31

Kotlin 内联函数详解及实例

Kotlin 内联函数详解及实例概述在说内联函数之前,先说说函数的调用过程。调用某个函数实际上将程序执行顺序转移到该函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去前要保护现场并记
2023-05-31

Kotlin协程Dispatchers原理示例详解

这篇文章主要为大家介绍了Kotlin协程Dispatchers原理示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

Android Build类的详解及简单实例

Android Build类的详解及简单实例一、类结构:java.lang.Object android.os.Build
2023-05-30

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录