面试必考-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;
        }
    }
}
最优,但是枚举这个东西可读性不高


具体选择什么,看情况


  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值