热门关键词:

软件开发如何防止反射,序列化和克隆的单例模式

添加时间:2019-06-24 13:59:38

来源:

浏览:

反射: 可以导致反射破坏单例类的单例属性,如下例所示:

filter_none

编辑

play_arrow


brightness_4

// Java code to explain effect of Reflection 

// on Singleton property 

  

import java.lang.reflect.Constructor; 

  

// Singleton class 

class Singleton  

    // public instance initialized when loading the class 

    public static Singleton instance = new Singleton(); 

      

    private Singleton()  

    { 

        // private constructor 

    } 

  

public class GFG  

  

    public static void main(String[] args) 

    { 

        Singleton instance1 = Singleton.instance; 

        Singleton instance2 = null; 

        try

        { 

            Constructor[] constructors =  

                    Singleton.class.getDeclaredConstructors(); 

            for (Constructor constructor : constructors)  

            { 

                // Below code will destroy the singleton pattern 

                constructor.setAccessible(true); 

                instance2 = (Singleton) constructor.newInstance(); 

                break; 

            } 

        } 

      

        catch (Exception e)  

        { 

            e.printStackTrace(); 

        } 

          

    System.out.println("instance1.hashCode():- " 

                                      + instance1.hashCode()); 

    System.out.println("instance2.hashCode():- " 

                                      + instance2.hashCode()); 

    } 

输出: - 

instance1.hashCode(): -  366712642

instance2.hashCode(): -  1829164700

运行此类之后,您将看到hashCodes不同,这意味着,创建了2个相同类的对象,并且销毁了单例模式。


克服反射问题:为了克服反射引发的问题,使用了枚举,因为java在内部确保枚举值仅实例化一次。由于Java Enum可以全局访问,因此它们可以用于单例。它唯一的缺点是它不灵活,即它不允许延迟初始化。


filter_none

编辑

play_arrow


brightness_4

//Java program for Enum type singleton 

public enum GFG  

  INSTANCE; 

由于枚举没有任何构造函数,因此Reflection无法使用它。枚举有默认的构造函数,我们不能自己调用??它们。JVM在内部处理枚举构造函数的创建和调用。由于枚举不会将其构造函数定义赋予程序,因此我们也无法通过Reflection访问它们。因此,在枚举的情况下,反射不能破坏单身属性。


序列化: - 序列化也可能导致单例类的单例属性破坏。序列化用于转换字节流的对象并保存在文件中或通过网络发送。假设您序列化单例类的对象。然后,如果您反序列化该对象,它将创建一个新实例,从而打破单例模式。

filter_none

编辑

play_arrow


brightness_4

// Java code to explain effect of  

// Serilization on singleton classes 

import java.io.FileInputStream; 

import java.io.FileOutputStream; 

import java.io.ObjectInput; 

import java.io.ObjectInputStream; 

import java.io.ObjectOutput; 

import java.io.ObjectOutputStream; 

import java.io.Serializable; 

  

class Singleton implements Serializable  

    // public instance initialized when loading the class 

    public static Singleton instance = new Singleton(); 

      

    private Singleton()  

    { 

        // private constructor 

    } 

  

  

public class GFG  

  

    public static void main(String[] args)  

    { 

        try

        { 

            Singleton instance1 = Singleton.instance; 

            ObjectOutput out 

                = new ObjectOutputStream(new FileOutputStream("file.text")); 

            out.writeObject(instance1); 

            out.close(); 

      

            // deserailize from file to object 

            ObjectInput in  

                = new ObjectInputStream(new FileInputStream("file.text")); 

              

            Singleton instance2 = (Singleton) in.readObject(); 

            in.close(); 

      

            System.out.println("instance1 hashCode:- "

                                                 + instance1.hashCode()); 

            System.out.println("instance2 hashCode:- " 

                                                 + instance2.hashCode()); 

        }  

          

        catch (Exception e)  

        { 

            e.printStackTrace(); 

        } 

    } 

输出: -  

instance1 hashCode: -  1550089733

instance2 hashCode: -  865113938

