• 单例模式(一)static、final和单例模式


    static

    那天我朋友问了我个问题,static和单例模式有什么区别,所以我觉得static可以讲一下

    他的问题是,把对象弄成static是不是就不变了

    显然,这是还没弄清楚引用和对象的区别

    其实存放在静态区中的是引用,而不是对象。而对象是存放在堆中的。如果有这样一句话

    public static final Book book = new Book();

    意思就是book这个引用,指向了这个new出来的对象。

    static的引用和正常的引用有什么区别?

    当你加载了这个类的时候(第一次使用这个类的时候会加载这个类到jvm),这个static引用会率先被加载。所以,当我们第一次调用Book.book的时候,这个静态的book引用就会一直存放在静态区里了(当fullGC回收整个类才会销毁这个引用)。

    而正常的引用,只能通过new出一个对象后才能使用,所以当对象被回收了,这个引用自然也回收了(而且非静态引用如果是方法中的引用,会存放在函数的栈里;如果是对象的引用,会和对象一起存放在heap里)。

    final

    final定义了之后,你就必须在一开始就需要赋值,所以上面那行代码就必须在一开始就赋值。而如果你想延迟加载,提高性能,那么就不可以用final。

    单例模式

    单例模式是如果实现的,就是通过调用这个类里的一个静态方法,弄一个if语句判断一下,如果有实例了,就返回这个实例,如果没有,就创建这个实例。其实并没有多大的技术含量。

    第一种,最基本的思维。

    public class Book {
    private static Book book = new Book();
    private Book() {}
    public static Book getInstance() {
    if (book == null) {
    book = new Book();
    }
    return book;
    }
    }

    这里为什么要判空呢?因为你这个是静态的,所以其他地方完全有Book.getInstance = null;的可能。

    第二种,这里使用final,让引用的指向不可变,这样就不需要判空了

    public class Book {
    private static final Book book = new Book();
    private Book() {}
    public static Book getInstance() {
    return book;
    }
    }

    第三种,延迟加载(线程不安全,假如有多个同时发现是空的,会创建出好多实例)

    public class Book {
    private static Book book;
    private Book() {}
    public static Book getInstance() {
    if (book == null) {
    book = new Book();
    }
    return book;
    }
    }

    第四种,添加线程安全功能,加一个关键字就可以

    public class Book {
    private static Book book;
    private Book() {}
    public static synchronized Book getInstance() {
    if (book == null) {
    book = new Book();
    }
    return book;
    }
    }

    这个方法在多线程下的工作表现很出色


    第五种,规避不需要的同步,因为上面的同步范围太大,有点浪费性能,在引用有指向的时候,是不需要同步的

    public class Book {
    private static Book book;
    private Book() {}
    public static synchronized Book getInstance() {
    if (book == null) {
    synchronized (Book.class) {
    book = new Book();
    }
    }
    return book;
    }
    }

    第六种,静态内部类

    public class Book {
    private Book() {}
    public static synchronized Book getInstance() {
    return BookHolder.book;
    }
    private static class BookHolder {
    private static final Book book = new Book();
    }
    }

    第七种,枚举单例

    public class Book {
    private Book(){}
    public static Book getInstance() {
    return BookEnum.BOOK.getInstance();
    }
    
    private static enum BookEnum {
    BOOK;
    private Book book;
    private BookEnum() {
    book = new Book();
    }
    public Book getInstance() {
    return book;
    }
    }
    }

    最优,但是枚举这个东西可读性不高

  • 相关阅读:
    Android-调用优酷SDK上传视频
    新浪微博客户端(16)-获得并显示用户昵称
    新浪微博客户端(15)-保存用户名和密码
    转:Java NIO系列教程(九) Pipe
    新浪微博客户端(14)-截取回调地址中的授权成功的请求标记,换取access_token
    iOS-AFN "Request failed: unacceptable content-type: text/plain"
    新浪微博客户端(13)-使用UIWebView加载OAuth授权界面
    iOS-(kCFStreamErrorDomainSSL, -9802)
    转:Java NIO系列教程(八) DatagramChannel
    转:Java NIO系列教程(七) Socket Channel
  • 原文地址:https://www.cnblogs.com/JonaLin/p/11533183.html
Copyright © 2020-2023  润新知