# static - Methoden



## javaguest456 (21. Sep 2012)

```
class HelloWorld {
public static void(String[] args) {
  System.out.println("Hello world"); 
} 
}
```

Ich bin mir nicht ganz sicher, weshalb die main()-Methode als static deklariert werden muss. 

Hier, wie ich es verstehe: 

In den Lehrbüchern heißt es: Das Schlüsselwort static ist dazu da, um Methoden aufzurufen, die nicht ans Instanzen einer Klasse gebunden sind. 


```
class Auto {
  void tuwas() {
  }
} 

Auto x = new Auto(); 
x.tuwas(); 
// Die Methode tuwas() ist gebunden an 'x', eine Instanz der Klasse 'Auto'
```

Und main() ist eben nicht an eine Instanz der Klasse HelloWorld (obiges Beispiel) gebunden - darum muss sie static sein. Richtig?!

Was ich mich jetzt aber fragen: Wann ist es noch sinnvoll oder sogar unumgänglich, eine Methode als static zu zu deklarieren? Kann mir jemand ein Beispiel geben? Danke!


----------



## Mujahiddin (21. Sep 2012)

static ist eine Klassenmethode, das hast du richtig verstanden.
die main-Methode ist die Eingangsstelle eines Javaprogramms, also muss diese als static deklariert werden - ansonsten müsste ein Objekt der Klasse (z.B. Main) erzeugt werden, um dann "main" aufzurufen.
Vielleicht wird es bei Instanz/Klassenvariablen deutlicher:


```
public class Auto {
    private static int anzahlAllerErstelltenAutos = 0; // Betrifft keine Instanz, sondern ist ein einziges Mal für die Klasse Auto vorhanden
    public final int autoID;

    public Auto() {
        autoID = anzahlAllerErstelltenAutos++;
    }
    
    public int welcheIDHatDiesesAuto() { // oder "dasWievielteAutoIstDiesesHier()", da in diesem Fall ID = Nummer der Stelle ist.
        return autoID;
    }
    
    public static int wieVieleAutosGibtEs() {
        return anzahlAllerErstelltenAutos;
    }
}
```

Verstehst du das Konzept?


----------



## Marco13 (22. Sep 2012)

javaguest456 hat gesagt.:


> Was ich mich jetzt aber fragen: Wann ist es noch sinnvoll oder sogar unumgänglich, eine Methode als static zu zu deklarieren?



Unumgänglich ist es selten. Man kann jede static-Methode in eine nicht-static verwandeln, indem man das "static" wegnimmt (und dann - falls möglich - eine Instanz erzeugt und die (dann nicht-statische) Methode darauf aufruft).

Sinnvoll ist es oft. Ich propagiere ja, dass man Methoden IMMER static machen sollte, wenn man sie ohne Verrenkungen static machen kann - also insbesondere wenn sie nicht den internen Zustand des Objektes verändern, auf dem sie aufgerufen werden. Man kann das dann meinetwegen "Utility-Methoden" nennen, und die in einer eigenen Klasse zusammenfassen. (Die Klasse "Math" ist vielleicht ein Beispiel, wenn auch kein sehr gutes für diesen Fall). Das schöne an static-Methoden ist eben, dass sie rein funktional sind. Parameter rein, Ergebnis raus. Es gibt keine ungültigen Zustände oder Vorbedingungen. Insbesondere sind sie damit auch automatisch thread-safe (das gilt aber nur, wenn man nicht auch einen statischen _Zustand_ hat, wie im Beispiel des Gotteskriegers)


----------



## Andreas29 (22. Sep 2012)

Hi,

auch wenn das eventuell ein wenig zu weit führt, sei hier doch eins noch zum Thema static angemerkt:
Man kann statische Methoden nicht überschreiben. Dies bedeutet, wenn ich eine Klasse schreibe, die z.B. eine mathematische Berechnung durchführt (meinestwegen irgendeine Zinsberechnung) kann ich sie problemlos statisch machen, solange ich von der Klasse, die diese Methode zur Verfügung stellt, nicht ableiten will. Sobald ich von der Klasse mit der statischen Methode eine Kindklasse baue und in dieser Kindklasse die Berechnung verändern will, habe ich ein Problem, weil dies nicht möglich ist.

Da ich aber oftmals nicht weiß, ob ich zu einer Utility-Klasse irgendwann mal ein Kind brauche, schreibe ich (soweit irgend möglich) keine statischen Methoden, um mir die Möglichkeiten, die mir die Objektorientierung liefert, nicht gleich wieder zu zerstören.

Nur so als Hinweis...

Grüße,
Andreas


----------



