所有分类
  • 所有分类
  • 未分类

单例模式Java实战-破坏单例的方法

简介

说明

本文介绍Java破坏单例模式的方法。

单例模式(Singleton Pattern)是指确保一个类只有一个实例,并提供一个全局访问点。破坏单例模式的话,就是说可以创建出两个或两个以上的实例。本文通过静态内部类方式进行说明。

破坏单例的方法

破坏单列模式的方式

  1. 反射
  2. 序列和反序列化
  3. 使用不同的类加载器

上边1, 2都可以用枚举来解决,具体见:此文

反射

破坏单例模式 

单例类

package org.example.a;

public class Singleton {
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    private Singleton() {
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

测试类

package org.example.a;

import java.lang.reflect.Constructor;

public class Demo {
    public static void main(String[] args) {
        Class<?> singletonClass = Singleton.class;
        try {
            Constructor c = singletonClass.getDeclaredConstructor(null);
            c.setAccessible(true);
            Object singleton1 = c.newInstance();
            Object singleton2 = c.newInstance();
            System.out.println(singleton1 == singleton2);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
}

执行结果(创建出了两个不同的实例)

false

防止反射破坏单例模式

在构造函数里防止反射。

单例类

package org.example.a;

public class Singleton {
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    private Singleton() {
        if (SingletonHolder.INSTANCE != null) {
            throw new RuntimeException("不允许通过反射创建实例");
        }
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

测试类(通过反射获得实例)

package org.example.a;

import java.lang.reflect.Constructor;

public class Demo {
    public static void main(String[] args) {
        Class<?> singletonClass = Singleton.class;
        try {
            Constructor c = singletonClass.getDeclaredConstructor(null);
            c.setAccessible(true);
            Object singleton1 = c.newInstance();
            System.out.println("singleton1 instance create successfully");
            Object singleton2 = c.newInstance();
            System.out.println("singleton2 instance create successfully");
            System.out.println(singleton1 == singleton2);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
}

执行结果

Caused by: java.lang.RuntimeException: 不允许通过反射创建实例

测试类(通过静态方法获得实例)

package org.example.a;

public class Demo {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        System.out.println("singleton create successfully");
    }
}

执行结果

singleton create successfully

防止反射破坏单例模式的原理

1.用getInstance

    调用到new Singleton()时,此时INSTANCE是null,所以不会报错。

2.用反射

    调用构造方法时,调用到Singleton.INSTANCE,然后会再new Singleton()赋值给Singleton.INSTANCE,此时,Singleton.INSTANCE不为null。

序列化与反序列化

此内容仅限VIP查看,请先
1

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录