如您所见,两个实例的hashCode不同,因此单个类有2个对象。因此,这个班不再是单身。


克服序列化问题: -为了克服这个问题,我们必须实现方法readResolve()方法。


filter_none

编辑

play_arrow


brightness_4

// Java code to remove the effect of  

// Serialization on singleton classes 

import java.io.FileInputStream; 

import java.io.FileOutputStream; 

import java.io.ObjectInput; 

import java.io.ObjectInputStream; 

import java.io.ObjectOutput; 

import java.io.ObjectOutputStream; 

import java.io.Serializable; 

  

class Singleton implements Serializable  

    // public instance initialized when loading the class 

    public static Singleton instance = new Singleton(); 

      

    private Singleton()  

    { 

        // private constructor 

    } 

      

    // implement readResolve method 

    protected Object readResolve() 

    { 

        return instance; 

    } 

  

public class GFG  

  

    public static void main(String[] args)  

    { 

        try

        { 

            Singleton instance1 = Singleton.instance; 

            ObjectOutput out  

                = new ObjectOutputStream(new FileOutputStream("file.text")); 

            out.writeObject(instance1); 

            out.close(); 

          

            // deserailize from file to object 

            ObjectInput in  

                = new ObjectInputStream(new FileInputStream("file.text")); 

            Singleton instance2 = (Singleton) in.readObject(); 

            in.close(); 

          

            System.out.println("instance1 hashCode:- "

                                           + instance1.hashCode()); 

            System.out.println("instance2 hashCode:- "

                                           + instance2.hashCode()); 

        }  

          

        catch (Exception e) 

        { 

            e.printStackTrace(); 

        } 

    } 

输出: -  

instance1 hashCode: -  1550089733

instance2 hashCode: -  1550089733

以上两个哈希码都相同,因此不会创建其他实例。


克隆: 克隆是一个创建重复对象的概念。使用clone我们可以创建对象的副本。假设,我们停止克隆单个对象,然后它将创建一个副本,即有两个单例类的实例,因此该类不再是单例。

filter_none

编辑

play_arrow


brightness_4

// JAVA code to explain cloning  

// issue with singleton 

class SuperClass implements Cloneable 

  int i = 10; 

  

  @Override

  protected Object clone() throws CloneNotSupportedException  

  { 

    return super.clone(); 

  } 

  

// Singleton class 

class Singleton extends SuperClass 

  // public instance initialized when loading the class 

  public static Singleton instance = new Singleton(); 

  

  private Singleton()  

  { 

    // private constructor 

  } 

  

public class GFG 

  public static void main(String[] args) throws CloneNotSupportedException  

  { 

    Singleton instance1 = Singleton.instance; 

    Singleton instance2 = (Singleton) instance1.clone(); 

    System.out.println("instance1 hashCode:- "

                           + instance1.hashCode()); 

    System.out.println("instance2 hashCode:- " 

                           + instance2.hashCode());  

  } 

输出: -  

instance1 hashCode: -  366712642

instance2 hashCode: -  1829164700

两个不同的hashCode意味着有2个不同的单例类对象。


克服克隆问题: -要克服此问题,请覆盖clone()方法并从克隆方法CloneNotSupportedException中引发异常。现在,每当用户尝试创建单个对象的克隆时,它将抛出异常,因此我们的类仍然是单例。


filter_none

编辑

play_arrow


brightness_4

// JAVA code to explain overcome  

// cloning issue with singleton 

class SuperClass implements Cloneable 

  int i = 10; 

  

  @Override

  protected Object clone() throws CloneNotSupportedException  

  { 

    return super.clone(); 

  } 

  

// Singleton class 

class Singleton extends SuperClass 

  // public instance initialized when loading the class 

  public static Singleton instance = new Singleton(); 

  

  private Singleton()  

  { 

    // private constructor 

  } 

  

  @Override

  protected Object clone() throws CloneNotSupportedException  

  { 

    throw new CloneNotSupportedException(); 

  } 

  