## Mujahiddin (22. Sep 2012)

Andreas29 hat gesagt.:


> Hi,
> 
> auch wenn das eventuell ein wenig zu weit führt, sei hier doch eins noch zum Thema static angemerkt:
> Man kann statische Methoden nicht überschreiben. Dies bedeutet, wenn ich eine Klasse schreibe, die z.B. eine mathematische Berechnung durchführt (meinestwegen irgendeine Zinsberechnung) kann ich sie problemlos statisch machen, solange ich von der Klasse, die diese Methode zur Verfügung stellt, nicht ableiten will. Sobald ich von der Klasse mit der statischen Methode eine Kindklasse baue und in dieser Kindklasse die Berechnung verändern will, habe ich ein Problem, weil dies nicht möglich ist.
> ...



Ich kann dir nicht zustimmen...
Die Tatsache, dass man statische Methoden nicht erben kann, ist ja gerade der Sinn daran. 
	
	
	
	





```
static
```
 bedeutet für mich nichts anderes als "Klassen-X", entweder Klassenvariable (wie bei autoID) oder Klassenmethode.
Zu deinem Zins-Beispiel:
Angenommen, du hast eine abstrakte Klasse 
	
	
	
	





```
Bank
```
, dann wäre es hier sinnvoll, eine allgemeine Funktion 
	
	
	
	





```
static BigDecimal zinsBerechnen(BigDecimal base, double percent){ ... }
```
 zu haben, die du von mir aus auch in eine Utility-Klasse schreibst. In deine Bank-Klasse kommt höchstens eine Methode 
	
	
	
	





```
abstract void monatsabrechnung();
```
 und in die Unterklassen die jeweiligen Methoden unter Verwendung von "zinsBerechnen".


----------



## Marco13 (22. Sep 2012)

Andreas29 hat gesagt.:


> Man kann statische Methoden nicht überschreiben. ...
> 
> Da ich aber oftmals nicht weiß, ob ich zu einer Utility-Klasse irgendwann mal ein Kind brauche, schreibe ich (soweit irgend möglich) keine statischen Methoden, um mir die Möglichkeiten, die mir die Objektorientierung liefert, nicht gleich wieder zu zerstören.



Bei oberflächlicher Betrachtung mag das stimmen. Ich finde, es ist schon eine Designentscheidung, ob man eine Methode statisch oder nicht statisch oder überschreibbar oder nicht überschreibbar macht. Und wie so oft sind Designentscheidungen nicht leicht - deswegen hatte ich auch mal gefragt: http://www.java-forum.org/allgemein...embermethoden-statische-utility-methoden.html . Der letzte Beitrag enthält aber schon einen Hinweis darauf, wie die "Vererbung" von static Methods in Zukunft einfacher wird, bzw. wie Vererbung und Erweiterbarkeit durch static methods in Zukunft sogar _unterstützt_ wird: Durch die "defender methods" in Java 8 wird es bald möglich sein, statische Methoden als default-Implementierungen von Methoden zu verwenden, die in Interfaces definiert sind.


----------



## nillehammer (22. Sep 2012)

Ich habe zum Thema folgende -zugegeben recht exteme- Meinung: Als *interne* Hilfsmetoden für meinen eigenen Code nutze ich statische Methoden. Mit intern meine ich, dass nur mein eigener Code sie aufruft und aufrufen kann. D.h. sie haben allerhöchstens package-Sichtbarkeit. public static Methoden vermeide ich vollends, weil ich damit zu viele Implementierungs-Details meiner API sichtbar mache und, weil sich static und extends/implements eben (noch) überhaupt nicht verträgt. Ins Extreme getrieben, habe ich in jedem meiner Packages genau eine public class mit einer public static Methode, nämlich die, mit der man sich Implementierungen der von mir definierten Interfaces holen kann, sonst nichts. Auf die Weise muss ich nur die Interfaces public machen. Sogar die Implementierungen sind nur package-Sichtbar.


----------



## Ark (22. Sep 2012)

Marco13 hat gesagt.:


> Unumgänglich ist es selten. Man kann jede static-Methode in eine nicht-static verwandeln, indem man das "static" wegnimmt (und dann - falls möglich - eine Instanz erzeugt und die (dann nicht-statische) Methode darauf aufruft).


So einfach ist das eben nicht, wie du schon selbst in Klammern hinzufügst. Das Hauptproblem ist tatsächlich, dass du zum Aufruf einer Instanzmethode eine Instanz der Klasse benötigst, ganz egal, ob du sie in der Methode tatsächlich benötigst oder nicht. Folgender Code ist zwar kein gültiges Java, aber verdeutlicht, wie man sich eine Instanzmethode als statische Methode ungefähr vorstellen kann:

