Detailed explanation of kotlin's singleton class

object

Declaration of singleton object:

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

Questions are raised: objectWhat type of singleton pattern is used for the modified class?

Here we first review javathe six singleton patterns

1. Hungry Chinese style
public class HungryMan {
    
    

    private HungryMan(){
    
    }

    private static HungryMan hungryMan = new HungryMan();

    public static HungryMan getInstance(){
    
    
        return hungryMan;
    }
}

Advantages: simple and convenient, thread safe

Disadvantages: Whether it is used or not, it will be instantiated, and it will be instantiated when the class is loaded

2. Lazy style
public class LazyMan {
    
    

    private static LazyMan lazyMan = null;

    private LazyMan() {
    
    
    }

    public static LazyMan getInstatce() {
    
    
        if (lazyMan == null) {
    
    
            lazyMan = new LazyMan();
        }
        return lazyMan;
    }
}

Advantages: Objects are only generated when they are used, which can reduce memory overhead

Disadvantages: Thread is not safe and can only be used in a single thread. When multiple threads access, multiple objects will be generated.

3. Lazy sync lock
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;
    }
}

Pros: supports multithreading

Disadvantages: There will be a lock and release operation every time, which is inefficient and can destroy the singleton mode through reflection.

4. DCLDouble detection lock
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;
    }
}

Here is an introduction to explain DCLthe double detection lock mechanism:

DCLDouble detection lock mechanism: DCLWhy use double detection lock mechanism to valoatilemodify, because lazyMan=new LazyMan()it is not an atomic operation. In fact, JVMI probably did 3 things in .

1. To lazyManallocate memory,

2. Call the constructor to initialize member variables

3. Point lazyManthe object to the allocated memory space. However JVM, there is an optimization of instruction reordering in the real-time compiler, that is to say, the order of the second and third steps above is uncertain. Once 2, 3, the order is messed up. This is because a thread calls the method. It is non-null, but it is not initialized, so an error is reported directly.

Advantages: high efficiency, thread safety

Disadvantages: the code is complicated, and the singleton can be destroyed by reflection

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

Advantages: The static properties of the class are only initialized when the class is loaded for the first time, so thread safety

Disadvantages: the code becomes complicated and apkthe file size increases

6. Enumerate singletons
public enum SingleTon {
    
    

    SINGLE_TON;

    private String field;

    public String getField() {
    
    
        return field;
    }

    public void setField(String field) {
    
    
        this.field = field;
    }
}

Advantages: thread safety, no need to worry about reflection breaking singleton mode

Disadvantage: enumeration class takes up a lot of memory

Analysis: What type of singleton is the object singleton class

Here we directly convert kotlinthe code to Java code for viewing.

kotlincode show as below

Javaafter turning

We can see Modelthat Javaafter the class is converted into code, it is a hungry singleton. So objectthe class used is a hungry Chinese singleton.

companion objectWhat type of singleton is the singleton that appears in the companion object

kotlincode show as below

class  Model{
    
    
    companion object{
    
    
        val text = ApiWrapper("11")
    }
}

class ApiWrapper (val api : String){
    
    
     fun s() {
    
    
      
    }
}

javacode show as below

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();
      }
   }
}

It can be seen that if you assign texta value directly, it is equivalent to a hungry Chinese style loading

But what if we textdo lazy assignment onby 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();
      }
   }
}

It can be seen that this time becomes 懒汉式同步单例,

As for why it is a synchronous singleton, here you need to look at LazyKt.lazy()the method

Guess you like

Origin blog.csdn.net/weixin_44710164/article/details/127889022