public class GFG 

  public static void main(String[] args) throws CloneNotSupportedException  

  { 

    Singleton instance1 = Singleton.instance; 

    Singleton instance2 = (Singleton) instance1.clone(); 

    System.out.println("instance1 hashCode:- " 

                         + instance1.hashCode()); 

    System.out.println("instance2 hashCode:- " 

                         + instance2.hashCode());  

  } 

输出: - 

线程“main”java.lang.CloneNotSupportedException中的异常

在GFG.Singleton.clone(GFG.java:29)

在GFG.GFG.main(GFG.java:38)

现在我们已经停止用户创建单例类的克隆。如果你不想抛出异常,你也可以从clone方法返回相同的实例。


filter_none

编辑

play_arrow


brightness_4

// JAVA code to explain overcome  

// cloning issue with singleton 

class SuperClass implements Cloneable 

  int i = 10; 

  

  @Override

  protected Object clone() throws CloneNotSupportedException  

  { 

    return super.clone(); 

  } 

  

// Singleton class 

class Singleton extends SuperClass 

  // public instance initialized when loading the class 

  public static Singleton instance = new Singleton(); 

  

  private Singleton()  

  { 

    // private constructor 

  } 

  

  @Override

  protected Object clone() throws CloneNotSupportedException  

  { 

    return instance; 

  } 

  

public class GFG 

  public static void main(String[] args) throws CloneNotSupportedException  

  { 

    Singleton instance1 = Singleton.instance; 

    Singleton instance2 = (Singleton) instance1.clone(); 

    System.out.println("instance1 hashCode:- " 

                           + instance1.hashCode()); 

    System.out.println("instance2 hashCode:- "

                           + instance2.hashCode());  

  } 

输出: - 

instance1 hashCode: -  366712642

instance2 hashCode: -  366712642

现在,由于两个实例的哈希码相同,这意味着它们代表单个实例。


需要软件开发就找我们吧

用户名 Name
评论 Comment

软件开发  相关内容

——
30

2019-09

软件开发的轻量化设计模式

Flyweight模式是结构设计模式之一,因为该模式提供了减少对象数量的方式,从而改善了应用程序所需的对象结构。当我们需要创建大量相似对象(例如10 5)时,将使用Flyweight模式。轻量级物体的一个重要特征是它们是 不可变的。这意味着一旦构建它们便无法对其进行修改。为什么我… [了解更多]

30

2019-09

某石油集团油气田公司信息报送系统

实现了公司信息报送系统的稳定高效运行;满足各二级单位和三级单位对信息报送平台的使用需求,有效提高了工作效率。主要功能有:用户基本信息管理、角色权限管理,部门管理,报送栏目管理,图片作者和文字作者管理,公告管理,菜单管理,配置管理、报送信息管理,审阅人权限设置,信息搜索,信息审核、… [了解更多]

05

2019-09

奇怪的重复模板模式(CRTP)

通过奇怪的重复模板模式(CRTP)可以完全避免使用VPtr和VTable。CRTP是C ++中的一种设计模式,其中类X派生自使用X本身作为模板参数的类模板实例化。更一般地,它被称为F结合多态性。filter_none编辑play_arrowbrightness_4// Image… [了解更多]

05

2019-09

软件设计奇怪的重复模板模式(CRTP)

建议将虚函数和运行时多态性作为先决条件。下面是一个演示运行时多态性的示例程序。filter_none编辑play_arrowbrightness_4// A simple C++ program to demonstrate run-time// polymorphism#inc…… [了解更多]

02

2019-08

app开发公司的软件设计的迭代器模式

迭代器模式是一种相对简单且经常使用的设计模式。每种语言都有很多数据结构/集合。每个集合都必须提供一个迭代器,让迭代器遍历其对象。但是,在执行此操作时,应确保它不会公开其实现。假设我们正在构建一个需要我们维护通知列表的应用程序。最终,您的代码的某些部分将需要迭代所有通知。如果我们将… [了解更多]

关注

成都软件开发

  • 地 址:成都市人民南路四段成科西路三号 863国家孵化园
  • 电 话:18215 660330
  • 手机:18215 660330
  • 传 真:18215 660330
  • 邮 箱:179001057@qq.com
  • 邮政编码:610000