```
public class Auto {

	private String name;

	// "richtige" Instanzmethode
	public final void setName(String name){
		this.name = name;
	}

	// Nachbau
	public static void setName(final Auto this, String name){
		if(this == null) throw new NullPointerException();
		this.name = name;
	}
}
```
Grob würde ich also mal sagen: Wenn du eine statische Methode erzeugst, und in der Parameterliste dieser Methode taucht ein Parameter vom Typ der eigenen Klasse auf, dann machst du was falsch.  Besser wäre es dann wahrscheinlich, die Methode nicht statisch zu machen und diesen einen Parameter quasi automatisch [c]this[/c] nennen zu lassen.

Was die Verwendung/Publizierung von statischen Methoden angeht, bin ich nillehammers Meinung: statische Methoden sollte es nur und ausschließlich zur Erzeugung von Instanzen der jeweiligen Klasse geben. (Und öffentliche Konstruktoren gehören abgeschafft!) Ansonsten sollte es gar keine statischen Methoden geben.

Warum? Es gibt da einen ganz wichtigen Grund, der mir selbst erst relativ spät klargeworden ist: Multithreading! Klassenvariablen gibt es nur einmal im gesamten System, und da kann es schnell schwierig werden, sobald mehrere Threads darauf zugreifen wollen. Besser wäre es, wenn man sich pro Thread eine Instanz erzeugen könnte, die man dann logischweise nur in diesem einen Thread verwenden kann/sollte. Eine solche Instanz könnte dann z.B. Werte zwischenspeichern, die während bestimmer Berechnungen anfallen, und auf diese Werte wieder zurückgreifen, um folgende Berechnungen zu beschleunigen.

Noch ein konkretes Beispiel: In der Dokumentation zur Methode [c]java.lang.Math.random()[/c] heißt es selbst:


> This method is properly synchronized to allow correct use by more than one thread. However, if many threads need to generate pseudorandom numbers at a great rate, it may reduce contention for each thread to have its own pseudorandom-number generator.



Und noch ein Beispiel mit Math: Es gibt nur eine Klasse Math. Aber auch nur eine Klasse StrictMath! Und was ist, wenn ich Implementierungen trigonometrischer Funktionen benötige, die zwar nicht so exakt, aber dafür viel, viel schneller sind? Tja. Dagegen könnte ich mit eigenen Math/StrictMath/MyMath-Instanzen sogar zur Laufzeit auf die Implementierung umschalten, die gerade gut genug ist.

Ark


----------



## dhalsim (22. Sep 2012)

Ein anderer wichtiger Punkt neben der nicht vorhandenen Flexibilität ist die Testbarkeit. Prozeduren (genau das sind statische Methoden im Endeffekt) lassen sich im Gegensatz zu Objekten und ihren Methoden, welche gegen Interfaces (im weiteren Sinn) programmiert wurden, nur sehr schlecht isoliert betrachten, vereinfachen und ersetzen. Sie stehen praktisch wie in Stein gemeißelt im Code.


----------



## Marco13 (23. Sep 2012)

Ark hat gesagt.:


> Folgender Code ist zwar kein gültiges Java, aber verdeutlicht, wie man sich eine Instanzmethode als statische Methode ungefähr vorstellen kann:
> ...



In Sprachen, die nicht so sehr in ihrer eigenen (VM-) Welt leben, wie Java, IST das sogar so. Ich weiß noch, dass die ersten Debugger von C++-IDEs, die erst aus C-Debuggern heraus entstanden waren, in den Methodensignaturen immer diesen ominösen zusätzlichen Zeiger als ersten Parameter hatten ???:L :idea: ...  



> Was die Verwendung/Publizierung von statischen Methoden angeht, bin ich nillehammers Meinung: statische Methoden sollte es nur und ausschließlich zur Erzeugung von Instanzen der jeweiligen Klasse geben. (Und öffentliche Konstruktoren gehören abgeschafft!) Ansonsten sollte es gar keine statischen Methoden geben.
> 
> Warum? Es gibt da einen ganz wichtigen Grund, der mir selbst erst relativ spät klargeworden ist: Multithreading!



Das Multithreading hatte ich ja explizit als ein Argument FÜR statische Methoden aufgeführt - aber mit dem Hinweis darauf, dass die Methode nichts mit einem statischen _Zustand_ zu tun haben dürfen. Statische Variablen sind GANZ schlecht, bzw. man muss höllisch aufpassen (sofern man nicht Lust hat, überall die dicke synchronized-Keule auszupacken). Statische Methoden (die nicht auf irgendeinem bäh-bäh-statischen _Zustand_ rumpfuschen) sind _immer_ Thread-Safe. Es sind rein funktionale Einheiten (und "funktional" wirklich im Sinne funktionaler Programmierung). 

Wie angedeutet (und im oben verlinkten Thread weiter ausgebreitet) kann man sagen, dass das Fehlen von Polymorphie ein Nachteil sein kann, aber ist das Argument IMHO leicht zu entkräften:

```
class ArrayList implements List
{
    public void sort()
    {
        // 200 Zeilen Code, der von der List-Implementierung unabhängig ist
    }
}

class Vector implements List
{
    public void sort()
    {
        // 200 Zeilen Code, der von der List-Implementierung unabhängig ist
    }
}
```
---->

```
class ArrayList implements List
{
    public void sort()
    {
        Lists.sort(this); // Ja, übergebe "this" ;) 
    }
}

class Vector implements List
{
    public void sort()
    {
        Lists.sort(this);
    }
}


class Lists
{
    public static void sort(List list) 
    {
        // 200 Zeilen Code, der von der List-Implementierung unabhängig ist
    }
}
```

Wenn man nun eine spezielle List-Implementierung anbieten will, bei der nicht die Standard-Sortierung verwendet werden soll, könnte man die Methode entsprechend überschreiben, und eben NICHT an die statische Methode delegieren.

(Wirkt so vielleicht etwas konstruiert, in dem anderen Thread war das etwas ausführlicher...)

Ich würde fast so weit gehen, zu sagen, dass man alle Methoden static machen könnte (selbst WENN sie eine Instanz "ihrer" Klasse übergeben bekommen müssen) wenn sie ihre Aufgabe erfüllen können, indem sie NUR auf den public-Methoden der Klasse arbeiten. Das klingt aber sehr pauschal, deswegen würde ich erst nochmal drüber nachdenken, bevor ich es _wirklich_ sage


----------



## javaguest789 (23. Sep 2012)

Zunächst erstmal vielen Dank an alle fürs Antworten. 


```
public class Auto {
    private static int anzahlAllerErstelltenAutos = 0; // Betrifft keine Instanz, sondern ist ein einziges Mal für die Klasse Auto vorhanden
    public final int autoID;
 
    public Auto() {
        autoID = anzahlAllerErstelltenAutos++;
    }
    
    public int welcheIDHatDiesesAuto() { // oder "dasWievielteAutoIstDiesesHier()", da in diesem Fall ID = Nummer der Stelle ist.
        return autoID;
    }
    
    public static int wieVieleAutosGibtEs() {
        return anzahlAllerErstelltenAutos;
    }
}
```

Danke, dein Beispiel ist sehr verständlich. Die Methode wieVieleAutosGibtEs() ist als static int deklariert, da sie eben eine Variable von diesem Typ zurückgibt. Habe ich das richtig verstanden?


----------



## Marco13 (23. Sep 2012)

javaguest789 hat gesagt.:


> Die Methode wieVieleAutosGibtEs() ist als static int deklariert, da sie eben eine Variable von diesem Typ zurückgibt. Habe ich das richtig verstanden?



Du könntest auch dort das "static" weglassen  Wie vielleicht (oder auch nicht) in den bisherigen Antworten deutlich wurde, ist ein riesiger Unterschied zwischen statischen _Methoden_ und statischen _Variablen_. Statische Variablen sollte man vermeiden, außer wenn man schon sehr genau weiß, was man tut. Schon in diesem Beispiel könnten durch die statische Variable "anzahlAllerErstelltenAutos" Fehler auftreten: Wenn zwei Threads gleichzeitig ein Auto erstellen, könnte die Variable 1 sein, obwohl schon 2 Autos erstellt wurden!

Vielleicht müßtest du nochmal genauer sagen, was die Frage ist ... falls es noch eine gibt...


----------



## Mujahiddin (23. Sep 2012)

Marco13 hat gesagt.:


> Du könntest auch dort das "static" weglassen  Wie vielleicht (oder auch nicht) in den bisherigen Antworten deutlich wurde, ist ein riesiger Unterschied zwischen statischen _Methoden_ und statischen _Variablen_. Statische Variablen sollte man vermeiden, außer wenn man schon sehr genau weiß, was man tut. Schon in diesem Beispiel könnten durch die statische Variable "anzahlAllerErstelltenAutos" Fehler auftreten: Wenn zwei Threads gleichzeitig ein Auto erstellen, könnte die Variable 1 sein, obwohl schon 2 Autos erstellt wurden!
> 
> Vielleicht müßtest du nochmal genauer sagen, was die Frage ist ... falls es noch eine gibt...



