特创论
来源:互联网 发布:美工抠图总结 编辑:程序博客网 时间:2024/05/01 14:42
有时候,对于一个类来说,跟踪其创建出来的实例个数会非常有用,其典型实现是通过它的构造器递增一个私有静态字段来完成的。
public class Creator {public static void main(String[] args) {for(int i = 0; i < 100; i++)Creature creature = new Creature();System.out.println(Creature.numCreated());}}class Creature {private static long numCreated = 0;public Creature() {numCreated++;}public static long numCreated() {return numCreated;}}
这个程序会打印什么呢?
因为循环一共创建了100次,所以应该打印100。其实该程序根本不能编译。因为在main方法中的循环中,只有一条局部变量声明语句,而JLS[JLS 14.4]规定在for,while,do循环中不允许重复执行局部变量声明语句,局部变量声明语句只能放在语句块中,也就是放在大括号中。另外,由于创建了对象并没有使用,因此,没有必要保存其引用,在适当时机GC会对它进行垃圾回收。
改进后的代码如下:
public class Creator {public static void main(String[] args) {for(int i = 0; i < 100; i++) new Creature();System.out.println(Creature.numCreated());}}class Creature {private static long numCreated = 0;public Creature() {numCreated++;}public static long numCreated() {return numCreated;}}
这样编译后运行,打印出了预期的值:100.
这里保存实例个数的变量类型设为long是有依据的。目的是防止溢出。因为int是有符号的整型,它的最大值为pow(2,31)-1。而一个程序每秒钟创建1亿个对象是有可能的,因此可能存在溢出现象。如果将int类型改为long,long的最大值为pow(2,63)-1,约为9.2*pow(10,18),这意味着程序在对象计数器溢出之前,不得不运行大约三千年。
另外,还需注意的是,如果在多线程中创建该对象存在线程安全性,因此此代码需对递增计数器进行同步:
class Creature {private static long numCreated = 0;public Creature() {synchronized (Creature.class) {numCreated++;}}public synchronized static long numCreated() {return numCreated;}}
如果使用的是5.0或更新的版本,可以使用AtomicLong实例,这样就无需再使用syncrhonized了:
class Creature {private static AtomicLong numCreated = new AtomicLong();public Creature() {numCreated.incrementAndGet();}public static long numCreated() {return numCreated.get();}}
总之,一个局部变量声明不能被用作for,while 或do循环中的重复执行语句,它作为一条语句只能出现在一个语句块中。另外,在使用一个变量来对实例的创建进行计数时,要使用long类型而不是int类型的变量,以防止溢出。最后,如果你打算在多线程中创建实例,要么将对实例计数器的访问进行同步,要么使用一个AtomicLong类型的计数器。
- 特创论
- Java解惑 55 -- 特创论
- Java解惑 -- 读书笔记 -- 类迷题 -- 55 -- 特创论
- 特创论--考考你对Java语句块的理解
- nginx 配置 详解(待指点/更新)
- 8051单片机I/O引脚工作原理(P2端口修改指明)
- 数据迁移:RAC 下开启关闭归档
- C语言学习(六)指针1 概念
- GetPrivateProfileInt
- 特创论
- HDOJ 1251 -- 统计难题 Trie
- 超链接的路径中含有中文页面无法访问的问题。
- HDOJ - 4414 (Finding crosses)
- hdu1228
- android:visibility
- form表单字段元素对象实例(一)— —当将焦点切换到密码框时,密码输入框上将发生onFocus事件。
- ZJUT 1204 01串排序
- 有2n个硬币和一个天平,其中有两个假硬币一个质量为m+1,一个质量为m-1,其余质量都为m,用O(logn)的时间复杂度找到这两个假硬币。