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

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

2018-05-29 00:35 155 查看

首先了解static 关键字

static声明的方法是静态方法,static声明的成员变量为静态成员变量。对于该类的所有对象来说,static的成员变量和static只有一份存储空间

即使没有创建该类的对象(实列),也可以使用该类static的成员变量和static方法。

  static所修饰的成员变量和静态代码块 当虚拟机对该类初始化的时候就会被创建,也就是 即使没有创建这个类的实列,java虚拟机也能根据类名在运行时数据区的方法内找到他们。(也就是说类的初始化和创建类的实列并不是一回事)

静态方法中不能使用this关键字

  这个也很好理解。当一个对象创建好之后,java虚拟机就会给它分配一个引用自身的指针:this。也就是说 this是当前对象的引用。红字部分说了 是当前对象的引用,而执行static方法的时候 对象的实列可能还没被创建,所static方法中不能引用this关键字。同理 不止是this关键字,static方法中 不可访问任何非static的成员变量。同理 非static的成员变量 在类被初始化的时候才会被创建

为什么作为程序入口的main方法是static方法

  把main()方法定义成static的静态方法,java虚拟机只要加载了main方法所属的类,就能执行main方法。而无需先创建这个类的实列

试想:如果main方法不是static的时候 运行main方法需要创建该类的实列,类的main是创建实列的入口。

补充:不管是静态方法,还是普通方法 他的字节码都位于方法区内。

为什么 static 成员变量 要和final一起用 public static final int xxx ;

  因为static关键字修饰的成员变量,程序中只有一份。多个线程同时操作的时候 会产生并发的bug。final关键字 修饰的变量不能被更改

  所以static final连用 可以防止静态变量 并发的bug。

  static 也可有ThreadLocal连用 同样可以防止线程并发的bug

利用static关键字 实现单例模式(懒汉式)

  在程序启动或单件模式类被加载的时候,单件模式实例就已经被创建。

  2.1:类的构造函数定义为private的,保证其他类不能实例化此类,

  2.2:然后提供了一个静态实例static XX  xx= new XX()并返回给调用者。

  它的好处是只在类初始化的时候创建一次实例,不会存在多个线程创建多个实例的情况,避免了多线程同步的问题。

  缺点也很明显,即使这个单例没有用到也会被创建,而且在类加载之后就被创建,内存就被浪费了。

 

public class Singleton implements Serializable{
private static final long serialVersionUID = 1L;

private static Singleton instance ;
private Singleton(){

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

public static void main(String[] args) throws Exception {
Singleton s1 = Singleton.getInstance();

ByteArrayOutputStream buf = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(buf);
o.writeObject(s1);

ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream(buf.toByteArray()));
Singleton s2 = (Singleton) in.readObject();
System.out.println(s1==s2);

}

}
View Code

解决办法: 在类中增加readResolve()方法

private Object readResolve(){
return instance;
}

如果一个类提供了readResolve()方法,重新指定反序列化的对象。

那么在执行反序列化操作时,先按照默认的方式或者用户自定义的方式进行反序列化,最后调用readResolve()方法,该方法返回的对象为反序列化的最终结果。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: