私の問題を解決してくれた 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
助けを求められたとき、Peter の例に示されているように、AtomicInteger クラスを使用して GEN_ID 実装を置き換えましたが、静的初期化に関するコンパイル時エラーを受け取りました。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 設計を壊さないようにすることもできました。静的ファクトリにコミットするのに十分なほど快適になるには、さらに練習が必要です。時間を割いて私の質問に答えてくれた 3 人にもう一度感謝します。~フィル