Ja, threadsicher war das nicht, war ja auch nur ein kleines Beispiel fürs Verständnis zum Unterschied static/nichtstatic
Aber ich muss dir widersprechen: Der einzige Fehler, der auftreten kann, ist lediglich, dass zwei gleichzeitig erstellte Autos die gleiche ID haben, die ID wird jedoch korrekt inkrementiert.


----------



## Marco13 (23. Sep 2012)

Mujahiddin hat gesagt.:


> Aber ich muss dir widersprechen: Der einzige Fehler, der auftreten kann, ist lediglich, dass zwei gleichzeitig erstellte Autos die gleiche ID haben, die ID wird jedoch korrekt inkrementiert.



Nun, bei Threads und Race conditions würde ich grundsätzlich nicht wetten  aber ... soweit ich weiß ist schon ein vermeintlich simples x++ nicht atomar, geschweige denn das verbunden mit einer Zuweisung. So einen counter könnte/sollte man (wie gesagt, wenn man nicht alles syncrhonized machen will) zumindest mit einem AtomicInteger (Java Platform SE 6) implementieren...


----------



## Ark (23. Sep 2012)

Mujahiddin hat gesagt.:


> Der einzige Fehler, der auftreten kann, ist lediglich, dass zwei gleichzeitig erstellte Autos die gleiche ID haben, die ID wird jedoch korrekt inkrementiert.


Hm, klingt irgendwie widersprüchlich. Wenn zweimal die gleiche ID vergeben wird (z.B. 0), dann kann doch beide Male auch nur ein um 1 zu niedriger Wert im globalen Zähler landen (im gleichen Beispiel eben 1). Wenn man also die Bedingung aufstellt, dass der globale Zähler immer die Anzahl der erzeugten Instanzen widerspiegeln muss (und diese Anzahl ist ja unabhängig davon, wie viele verschiedene IDs vergeben wurden), dann wurde dieser Zähler nicht richtig inkrementiert: Es gibt 2 Autos mit der ID 1, aber laut Zähler dürfte es nur 1 Auto geben.



Marco13 hat gesagt.:


> In Sprachen, die nicht so sehr in ihrer eigenen (VM-) Welt leben, wie Java, IST das sogar so. Ich weiß noch, dass die ersten Debugger von C++-IDEs, die erst aus C-Debuggern heraus entstanden waren, in den Methodensignaturen immer diesen ominösen zusätzlichen Zeiger als ersten Parameter hatten ???:L :idea: ...






Marco13 hat gesagt.:


> Das Multithreading hatte ich ja explizit als ein Argument FÜR statische Methoden aufgeführt - aber mit dem Hinweis darauf, dass die Methode nichts mit einem statischen _Zustand_ zu tun haben dürfen. Statische Variablen sind GANZ schlecht, bzw. man muss höllisch aufpassen (sofern man nicht Lust hat, überall die dicke synchronized-Keule auszupacken). Statische Methoden (die nicht auf irgendeinem bäh-bäh-statischen _Zustand_ rumpfuschen) sind _immer_ Thread-Safe. Es sind rein funktionale Einheiten (und "funktional" wirklich im Sinne funktionaler Programmierung).


Solche "reinen" funktional-statischen Methoden nutzen aber bei weitem nicht die Möglichkeiten, die man zur Verfügung hätte. So muss eine solche Methode bei jedem Aufruf ihren gesamten Kontext neu aufbauen (sprich: eventuell zur Berechnung notwendige Objekte erzeugen, Dinge überprüfen etc.), auch wenn es praktisch immer der gleiche ist.

Im Gegensatz dazu könnte ich aber auch einmal ein Eine-Methode-Objekt erzeugen, das bei der Instanziierung auf die konkrete Aufgabe zugeschnitten wird (sprich: der Kontext wird nur einmal aufgebaut). Dieses Objekt kann ich dann für die Aufgabe verwenden, ich muss nur noch die Werte beim Aufruf übergeben, die sich ändern (bzw. aus Sicht des Objekts ändern _könnten_), und wenn ich fertig bin, werfe ich das Objekt einfach weg. Dazu gibt's kostenlos z.B. Thread-Safety oder die Möglichkeit, im Objekt Werte zwischenzuspeichern.

Etwas krass ausgedrückt: Wenn man statische Methoden verwendet, ist man meines Erachtens sogar noch schlechter dran (was den Entwurf betrifft), als wenn man Singletons verwendet.

Ark


----------



## Marco13 (23. Sep 2012)

Ark hat gesagt.:


