静态内部类实现单例模式

StaticInnerClass

静态内部类的外部调用

  • 静态内部类可以直接创建对象
new B.C();
  • 如果内部类不是静态的,那就得这样
B b = new B();
B.C c = b.new C();

静态内部类来实现"延时加载"的线程安全的单例模式

  • 单例模式分为饿汉式、懒汉式,其中懒汉式涉及到多线程安全问题,解决方法有加同步锁synchronized,双重检查(避免对除第一次调用外的所有调用都实行同步),静态内部类实现的单例模式等。

1. 直接添加synchronized

public class Singleton {  

    private static Singleton instance;  
    private Singleton() {  
        System.out.println("private Singleton()");  
    }
    
    public synchronized static Singleton getInstance() {
        if(instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
}

2. 双重检查实现(最常用)

public static Singleton getInstance()
{
  if (instance == null)
  {
    synchronized(Singleton.class) {
      if (instance == null) 
        instance = new Singleton();
    }
  }
  return instance;
}

3. 静态内部类实现

  • 使用静态内部类能保证线程安全的原因
  1. 由于内部静态类只会被加载一次,故该实现方式是线程安全的
  2. 类加载的初始化阶段是单线程的
  • 类加载时机
  1. 使用new,invokestatic,putstatic,getstatic指令时若该类未加载则触发
  2. 反射使用某个类时若该类未加载则触发
  3. 子类加载时若父类未加载则触发
  4. 程序开始时主方法所在的类会被加载

  • 静态内部类的懒加载应该是第一种情况。为什么外部类加载时静态内部类未加载,《effective java》里面说静态内部类只是刚好写在了另一个类里面,实际上和外部类没什么附属关系。(但直接放在外部,1. 如果设置为public访问没有限制 2. private的话访问受限)
  • 线程安全是因为,类加载的初始化阶段是单线程的,类变量的赋值语句在编译生成字节码的时候写在函数中,初始化时单线程调用这个完成类变量的赋值。

链接

静态内部类实现的单例模式

public class Singleton {    
 private Singleton() {}    
 private static class Holder {    
  // 这里的私有没有什么意义    
  /* private */static Singleton instance = new Singleton();    
 }
 public static Singleton getInstance() {    
  // 外围类能直接访问内部类(不管是否是静态的)的私有变量    
  return Holder.instance;    
 }    
}  

附 类加载顺序示例

package ktuil;

public class TestStaticInnerClass {
	public static void main(String[] args) {
		new B();
		new A.C();
	}
}

class A {
	private P p1 = new P("A--p1");
	static P p3 = new P("A--p3");

	public A() {
		System.out.println("A()");
	}

	private P p2 = new P("A--p2");
	static {
		new P("A--static");
	}
	{
		new P("A{...}");
	}

	public static class C {
		private P p1 = new P("C--p1");
		static P p3 = new P("C--p3");

		public C() {
			System.out.println("C()");
		}

		private P p2 = new P("C--p2");
		static {
			new P("C--static");
		}
		{
			new P("C{...}");
		}
	}
}

class B extends A {
	private P p1 = new P("B --p1");
	static P p3 = new P("B -- p3");

	public B() {
		System.out.println("B()");
	}

	public P p2 = new P("B -- p2");
	static {
		new P("B -- static");
	}

	{
		new P("B{...}");
	}
}

class P {
	public P(String s) {
		System.out.println(s);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值