首页 > 编程语言 >【Java】反射与单例

【Java】反射与单例

时间:2022-11-11 12:05:51浏览次数:42  
标签:反射 Singleton Java 构造方法 private static 单例


双重检验与静态内部类两种方法都可以实现延迟加载的单例模式。但是无法阻止反射破坏单例,因为反射可以无视修饰权限,直接调用构造方法创建对象,下面是一个例子:

package ThreadTest;

public class Singleton {

private Singleton(){

}
static class SingletonGen{
private static final Singleton instance = new Singleton();
}

public static Singleton getInstance(){
return SingletonGen.instance;
}


public static void main(String args[]){
Singleton s = Singleton.getInstance();
try {
Class clazz = Class.forName("ThreadTest.Singleton");
Singleton sss = (Singleton) clazz.newInstance();

System.out.println(s.hashCode());
System.out.println(sss.hashCode());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

最终两个对象的hashcode不同,说明是两个对象。

那么如何解决反射破坏呢?可以类内创建一个标志变量,在构造方法内部检测该标志变量,使得构造方法只执行一次。但是这个检测必须 是线程安全的,必须同步,那么是类锁还是对象锁?很显然是类锁,因为多线程中的反射是以类为单位进行的,所以需要类锁。

private static boolean flag = false;

private Singleton(){
synchronized (Singleton.class) {
if(!flag){
flag = true;
}else{
throw new RuntimeException("单例被破坏");
}
}
}


这样,不论以什么方式,只要是通过构造方法来破坏单例,都会被阻止。

标签:反射,Singleton,Java,构造方法,private,static,单例
From: https://blog.51cto.com/u_15873544/5844101

相关文章

  • 【Java】序列化与单例
    之前明白了线程安全且延迟加载的单例如何写,有两种,双重检验和静态内部类。然后为了防止反射破坏单例,在私有构造方法里面加入了一个同步变量的判断,确保构造方法只调用一次。......
  • 【Java】HashMap 实现原理
    Java集合框架有两个顶级接口,一个是collection接口,另一个是map接口,hashmap便是map接口的重要实现类。首先看map接口。根据map键值对的特性,接口中必然有相关的方法,主要是:Vget......
  • 【Java】concurrentHashMap
    concurrentHashMap类引入了段的概念,读操作不需要上锁,写操作只需要获取相应的段的锁即可,而非锁定全部的数据。所以map里面是一个segment的数组,segment里面才是entry的数组。m......
  • 【Java】Map 实现类
    hashmap:遍历时顺序无法保证linkedhashmap:遍历时按照插入顺序treemap:遍历时按照大小顺序linkedhashmap实现上是继承了hashmap,多了一个双向的链表记录插入顺序,重写了迭代器,基......
  • 【Java】 Set实现类
    Set是collection的子接口,对应数学中的集合。与list的最主要的区别是,set无法通过索引取值,因为set是无序的。set还有一个特性是唯一性,不能存相同的元素。第一个实现类是hashse......
  • 【Java】垃圾回收机制 GC
    GC是java中比较有特色的技术,减轻了程序员的负担。当然也是面试中的高频话题。对于垃圾回收,首先要解决的是找出哪些对象是需要回收的。第一个方法是计算引用数目,实现比较简单......
  • springboot 引入外部包的坑Lookup method resolution failed; nested exception is ja
    手动引入jar包<dependency><groupId>com.allinpay.sdk</groupId><artifactId>top-sdk-java</artifactId><version>1.0.5</......
  • java
    Java是一种编程语言和计算平台,由SunMicrosystems在1995年首次发布。它从微末起步,逐渐发展为当今数字世界中很大一部分资产所依赖的基础,是用于构建许多服务和应用程序......
  • Java之找不到或无法加载主类
    IDEA报错:错误:找不到或无法加载主类。解决方法1:原因:未能成功编译。尝试:菜单栏Build->RebuildProdject 解决方法2:原因:IDEA缓存问题。尝试:菜单栏File->Invalida......
  • Java--comparator接口与Comparable接口的区别
    1.Comparator和Comparable相同的地方他们都是java的一个接口,并且是用来对自定义的class比较大小的,什么是自定义class:如publicclassPerson{Stringname;int......