感谢 Jon、Peter 和 Upog 在我的问题上帮助我。我想展示我最初的问题的真实代码,然后展示解决它的代码,希望其他人可以从这个特殊案例中受益。
我最初的问题是我不能增加一个静态的、不可重复的计数器:
/**
* Generate numbers and increment
*/
public class BuggedGenerator {
/************** Public Constants / Factory ***********/
private static BuggedGenerator INSTANCE = null; // to contain the single instance
/**
* The single instance of BuggedGenerator.
*/
public static final BuggedGenerator READ_IN = getInstance();
public static final int GEN_ID = genID();
private static int base = 999999;
/************ Singleton SetUp ************/
/**
* Utility Constructor.
*/
private BuggedGenerator() {
super(); // unnessesary, but I always invoke super()
}
/**
* Initialize the counter singleton
*/
private static int genID() {
BuggedGenerator.SINGLETON.base += 1;
return base
}
/**
* Determine whether BuggedGenerator already has an instance
* and return that instance.
*/
public static BuggedGenerator getInstance() {
if (null == BuggedGenerator.INSTANCE) {
BuggedGenerator.INSTANCE = new BuggedGenerator();
}
return BuggedGenerator.INSTANCE;
} // end getInstance()
}
这就是我从这个实现中得到的:
> BuggedGenerator.READ_IN.GEN_ID
> 1000000
> BuggedGenerator.READ_IN.GEN_ID
> 1000000
> BuggedGenerator b = BuggedGenerator.READ_IN
> b.GEN_ID
> 1000000
当提示帮助时,我使用 AtomicInteger 类来替换 GEN_ID 实现,如 Peter 的示例所示,但我收到了有关静态初始化的编译时错误。我认为反对 OOP 太痛苦了,并将 AtomicInteger 实现为传统的单例,作为对象的属性。根据 Jon 的建议,我已经包含了整个代码而不是快照。随意使用:
/**
* Copyright 2013, Phil Reason. preason intisive com
* Permission to copy, modify, resell and or freely distribute - provided an
* exact copy of this file is explicitly accompanied and unaltered alongside
* of any distribution of works using this file or any modified version of
* this file.
*/
import java.util.concurrent.atomic.AtomicInteger;
/**
* This is a class to generate numbers for various purposes.
* @author Phil Reason
* @conceptionDate 9/6/13
* @version 1.1
* @revisionDate 9/8/13
*/
public class Generator {
/************** Constants *********************/
/**
* The single instance of Generator.
*/
public static final Generator READ_IN = getInstance();
private static Generator INSTANCE = null; // to contain the single instance
/******** Instance Vars: *******************/
private AtomicInteger counter; // construct an AtomicInteger
private int iDRange;
/************ Singleton SetUp ************/
/**
* non-public default constructor override.
*/
private Generator() {
super(); // unnessesary, but I always invoke super()
this.iDRange = 1000000; // the starting number to range increments
this.counter = new AtomicInteger(); // the AtomicInteger instance
} //END Generator()
/**
* Determine whether Generator already has an instance
* and return that instance.
*/
private static Generator getInstance() {
if (null == Generator.INSTANCE) { // upon first use...
Generator.INSTANCE = new Generator(); // construct the single instance
}
return Generator.INSTANCE; // return ony that instance
} // END Generator getInstance()
/**
* Generate non-repeating numbers. This can be useful for serializing when
* inherited serialization isn't useful or needed.
*
* Return the current count generation then increment the AtomicInteger.
* @ensure genID() >= 1000000 && genID() != genID() (never repeats a number)
*/
public int genID () {
return iDRange + counter.getAndIncrement(); // increments the sum of counter
} // END int genID()
}
这个实现的输出正是我所需要的,因为它适用于类的内存驻留的生命周期。对于该属性,我只需要在 setUp() 重新运行时在测试之间预测 JUnit 的每个增量 - 这不会从内存中取消引用静态类引用。对于我正在测试的包,这实际上对我有利。这是我从后一个工具的输出中得到的:
> Generator.READ_IN.GEN_ID
> 1000000
> Generator.READ_IN.GEN_ID
> 1000001
> Generator b = Generator.READ_IN
> b.GEN_ID
> 1000002
... and so on ...
在此实现中,AtomicInteger 与任何其他具有传统方法调用的对象一样使用,尽管是作为单例。它不仅能满足我的需要,而且还能避免破坏 OOP 设计。在我足够舒适地致力于静态工厂之前,我需要更多的练习。再次感谢三位花时间回答我的问题!〜菲尔