> Solche "reinen" funktional-statischen Methoden nutzen aber bei weitem nicht die Möglichkeiten, die man zur Verfügung hätte. So muss eine solche Methode bei jedem Aufruf ihren gesamten Kontext neu aufbauen (sprich: eventuell zur Berechnung notwendige Objekte erzeugen, Dinge überprüfen etc.), auch wenn es praktisch immer der gleiche ist.
> 
> Im Gegensatz dazu könnte ich aber auch einmal ein Eine-Methode-Objekt erzeugen, das bei der Instanziierung auf die konkrete Aufgabe zugeschnitten wird (sprich: der Kontext wird nur einmal aufgebaut). Dieses Objekt kann ich dann für die Aufgabe verwenden, ich muss nur noch die Werte beim Aufruf übergeben, die sich ändern (bzw. aus Sicht des Objekts ändern _könnten_), und wenn ich fertig bin, werfe ich das Objekt einfach weg. Dazu gibt's kostenlos z.B. Thread-Safety oder die Möglichkeit, im Objekt Werte zwischenzuspeichern.
> 
> Etwas krass ausgedrückt: Wenn man statische Methoden verwendet, ist man meines Erachtens sogar noch schlechter dran (was den Entwurf betrifft), als wenn man Singletons verwendet.



Ich finde jetzt, DAS klingt widersprüchlich: Wenn man ein Objekt erstellt, das irgendeinen "Kontext" hat (was auch immer das im Einzelfall ist) könnte es damit leichter zu Race-Conditions kommen - FALLS dieser "Kontext" durch den Aufruf irgendwie verändert wird. Wenn es nur read-only-Datenstrukturen sind, ist das natürlich kein Problem: Wenn man z.B. irgendeine Map EINmal aufbaut, und die ""statische"" Methode dann darin nachsieht, ist das natürlich Threadsicher, und es würde Sinn machen, die Map nur einmal zu erstellen. Aber vermutlich geht das jetzt langsam über zu verschiedenen Abstufungen verschiedener Umsetzungen, die man zwar (mit einigen Spekulationen und "ich-meinte-aber"s ) ausdiskutieren könnte, was aber nicht nötig ist wenn sich jeder einigermaßen über die Auswirkungen bestimmter Designentscheidungen im Klaren ist. 

