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和单例模式的更多相关文章

  1. JAVA Static方法与单例模式的理解

    近期用sonar測评代码质量的时候,发现一个问题,project中一些util类,曾经写的static方法都提示最好用单例的方式进行改正. 为此,我细致想了想,发现还是非常有道理的.这里谈谈我个人对s ...

  2. JDK设计模式之—单例模式和static关键字

    首先了解static 关键字 static声明的方法是静态方法,static声明的成员变量为静态成员变量.对于该类的所有对象来说,static的成员变量和static只有一份存储空间 即使没有创建该类 ...

  3. java——多线程——单例模式的static方法和非static方法是否是线程安全的?

    单例模式的static方法和非static方法是否是线程安全的? 答案是:单例模式的static方法和非static方法是否是线程安全的,与单例模式无关.也就说,如果static方法或者非static ...

  4. [转]java static final 初始化

    http://tanbing1986411.blog.163.com/blog/static/7259798220103610224434/ java static final 初始化 1.stati ...

  5. java单例模式教程之java实现单例模式的8大方法

    单例模式是Java中常用的设计模式之一.单例模式属于创建型模式,它提供了一种创建对象的最佳方式. 单例模式只创建类的一个对象,之后在一定范围为可任意调用,确保只有单个对象被创建.这个类提供了一种访问其 ...

  6. DCL单例模式中的缺陷及单例模式的其他实现

    DCL:Double Check Lock ,意为双重检查锁.在单例模式中懒汉式中可以使用DCL来保证程序执行的效率. 1 public class SingletonDemo { 2 private ...

  7. Java 关键字static final使用总结

    Static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,被static修饰的成员变量和成员方法独立于该类的任何对象.也就是说,它不依赖类特定的实例,被 ...

  8. 关于The serializable class XXX does not declare a static final serialVersionUID field of type long的警告

    编写实体类并且继承序列化接口时候,实体类会有警告,要生成一个静态的serialVersionUID. 上网搜了一下资料,现通俗解释一下: 点击前2个选项,会生成: private static fin ...

  9. 为什么构造器不能是abstract, static, final, native or synchronized的?

    Unlike methods, a constructor cannot be abstract, static, final, native  or synchronized. 1. A const ...

随机推荐

  1. 【agc005d】~K Perm Counting

    题目大意 求有多少中1~n的排列,使得\(abs(第i个位置的值-i)!=k\) 解题思路 考虑容斥,\(ans=\sum_{i=0}^{n}(-1)^ig[i](n-i)!(g[i]表示至少有i个位 ...

  2. HDU 6039 - Gear Up | 2017 Multi-University Training Contest 1

    建模简析: /* HDU 6039 - Gear Up [ 建模,线段树,图论 ] | 2017 Multi-University Training Contest 1 题意: 给你n个齿轮,有些齿轮 ...

  3. EOS dice移到1.8版本的修改汇总

    EOS dice移到1.8版本的修改汇总 1. CORE_SYMBOL 被去掉了,需要自己在文件中声明eg: uint64_t string_to_symbol_c(uint8_t precision ...

  4. java+实现上传文件夹

    我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 首先我们需要了解的是上传文件三要素: 1.表单提交方式:post (get方式提交有大小 ...

  5. apt-get build-dep命令详解

    apt-get build-dep命令详解 - 星星之火的Blog - CSDN博客  https://blog.csdn.net/starflame/article/details/7416311 ...

  6. vue添加外部js

    1.新建节点 const s = document.createElement("script"); 2.设置节点属性 s.type = "text/javascript ...

  7. 关于我&留言板

    在下高一OIer一枚,就读于SC的一所发展中学(ruo)校 对二次元什么的,有着淡淡的喜爱 初三的时候入了古风的坑,想变得文艺一点,可爱一点 也会听歌,但听得不多(主要是听新歌比较随缘),范围窄(古风 ...

  8. HNOI2012排队

    排列组合题(本文A(n,m)表示从n个元素里选m个的排列数). 首先,老师和女生有不能相邻的限制条件,应该用插空法.而且老师人数较少且固定,把老师和男生进行混合,对女生用插空. 我先来一手错误做法,n ...

  9. IDEA安装配置Thrift

    下载exe:http://archive.apache.org/dist/thrift/0.9.3/ 新建一个thrift目录放进来,并将名字改成thrift

  10. 踩坑之SpringBoot WebSocker 部署Tomcat冲突

    启动tomcat容器,部署SpringBoot项目,启动项目报错,如下图: 看1.2的顺序就知道是WebSocket冲突了. 上网找了一下资料发现,使用@ServerEndpoint创立websock ...