0

「静的を使用しないでください」という叫び声をすべて読みました。これにより、OOPが減少し、単体テストが台無しになり、マルチスレッド時にコードが破損する可能性があることを理解しています。しかし、私はそれらのどれも試みていません。

ID を発行するためのパブリック静的番号ジェネレーター (複製できない番号) を含む Java シングルトン ユーティリティを構築しています。シングルトンを選択したのは、100 万を再構築する必要がなく、誰かが複数のインスタンスを逆参照しないことを心配する必要なく、プログラムの存続期間中に発行された数字を追​​跡できるようにするためです。初期化は機能しますが、最初の呼び出しを超えて増加することはありません

私はこの方法で試しました:

    public class SClass {
      public static final SClass SINGLETON = getInstance();
      ...

      public static final int GEN_ID = genID();
      private static int base = 999999;

      ...
      ...

      private static int genID() {
        SClass.SINGLETON.base += 1;
        return base
      }
    }

そして、私はこの方法で試しました:

    public class SClass {
      public static final SClass SINGLETON = getInstance();
      ... 

      public static int GEN_ID = genID();
      private int base;
      ...

      private SClass () {
        ...
        this.base = 999999;
        ...
      }

      ...
      ...

      private int genID() {
        this.base += 1;
        return base;
      }
    }

はい、すべてから「最終」を削除して試しました...

各実装では、厳密に静的に呼び出すか、前述の静的実装とオブジェクト実装の両方でインスタンス (SClass s = SClass.SINGLETON; s.Gen_ID) を使用します。最初の呼び出しと連続した呼び出しの両方で(いずれかの方法論の)「1000000」しか得られません。誰かがここで何が起こっているのか説明してくれませんか?

静的を実装する必要があるかどうかを尋ねているわけではありません (すでに静的なページがたくさんあります)。単純に、これを機能させる方法を尋ねているだけです。私はよりエレガントなソリューションを受け入れていますが..事前に感謝します!

4

3 に答える 3

0

あなたはこれを試すことができます

class SClass {
    static final AtomicInteger COUNTER = new AtomicInteger();
    final int id = 1000000 + COUNTER.getAndIncrement();
}

AtomicInteger はスレッドセーフであるため、synchronized を使用する必要はありません。

于 2013-09-08T06:46:10.130 に答える
0

私の問題を解決してくれた 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 人にもう一度感謝します。~フィル

于 2013-09-09T02:45:21.463 に答える