3

次のように設定されたクラスに出くわしました:

public class MyClass {

  private static boolean started = false;

  private MyClass(){
  }

  public static void doSomething(){
    if(started){
      return;
    }
    started = true;
    //code below that is only supposed to run
    //run if not started
  }
}

静的メソッドに関する私の理解では、それらが定数であり、変更されない限り、クラス変数を使用しないでください。代わりに、パラメーターを使用する必要があります。私の質問は、MyClass.doSomething() を実行して複数回呼び出されたときに、これが壊れないのはなぜですか。うまくいかないように思えますが、うまくいきます。if ステートメントを一度だけ渡します。

では、なぜこれが壊れないのか、誰かが私に説明できますか?

4

9 に答える 9

6

静的変数の使用が機能しない理由はありません。特に良い習慣だと言っているわけではありませんが、うまくいくでしょう。

何が起こるべきか:

  1. 最初の呼び出しが行われます。クラスは初期化され、startedはfalseです。
  2. doSomethingが呼び出されます。ifが失敗し、コードがそれをバイパスします。startはtrueに設定され、他のコードが実行されます。
  3. doSomethingが再度呼び出されます。ifがパスし、実行が停止します。

ここで同期が行われないことに注意してください。したがって、doSomething()が非常に近くにある別々のスレッドで呼び出された場合、各スレッドはfalseとして開始され、ifステートメントをバイパスして作業を実行できます。つまり、競合状態が発生します。

于 2009-03-03T12:33:29.263 に答える
2

これは特に優れたコードではありません。通常、設計では状態が変化するオブジェクトインスタンスを使用する必要がありますが、違法なものは何もありません。

静的メソッドについての私の理解は、定数であり、変更されない限り、クラス変数を使用してはならないということです。

あなたは、設計ガイドラインから言語機能に外挿したようです。言語で実際に許可されているものについて、オンラインで利用できる多くのJavaチュートリアルの1つを読んでください。静的メソッドでは非最終静的フィールドを自由に使用できますが、オブジェクト指向コードではなく手続き型コードになります。

代わりに、パラメーターを使用する必要があります。

パラメータがどのように使用されるかを確認するのは困難startedです。呼び出し元がプロセスが開始されたことを知っている場合、なぜメソッドを呼び出すのでしょうか。

于 2009-03-03T12:33:54.473 に答える
1

静的メソッドは静的クラス変数と通信しているので、問題ないはずです。これは、クラスの名前空間にあるグローバルコードおよびグローバル変数と考えることができます。

非静的メンバー変数にアクセスしようとした場合:

private int foo = 0;

静的メソッド内から、コンパイラは文句を言うでしょうし、文句を言うべきです。

started is false - initial state.
MyClass.doSomething() - statered is now true
MyClass.doSomething() - started is STILL true

MyClass foo = new MyClass();
foo.started -> it's STILL true, because it's static
foo.doSomething() - not sure you can do this in Java, but if you can, it's be STILL TRUE!

さて、上記のコードにはスレッドセーフの問題がありますが、それを除けば、設計どおりに機能しているようです。

于 2009-03-03T12:37:02.797 に答える
1

「静的変数はクラスレベルの変数であり、すべての非静的変数はインスタンス変数である」という経験則を覚えておいてください。そうすれば、まったく混乱することはありません!

つまり、静的変数の場合、コード内で変数に対して行われるすべての参照は、同じメモリ位置を指します。また、非静的変数の場合、そのクラスの新しいインスタンスが作成されるたびに、新しいメモリ割り当てが行われます (したがって、変数へのコードで行われたすべての参照は、クラス インスタンスの呼び出しに割り当てられた別のメモリ位置を指します)。

于 2009-03-03T12:57:48.957 に答える
0

上記のコードは完全に機能します(マルチスレッド環境で実行されている場合を除く)。なぜそれが壊れるべきだと思いますか?

于 2009-03-03T12:32:34.307 に答える
0

静的メソッドに関する私の理解は、クラス変数が一定でない限り、クラス変数を使用してはならず、変更しないことです。

アクセスできるのは静的メンバーだけだと思います。一定である必要はありません!

私の質問は、MyClass.doSomething()を実行して複数回呼び出されたときに、これが壊れないのはなぜかということです。うまくいかないように思えますが、うまくいきます。ifステートメントを1回だけ通過します

既存のロジックごと。最初の呼び出しのみが//code to be runパーツを実行します

于 2009-03-03T12:33:03.430 に答える