`

【单例】单例在全局变量中引用变成了多例

    博客分类:
  • Java
阅读更多

单例在编程中经常使用,但在全局变量中应用会出现一些问题。

 

例子:

public class Tst {
	public static void main(String[] args) {
		A.getInstance();
	}
}

class Glbl {
	static {
		System.out.println("In class GlblVars");
	}
	public static String log = "I love java.";
	public static A a = A.getInstance();
}

class A {
	static int instanceNum = 0;
	
	private A() {
		instanceNum ++;
		int n = instanceNum;
		System.out.println(n +" create instance A");
		System.out.println(Glbl.log);
		System.out.println(n +" create instance A done");
	}
	
	private static A instance;
	public static A getInstance() {
		if (instance == null) {
			System.out.println("In class A");
			instance = new A();
		}
		return instance;
	}
}

 

运行结果 写道
In class A
1 create instance A
In class GlblVars
In class A
2 create instance A
I love java.
2 create instance A done
I love java.
1 create instance A done

 

类A生成了,两个对象,因为在调用【A.getInstance();】的时候,给A初始化,A的构造函数中又使用了全局变量【Glbl.log】,这样java虚拟机就会载入类Glbl,这样就会把里面的static的变量a初始化,就又生成了一个A对象了。

 

关键点就是A的构造函数又引用了有A静态变量的类。

 

消除这个问题:

1,去除Glbl 中的静态变量A。【推荐这种因为A.getInstance();这种访问本来就是全局的了,没必要在画蛇添足。】

2,使用Glbl.a来访问A的实例,而不是【A.getInstance();】。

 

看了《Java与模式》好像采用“饿汉式单例”同样可以解决这个问题:

public class Tst {
	public static void main(String[] args) {
		A.getInstance();
	}
}
class Glbl {
	static {
		System.out.println("In class GlblVars");
	}
	public static String log = "I love java.";
	public static A a = A.getInstance();
}
class A {
	static {
		System.out.println("In class A");
	}
	static int instanceNum = 0;
	private A() {
		instanceNum ++;
		int n = instanceNum;
		System.out.println(n +" create instance A");
		System.out.println(Glbl.log);
		System.out.println(n +" create instance A done");
	}
	private static A instance = new A();
	public static A getInstance() { return instance;}
}

 

 

结果:

In class A
1 create instance A
In class GlblVars
I love java.
1 create instance A done

 

0
1
分享到:
评论

相关推荐

    singleton_crash:演示由多个动态库链接的静态库中的单例导致的崩溃

    静态库中的单例如果在多个动态库中被使用,每个动态库都会有自己的副本,这违反了单例模式的初衷——在整个应用程序中只有一个实例。 具体来说,问题可能出在以下几个方面: 1. **内存管理**:每个动态库都可能...

    Qt单例模式实现Mysql数据库的链接,增加,删除,修改,查询

    在类中,我们将实现一个静态成员函数`getInstance()`,它返回单例对象的引用。同时,我们需要私有化构造函数和拷贝构造函数,防止直接实例化和复制。 ```cpp class MySqlConnection { public: static MySql...

    Swift-MLeaksFinder腾讯开源的iOS平台的自动内存泄漏检测工具

    - 未释放的全局/静态变量:合理规划全局变量的生命周期或使用autoreleasepool。 - 单例模式:避免单例成为内存泄漏的源头,确保其持有对象的生命周期得到正确管理。 7. **最佳实践** - 使用Instruments工具进行...

    Python面试练习题目 Python面试题进阶版 Python笔试题目整理归纳 共7页.pdf

    - **设置全局变量**:在函数内部,若想修改全局变量,需先声明`global variable_name`。 - **pass语句**:在Python中,`pass`是一个空语句,通常用作占位符或作为分隔符。 了解这些Python基础知识和面试题,有助...

    Android中单例模式的一些坑小结

    这个实现看似安全,因为它在`getInstance()`方法中使用了`synchronized`关键字,但在多线程环境下仍然可能存在问题。问题出在指令重排序和内存可见性上。当多个线程同时尝试创建单例时,可能会导致对象在初始化之前...

    经典C++面试题.docx

    而LNK2005错误表示重复定义,这可能是由于全局变量或函数在多个地方定义导致的。 3. 继承和委派是两种不同的继承机制。继承是子类直接获取父类的所有属性和方法,增强了类之间的层次关系和代码重用。委派则是在创建...

    美国IT大公司面试题整理

    1. 线程终止问题:在多线程环境中,一个线程想要终止另一个线程通常可以通过共享变量来通知目标线程退出,或者使用线程中断机制,如Java中的interrupt()方法。但直接终止其他线程是不推荐的做法,因为它可能导致资源...

    宝宝树(15问).pdf

    与传统的全局变量或单例模式相比,Redux通过严格的状态不可变性和单一数据流,确保了数据的可控性和可预测性,同时也支持复杂的业务逻辑。 6. RN和原生通信:RN指的是React Native,是一个用于开发跨平台移动应用的...

    C#开发常见问题清单总结与入门常见问题.docx

    - 通过将值类型包装在Nullable中,可以在运行时检查值是否为null,从而避免空引用异常。 #### 2. 异常处理与安全性 **技巧5:合理的异常捕获与处理策略** - 在适当的层级捕获异常,避免不必要的全局异常处理。 - ...

    南京中兴软创2010年最新笔试题.doc

    【南京中兴软创2010年最新笔试题】...引用的值(即变量指向的对象)通常情况下不会改变,除非在函数内部重新赋值。 以上是笔试题中涉及的核心技术点,理解并掌握这些知识点对于准备软件开发岗位的面试和笔试至关重要。

    Objective-C面试题.pdf

    - **weak**:弱引用,不增加引用计数,当对象释放时变为`nil`。 - **copy**:拷贝对象。 - **unsafe_unretained**:不安全的未保留引用,与`weak`相似,但不会自动设置为`nil`。 6. **@autoreleasepool的理解**...

    MemoryLinkers

    另外,避免全局变量和静态变量,因为它们会延长生命周期,占用更多内存。 3. **内存限制**:`memory_limit`配置项可以设定PHP脚本的最大内存使用量,防止因无限增长导致的服务器崩溃。合理设置这个值可以确保系统...

    java面试800题

    Q0043 java相关概念 "static:静态,无需实例化,可直接引用,全局只有一份copy,修饰变量和方法 final:最终的,不可继承、不可修改,修饰变量、方法、类 volatile:volatile变量表示保证它必须是与主内存保持一致,...

    企业面试笔试题总汇v1.6重新编辑版

    当一个对象不再被任何引用所引用时,它就会变成垃圾,此时GC会自动回收这块内存空间。然而,如果某个对象本应被回收但仍然被引用着,那么这块内存就可能不会被回收,从而引发内存泄漏。 #### 单例模式的不同实现...

    C++随手笔记C++随手笔记

    - 私有继承意味着基类的公有成员在派生类中变为私有。 - 私有继承主要用于实现细节的隐藏。 #### 61. const正确性 - 使用`const`可以提高代码的正确性和可维护性。 - 在不需要修改的情况下使用`const`。 #### 62. ...

    锐明视讯校招试题

    **解析**:题目中的代码展示了静态局部变量在不同函数调用中的行为。 - `function`函数中定义了一个静态局部变量`b`,每次调用`function`时,`b`的值都会保留。 - 第一次调用`function(2)`,`b`初始化为`10`,然后...

    最近5年133个Java面试问题列表

    这意味着即使在一个多处理器系统中,当一个线程正在读取一个volatile `long`变量时,其他线程不能看到该变量的中间状态。 3. **volatile的深入理解** - **答案:** volatile关键字用于标记一个字段,表示该字段的...

    Android面试系列—目录

    - **线程**:进程中的执行单元,多个线程可以在同一进程中并发执行。 #### 20. Android中的存储方式及其适用场合 - **文件存储**:适用于小量数据存储。 - **SharedPreferences**:存储简单的键值对数据。 - **...

    各大著名it企业面试题

    - **final**: 在Java中,`final`关键字可以用于变量、方法和类。当一个类被声明为final时,它不能被继承;当一个方法被声明为final时,它不能在子类中被重写;当一个变量被声明为final时,则该变量不可变,对于基本...

Global site tag (gtag.js) - Google Analytics