Frage

ich auf eine Klasse lief, die wie folgt aufgebaut wurde:

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
  }
}

Mein Verständnis mit statischen Methoden ist, dass Sie nicht Klassenvariablen in Anspruch genommen werden sollte, wenn sie nicht konstant sind, und sich nicht ändern. Stattdessen sollten Sie Parameter verwenden. Meine Frage ist, warum ist das nicht zu brechen, wenn mehrmals aufgerufen durch MyClass.doSomething tun (). Es scheint mir, wie es nicht funktionieren sollte, aber. gehen Sie wird nur einmal die if-Anweisung übergeben.

So könnte jemand mir erklären, warum dies nicht brechen?

War es hilfreich?

Lösung

Das Verfahren doSomething() und die Variable started sind sowohl statisch, so gibt es nur eine Kopie der Variablen, und es ist von doSomething(). Das erste Mal doSomething() genannt wird, started falsch ist, so setzt er started auf true und dann tut ... na ja, etwas. Die zweiten und die folgenden Zeiten es heißt, started wahr ist, so ist es zurück, ohne etwas zu tun.

Andere Tipps

Es gibt keinen Grund, warum eine statische Variable nicht funktionieren würde. Ich sage nicht, es ist eine besonders gute Praxis, aber es wird funktionieren.

Was geschehen soll, ist:

  1. Der erste Anruf wird. Die Klasse wird initialisiert, gestartet ist falsch.
  2. doSomething aufgerufen. Die if ausfällt und der Code umgeht es. gestartet wird, auf true gesetzt und die anderen Code ausgeführt wird.
  3. doSomething erneut aufgerufen. Die if Pässe und stoppt die Ausführung.

Das einzige, was zu beachten ist, dass es keine Synchronisation hier ist, also wenn doSomething () auf separate Threads unglaublich dicht beieinander genannt wurde, konnte jeder Thread als falsch lesen begann, umgehen die if-Anweisung und die Arbeit, dh es ist ein race-Bedingung.

Der Code gegeben ist nicht Thread-sicher. Der einfache Weg, diesen Code Thread-sicher zu machen, wäre so etwas wie zu tun

public class MyClass {

  private static AtomicBoolean started = new AtomicBoolean(false);

  private MyClass(){
  }

  public static void doSomething(){
    boolean oldValue = started.getAndSet(true);
    if (oldValue)
      return;
    }

    //code below that is only supposed to run
    //run if not started
  }
}

Diese sichere Thread sollte die AtomicBoolean getAndSet synchronisiert ist.

Zwar ist dies kein Problem, wenn Sie Threads nicht verwenden (bitte beachten Sie, dass eine Webapp ohne eine ganze Reihe von Themen im Umgang mit verschiedenen Anfragen können Sie sich bewusst, dass sein).

Es ist nicht besonders schön Code -. Design im allgemeinen Objektinstanzen, wo Statusänderungen verwendet werden sollte, aber es gibt nichts illegal mit ihm

  

Mein Verständnis mit statischen Methoden ist, dass Sie nicht Klassenvariablen in Anspruch genommen werden sollte, wenn sie nicht konstant sind, und sich nicht ändern.

Sie scheinen von einer Design-Richtlinie zu einem Sprachmerkmal hochgerechnet zu haben. Lesen Sie eine der vielen Java-Tutorials auf der Linie, was tatsächlich in der Sprache erlaubt. Sie können verwenden nicht endgültige statische Felder frei in statischen Methoden, aber es führt zu verfahrens anstatt objektorientierten Code.

  

Stattdessen sollten Sie Parameter verwenden.

Es ist schwer zu sehen, wie ein started Parameter verwendet werden würde - wenn der Anrufer weiß, dass der Prozess gestartet wurde, warum sie rufen Sie die Methode

?

Im statischen Methode, Sie dürfen aufrufen oder den Zugriff auf statische Member innerhalb der gleichen Klasse.

mehrere Threads Szenarien Ohne Berücksichtigung, Der erste Aufruf von doSomething die boolean statischen Variable machen zu wahren, daher wird der zweite Aufruf den Code, wenn Block auszuführen, die einfach nur die Methode verlassen.

Sie statische Methode spricht mit einer statischen Klasse variabel, so sollte es in Ordnung sein. Sie könnten denken, dieses als globale Code und eine globale Variable, tho es im Namensraum der Klasse ist.

Wenn Sie versucht, ein nicht-statisches Member-Variable zuzugreifen:

private int foo = 0;

aus der statischen Methode, der Compiler und beschweren sollte.

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!

Nun gibt es Probleme in dem obigen Code mit Thread-Sicherheit, aber davon abgesehen, scheint es, als entworfen zu arbeiten.

Denken Sie daran, die Faustregel, dass „Statische Variablen sind Klasse-Niveau Variablen und alle nicht-statische Variablen sind Beispiel: Variablen“. Dann werden Sie keine Verwirrung überhaupt haben!

d. Für die statische Variable, alle Verweise in Code auf den variablen Punkt auf denselben Speicherplatz gemacht. Und für nicht-statische Variable, neue Speicherzuweisung erfolgt immer dann, wenn neue Instanz dieser Klasse erstellt wird (so dass jeder im Code gemacht Bezug auf die Variable auf einen anderen Speicherort für den Aufruf von Klasseninstanz zugeordnet).

Der obige Code funktioniert ganz gut (es sei denn, es in einer Multithreaded-Umgebung ausgeführt wird). Warum denken Sie, sollte es brechen?

  

Mein Verständnis mit statischen Methoden ist, dass Sie nicht Klassenvariablen in Anspruch genommen werden sollte, wenn sie nicht konstant sind, und sich nicht ändern

Ich denke, nur statische Elemente zugegriffen werden kann. Es muss nicht konstant sein!

  

Meine Frage ist, warum ist dies nicht, wenn, indem Sie MyClass.doSomething mehrmals aufgerufen brechen (). Es scheint mir, wie es nicht funktionieren sollte, aber. Es wird nur ein einziges Mal die if-Anweisung gehen passieren

Per bestehenden Logik. Nur der erste Aufruf wird mit dem //code to be run Teil

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top