Ich muß es aber wegen deines Vergleiches nochmal betonen: Ein Singleton impliziert immer* einen statischen _Zustand_ - andernfalls bräuchte man es ja nicht, sondern könnte gleich die Methoden statisch machen und sich den Umweg über getInstance sparen. Und ein statischer _Zustand_ ist schlecht, und hat IMHO nichts mit reinen statischen Methoden zu tun. Letztere sehe ich eher als atomare building blocks, aus denen man komplexere Operationen zusammenbauen kann. (Das klingt im ersten Moment vielleicht ziemlich prozedural, aber ist eher so gemeint wie z.B. die Methoden Collections#sort, Collections#max etc...)


* Es gibt auch Singletons ohne Zustand. Ich habe auch schon sowas gesehen wie

```
public class Utilities<T>
{
    abstract void doSomething(T t);

    class HundUtilities extends Utilities<Hund> { ... }
    class KatzeUtilities extends Utilities<Katze> { ... }

    public static Utilities<T> getInstance(Object object)
    {
        if (object instanceof Hund) return new ((new Utilities()).HundUtilities();
        if (object instanceof Katze) return new ((new Utilities()).KatzeUtilities();
        throwSomeException();
    }

}
```
So viel zum Thema Polymorphie: Egal wie tief mal die Latte legt, irgendjemand schafft es immernoch, den Limbo zu machen


----------



## Mujahiddin (23. Sep 2012)

Ark hat gesagt.:


> Hm, klingt irgendwie widersprüchlich. Wenn zweimal die gleiche ID vergeben wird (z.B. 0), dann kann doch beide Male auch nur ein um 1 zu niedriger Wert im globalen Zähler landen (im gleichen Beispiel eben 1). Wenn man also die Bedingung aufstellt, dass der globale Zähler immer die Anzahl der erzeugten Instanzen widerspiegeln muss (und diese Anzahl ist ja unabhängig davon, wie viele verschiedene IDs vergeben wurden), dann wurde dieser Zähler nicht richtig inkrementiert: Es gibt 2 Autos mit der ID 1, aber laut Zähler dürfte es nur 1 Auto geben.



Ich dachte eher folgendes:


```
this.autoID = zaehler++;
```

ist das gleiche wie

```
this.autoID = zaehler;
zaehler = zaehler + 1;
```

Wenn jetzt beide Threads ein Auto erstellen, passiert folgendes [extrem unwahrscheinlich]:
Thread1: 
	
	
	
	





```
this.autoID = zaehler;
```
Thread2: 
	
	
	
	





```
this.autoID = zaehler;
```
Thread2: 
	
	
	
	





```
zaehler++;
```
Thread1: 
	
	
	
	





```
zaehler++;
```

Ich denke, du meinst, dass folgendes passiert:

Thread1: 
	
	
	
	





```
zaehler = zaehler ... // hier wird der Thread gestoppt, zaehler wird im Cache gespeichert(??)
Thread2: [code]zaehler = zaehler + 1; // wenn zuvor 3, dann 4
```
Thread1: 
	
	
	
	





```
/* macht weiter */ zaehler = zaehlerFromCache + 1; // ebenfalls 4
```

Keine Ahnung, ob das möglich ist. Oder hab ich dich falsch verstanden?


----------



## Ark (23. Sep 2012)

@Mujahiddin: Du musst dir die Operationen kleinschrittiger vorstellen:

[…]
(zaehler ist jetzt 3)
Thread1: push zaehler
Thread2: push zaehler
Thread1: push 1
Thread2: push 1
Thread1: add
Thread2: add
(jetzt liegt bei beiden Threads die Zahl 4 auf dem Stapel)
Thread1: pop zaehler (schreibt seine 4 in zaehler)
(zaehler ist jetzt 4)
Thread2: pop zaehler (schreibt seine 4 in zaehler)
(zaehler ist jetzt immer noch 4)
[…]

Das [c]zaehler = zaehler + 1[/c] wird nicht atomar ausgeführt. Das grundsätzliche Problem ist dabei immer: Wie kann ich einen Wert lesen und sofort danach (ohne dass jemand dazwischenfunkt) schreiben?

Ark


----------



## Bernd Hohmann (23. Sep 2012)

Andreas29 hat gesagt.:


> auch wenn das eventuell ein wenig zu weit führt, sei hier doch eins noch zum Thema static angemerkt: Man kann statische Methoden nicht überschreiben.



Warum sollte man sie nicht überschreiben können?


```
class Test2 {
	public static void main(String args[]) throws Throwable {
		System.out.println("main von test2");
		utility();
	}

	public static void utility() {
		System.out.println("utility von test2");
	}
}
```


```
public class Test3 extends Test2 {
	public static void main(String[] args) {
		System.out.println("main von test3");
		utility();
	}

	public static void utility() {
		System.out.println("utility von test3");
	}
}
```

Du kannst "utility()" in Test3 auskommentieren und dann wird die Methode von Test2 ausgeführt.

Bernd


----------



## Mujahiddin (26. Okt 2012)

Ark hat gesagt.:


> @Mujahiddin: Du musst dir die Operationen kleinschrittiger vorstellen:
> 
> […]
> (zaehler ist jetzt 3)
> ...



Ist jetzt schon über einen Monat her, aber ich verstehe nicht ganz!

(zaehler ist jetzt 3)
Thread1: push zaehler > im CPU steht 3
Thread2: push zaehler > im CPU steht 3
Thread1: push 1 > im CPU (anderer Ort?) steht 1
Thread2: push 1 > im CPU (erster Ort?) steht 1
Thread1: add > im CPU steht 2 (1+1) und wird in einem Ort gespeichert
Thread2: add > im CPU steht 3 (2+1)

push holt ja die 
	
	
	
	





```
zaehler
```
-Variable in den CPU-Register (bei falscher Terminologie bitte korrigieren) - ein CPU hat sicherlich mehrere Registerplätze. Bei deiner Argumentation liefe es jawie folgt:

(zaehler ist jetzt 3)
Thread1: push zaehler
Thread2: push zaehler
Thread1: push 1
Thread2: push 1
Thread1: add > 3+1 = 4, steht jetzt dort, wo erst die 3 stand(?)
Thread2: add > 4+1 = 5, das heißt, es lief alles doch nach Plan...


Ich glaube, ich verstehe etwas grundsätzlich falsch...


----------



## Ark (26. Okt 2012)

Mujahiddin hat gesagt.:


> push holt ja die
> 
> 
> 
> ...


push macht eher das Gegenteil davon: einen Wert (aus einem Register) auf den Stapel schieben ("retten"). Die Argumentation über Register ist übrigens viel zu kompliziert. (Das fällt dir wahrscheinlich nicht auf, weil dir dazu wohl die Grundlagen fehlen.)

Als Einstieg in die Grundlagen sei dieser Ausschnitt aus einem Wikipediaartikel genannt: Umgekehrte Polnische Notation ? Wikipedia Noch mehr Grundlagen gibt's beim Programmieren mit Assembler sowie beim Compilerbau.



Mujahiddin hat gesagt.:


> ein CPU hat sicherlich mehrere Registerplätze.


Das stimmt typischerweise. Allerdings hilft das in der Argumentation nicht, weil jeder Thread "seine" Register hat. (Das stimmt so natürlich nicht wirklich. Tatsächlich werden die Registerinhalte immer wieder komplett ausgetauscht: Kontextwechsel ? Wikipedia)



Mujahiddin hat gesagt.:


> Ich glaube, ich verstehe etwas grundsätzlich falsch...


Jeder Thread hat seinen eigenen Stack. (Dies ist ein wesentlicher Unterschied zum Heap, den sich alle Threads teilen.) Beide Threads führen ein und dasselbe Programm aus, das in einem Teil so aussieht (vereinfacht):

```
push zaehler
push 1
add
pop zaehler
```
Die Variable zaehler liegt auf dem Heap (weil zaehler eine Variable eines Klassenobjektes ist, und Objekte liegen auf dem Heap). Mit "push zaehler" wird der Wert von zaehler auf den Stack des Threads kopiert, der gerade ausgeführt wird. "push 1" kopiert den Wert von 1 auf den jeweiligen Stack. Die Addition "add" ersetzt die beiden obersten Stackelemente (die Kopie von zaehler sowie die Kopie von 1) durch die Summe ebendieser Elemente. Und "pop zaehler" kopiert das oberste Stackelement (in dem Fall das Ergebnis der Addition) in die Variable zaehler. (Darüber hinaus entfernt das pop auch das oberste Stackelement, aber das ist gerade egal.)

Hoffentlich ist es jetzt etwas klarer geworden.

BTW: Derart puristisch "nur auf dem Stack" rechnet vielleicht der Java-Interpreter (wobei auch der kurzfristig Register benutzen wird). Erst der JIT-Compiler ersetzt diese Stackoperationen durch Operationen mit Registern. (Beim Kompilieren in Bytecode sind die Register des tatsächlich ausführenden Prozessors noch nicht bekannt, deshalb stehen in der class-Datei nur Stackoperationen.)

Ark


----------



## Mujahiddin (26. Okt 2012)

Alles klar, vielen Dank! Hab's jetzt einigermaßen verstanden.
Also du versuchst, mit Stacks anstelle von Registern im CPU zu argumentieren, hab ich Recht? Ich war im Trugschluss, dass sich die Thread diesen auch teilen!


----------



## schalentier (26. Okt 2012)

@Bernd Hohmann:

folgendes ist das Problem:


```
public class Test {
    public static class Super {
        public static String getStatic(){
            return "SuperStatic  ";
        }
        public String getInstance() {
            return "SuperInstance";
        }
        public static String getStaticWithCall() {
            return getStatic();
        }
        public String getInstanceWithCall() {
            return getInstance();
        }
    }

    public static class Sub extends Super {
        public static String getStatic() {
            return "SubStatic    ";
        }

        @Override
        public String getInstance() {
            return "SubInstance  ";
        }
    }

    public static void main(String[] args) {
        Super superInstance = new Super();
        Sub   subInstance   = new Sub();
        System.out.println("superInstance: " + superInstance.getInstance() + " / " + superInstance.getInstanceWithCall() );
        System.out.println("subInstance:   " + subInstance.getInstance()   + " / " + subInstance.getInstanceWithCall()  );
        System.out.println("Super:         " + Super.getStatic()           + " / " + Super.getStaticWithCall() );
        System.out.println("Sub:           " + Sub.getStatic()             + " / " + Sub.getStaticWithCall() );
    }
}
```

Und die Ausgabe ist:


```
superInstance: SuperInstance / SuperInstance
subInstance:   SubInstance   / SubInstance  
Super:         SuperStatic   / SuperStatic  
Sub:           SubStatic     / SuperStatic
```

Das Problem ist, dass es kein [c]this[/c] gibt auf Klassenebene. Dieses muesste naemlich der Methode [c]getStaticWithCall()[/c] mitgegeben werden.

Im Beispiel beim Aufruf in Zeile 34 waere dieses [c]this[/c] die Klasse [c]Sub[/c]. Dann ginge der Aufruf in Zeile 10 an die richtige Methode.

Aber so ist das in Java leider nicht. Besonders aergerlich ist sowas beim Schreiben von Tests fuer ne Klasse voll mit static Methoden, da man keine dieser Methoden sinnvoll mocken kann. Deshalb am besten die Finger lassen von static. ;-)


----------

