一个类的静态属性只会在第一次加载类时初始化
静态变量只初始化一次
懒汉式方式:
1 //懒汉式单例 2 public class Singleton1 { 3 // 4 定义一个变量存储创建好的类实例 4 // 5 要在静态方法中使用,所以需要加上static修饰 5 private static Singleton1 instance = null; 6 //1 私有化构造函数,在内部控制创建实例的数目 7 private Singleton1(){} 8 // 2 定义一个方法为客户端提供类实例 9 // 3 需要定义成类方法,加static 10 public static Singleton1 getInstance(){ 11 // 6 判断存储实例的变量是否有值 12 if(instance == null){ 13 // 6.1 如果没有,就创建一个类实例,赋给存储类实例的变量 14 instance = new Singleton1(); 15 } 16 // 6.2 如果有值,就直接使用 17 return instance; 18 } 19 } 20 //没有经过内部类处理,这种方式最主要的缺点就是一旦我访问了Singleton1的任何其他的静态域, 21 //就会造成实例的初始化,而事实是可能我们从始至终就没有使用这个实例,造成内存的浪费
不加同步的懒汉式是线程不安全的。
//饿汉式单例 public class Singleton { private static Singleton singleton = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return singleton; } }
饿汉式是线程安全的,因为虚拟机只会装载一次,在装载类的时候不会发生并发。
没有经过内部类处理,这种方式最主要的缺点就是一旦我访问了Singleton1的任何其他的静态域,就会造成实例的初始化,而事实是可能我们从始至终就没有使用这个实例,造成内存的浪费。
改成使用静态的内部类作为单例
public class Singleton { //1 私有化构造函数,内部控制创建实例的个数 private Singleton(){} //2 定义方法为客户端提供类实例 //3 需要定义成类方法,加static public static Singleton getIntance(){ return SingletonInstace.instance; } //静态的内部类作为实例,一个类的静态属性只会在第一次加载类时初始化 private static class SingletonInstace{ static Singleton instance = new Singleton(); } }
类级内部类:有static修饰的成员式内部类。如果没有static修饰的成员式内部类成为对象级内部类。
类级内部类相对于外部类的static成分,与外部不存在依赖关系。
类级内部类中相当于其外部类的成员,只有在第一次被使用的时候才会被加载。