zoukankan      html  css  js  c++  java
  • JDK设计模式之—单例模式和static关键字

    首先了解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{
        //类被搜索加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。
        private static Singleton instance = new Singleton();//static的属性,是在类定义被JVM所加载时   就初始化完毕的,是类的所有实例共有的
        private Singleton(){//私有的构造方法
            
        }
        public static Singleton getInstance(){
            return instance;
        }
        public static void main(String[] args) {
            Singleton s1 = Singleton.getInstance();
            Singleton s2 = Singleton.getInstance();
            System.out.println(s1==s2);
        }
    }
    View Code

    以下补充类的初始化过程,了解一下 类的初始化和创建类的实列区别  

    饿汉式单例模式

    当程序第一次访问单件模式实例时才进行创建。

    public class Singleton{
        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) {
            Singleton s1 = Singleton.getInstance();
            Singleton s2 = Singleton.getInstance();
            System.out.println(s1==s2);
        }
        
    }
    View Code

    注意synchronized关键字的使用,防止因为并发导致创建多个对象

    反序列化打破单例模式

    反序列化会创建一个对象,打破了单例只有一个实列的约定。

    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()方法,该方法返回的对象为反序列化的最终结果。

  • 相关阅读:
    Raspberrypi安装使用开发简要说明
    android UI之Shape详解_GradientDrawable
    智能电视前传——盒子
    Winform不用窗体之间传值
    uva 10706 Number Sequence(数学规律)
    动态规划——矩阵链相乘
    SQL Server 锁
    Azure 配置高可用的准备系列工作-建立不同区域的存储账户和建立网络!
    仿小米简约Calculator
    CentOS 中使用yum出现的“UnicodeDecodeError: 'ascii' codec”问题解决方法
  • 原文地址:https://www.cnblogs.com/ssskkk/p/9070061.html
Copyright © 2011-2022 走看看