单例模式(一)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;
}
}
}
最优,但是枚举这个东西可读性不高
单例模式(一)static、final和单例模式的更多相关文章
- JAVA Static方法与单例模式的理解
近期用sonar測评代码质量的时候,发现一个问题,project中一些util类,曾经写的static方法都提示最好用单例的方式进行改正. 为此,我细致想了想,发现还是非常有道理的.这里谈谈我个人对s ...
- JDK设计模式之—单例模式和static关键字
首先了解static 关键字 static声明的方法是静态方法,static声明的成员变量为静态成员变量.对于该类的所有对象来说,static的成员变量和static只有一份存储空间 即使没有创建该类 ...
- java——多线程——单例模式的static方法和非static方法是否是线程安全的?
单例模式的static方法和非static方法是否是线程安全的? 答案是:单例模式的static方法和非static方法是否是线程安全的,与单例模式无关.也就说,如果static方法或者非static ...
- [转]java static final 初始化
http://tanbing1986411.blog.163.com/blog/static/7259798220103610224434/ java static final 初始化 1.stati ...
- java单例模式教程之java实现单例模式的8大方法
单例模式是Java中常用的设计模式之一.单例模式属于创建型模式,它提供了一种创建对象的最佳方式. 单例模式只创建类的一个对象,之后在一定范围为可任意调用,确保只有单个对象被创建.这个类提供了一种访问其 ...
- DCL单例模式中的缺陷及单例模式的其他实现
DCL:Double Check Lock ,意为双重检查锁.在单例模式中懒汉式中可以使用DCL来保证程序执行的效率. 1 public class SingletonDemo { 2 private ...
- Java 关键字static final使用总结
Static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,被static修饰的成员变量和成员方法独立于该类的任何对象.也就是说,它不依赖类特定的实例,被 ...
- 关于The serializable class XXX does not declare a static final serialVersionUID field of type long的警告
编写实体类并且继承序列化接口时候,实体类会有警告,要生成一个静态的serialVersionUID. 上网搜了一下资料,现通俗解释一下: 点击前2个选项,会生成: private static fin ...
- 为什么构造器不能是abstract, static, final, native or synchronized的?
Unlike methods, a constructor cannot be abstract, static, final, native or synchronized. 1. A const ...
随机推荐
- [React] Always useMemo your context value
Have a similar post about Reac.memo. This blog is the take away from this post. To understand why to ...
- 【Python之路】特别篇--Python反射
反射 说反射之前先介绍一下__import__方法,这个和import导入模块的另一种方式 1. import commons 2. __import__('commons') 如果是多层导入: 1. ...
- vue子组件改变父组件的值
1 在父组件的coment绑定事件 <template> <div :class="classObj" class="app-wrapper" ...
- C++入门经典-类成员的可访问性,继承后的可访问性
1:关键字public.private.protected说明类成员是共有的.私有的,还是保护的.这3个关键字将类划分为3个区域,在public区域的类成员可以在类作用域外被访问,而private区域 ...
- 使用Grizzy+Jersey搭建一个RESTful框架()报错Exception in thread "main" java.lang.AbstractMethodError: javax.ws.rs.core.UriBuilder.uri(Ljava/lang/String;)Ljavax/ws/rs/core/UriBuilder;
报错的类涉及UriBuilder,我搜索类发现, 这个类存在于两个包中,我在baidu的时候,也有人提到是jar包冲突,我就删除了 这个依赖,问题解决了. 环境搭建过程请见地址https://blog ...
- LVS分析
概述 LVS是章文嵩博士十几年前的开源项目,已经被何如linux kernel 目录十几年了,可以说是国内最成功的kernle 开源项目, 在10多年后的今天,因为互联网的高速发展LVS得到了极大的应 ...
- SUSE zypper 本地源配置
存放repo 文件目录 cd /etc/zypp/repos.d 创建用来存放ISO文件的目录: mkdir /opt/iso 将服务器端的存放ISO文件的目录挂载到本机: mount -t cifs ...
- 2、记录代码----Ajax
$.ajax({ url:'/content-engine/index.php/tracker/confirmSendEmail', async: false, //默认为true,同意异步传输 da ...
- leetcode-hard-array-76. Minimum Window Substring -NO
mycode 不会.. 参考: class Solution(object): def minWindow(self, s, t): """ :type s: str : ...
- @Transient的应用
我今天分配的任务是为一个页面Debug,遇到了一个问题查询的实体类在数据库没有对应的表,这时最常用的是建立视图或者表,但是应用@Transient注释可以让你更简单,免除建立表还有视图需要找多表关联关 ...