您的位置:首页 > 编程语言 > Java开发

Java知识碎片整理(5)——static关键字与单例设计模式

2016-10-28 00:26 429 查看
static——2016/10/28

单例模式——2017/1/13

static关键字用途:

修饰静态变量

修饰静态方法,或者叫实用用法(utility method)

静态变量:

静态变量是一个类的共有性质:all objects of one class share same static fields.一个实例的静态变量变化,这个类的其他实例的该变量同时发生变化。

静态方法是通过类而非类的对象调用的方法,最典型的例子是Math类:

double x=Math.sqrt(3.9);


以及单例设计模式的类实例化方法:

public static classname getInstance()


完整的例子应该是这样的:

static的加载与执行

实际上,静态变量与静态方法使用的不同只是表象,本质是static修饰符改变了代码的加载时机。

下面的例子来说明问题:

public class StaticClass {
static{
System.out.println("run1");
}
public StaticClass(){
System.out.println("init");
}
static{
System.out.println("run2");
}
public static void main(String[] args) {
StaticClass sc=new StaticClass();
}
}


输出是:

run1
run2
init


1、每调用一次构造方法,则执行一次构造块

2、静态块只在类加载的时候加载一次

3、有多个静态变量或块时,按声明顺序加载

通过static关键词实现单例设计模式

/**
* 演示单例设计模式
* @author reus
* 1,私有化构造器,避免外部直接创建
* 2,声明私有静态的类对象,初始设置为空
* 3,创建对外的静态方法,判断对对象是否为空,如果为空,调用私有的创建方法
*/

public class Singleton {

//1,私有化构造器,避免外部直接创建
private Singleton(){

}

//2,声明私有静态的类对象,初始设置为空
private static Singleton instance=null;

//3,创建对外的静态方法,判断对对象是否为空,如果为空,调用私有的创建方法
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}

}

public class test
{
public static void main(String[] args)
{
Singleton s1=Singleton.getInstance();//调用getInstance()实例化
Singleton s2=Singleton.getInstance();
System.out.println(s1==s2);//通过输出可以看到实际上s1和s2是同一个对象
}
}


通过这样的设计,可以设定一个类只有一个实例化,这样的设计方法也叫做单例模式。这样的功能实际上也可以使用一个int型数字作为标记,然后可以是一个类实例化不超过一个或几个,但显然使用static更高端一点。

但这个设计存在一个漏洞,那就是公共实例方法不是同步方法,这意味着,如果多个线程调用这个方法,可能会出现创建了多个实例的错误情况。使用synchronized关键字,加强上述代码:

/**
* 演示单例设计模式
* @author reus
* 1,私有化构造器,避免外部直接创建
* 2,声明私有静态的类对象,初始设置为空
* 3,创建对外的静态方法,判断对对象是否为空,如果为空,调用私有的创建方法
* *用synchronized关键词强化安全性
*/

public class Singleton {

//1,私有化构造器,避免外部直接创建
private Singleton(){

}

//2,声明私有静态的类对象,初始设置为空
private static Singleton instance=null;

//3,创建对外的静态方法,判断对对象是否为空,如果为空,调用私有的创建方法
public static Singleton getInstance(){
if(instance==null){//已经有实例,直接返回,提高效率
synchronized (Singleton.class) {//*用synchronized关键词强化安全性
if(instance==null){//确保安全性
instance=new Singleton();
}
}
}
return instance;
}

}


上述代码演示的都是“懒汉式”单例模式,还有一种“恶汉式”单例模式,两者区别在于:

懒汉式:在声明私有静态的类对象,初始设置为空;

饿汉式:在类中声明静态类对象时直接初始化了一个实例。

/**
* 演示单例设计模式
* @author reus
* 1,饿汉式实现:在类中声明静态类对象时直接初始化了一个实例
* 2,在对外的实例方法中,直接返回已实例化对象
*/

class Singleton2 {

private Singleton2(){
}

//1,声明私有静态的类对象——饿汉式实现:在类中声明静态类对象时直接初始化了一个实例
private static Singleton2 instance=new Singleton2();

//2,创建对外的静态方法,判断对对象是否为空,如果为空,调用私有的创建方法
public static Singleton2 getInstance(){
return instance;
}

}


这样做确保了一定只有一个实例,安全性更有保障,但较比懒汉式存在一个问题,就是在未使用的时候,就消耗了空间,如果这个类包含很多属性,这个消耗就值得优化。因此有了下面的小改良:

/**
* 演示单例设计模式
* @author reus
* 1,饿汉式实现:在类中声明静态类对象时直接初始化了一个实例
* 2,在对外的实例方法中,直接返回已实例化对象
* **把实例包装在一个类里面,这样在Singleton只有一个SingletonHolder类的引用,、
* **只有在真正外部实例化的时候,才会开辟空间,创建单例的对象
*/

class Singleton3 {

//**把实例包装在一个类里面,这样在Singleton只有一个SingletonHolder类的引用,只有在真正外部实例化的时候,才会开辟空间,创建单例的对象
private static class Singleton3Holder{
//1,声明私有静态的类对象——饿汉式实现:在类中声明静态类对象时直接初始化了一个实例
private static Singleton3 instance=new Singleton3();
}
private Singleton3(){
}

//2,创建对外的静态方法,判断对对象是否为空,如果为空,调用私有的创建方法
public static Singleton3 getInstance(){
return Singleton3Holder.instance;
}

}


把实例包装在一个私用的工具类里面,这样在类中只有一个工具类的引用,只有在真正外部实例化的时候,才会开辟空间,创建类的实际对象。代码又一次提升了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 设计模式