# Globale vs. Lokale Variablen



## steff aka sId (7. Januar 2005)

Hi ich hab einmal eine Grundsatzfrage.
Womit sollte man eher arbeiten mit globalen oder lokalen Variablen? Bzw. wo ist es sinvoll globale Variablen zu nutzen und wo ist es eher sinnvoll  lokale Variablen zu nutzen?
Greetz Steff


----------



## hpvw (7. Januar 2005)

In Java als objektorientierte Programmiersprache sollte man möglichst immer lokale bzw. private Variablen verwenden.
Static ist soweit, wie möglich, zu vermeiden, wenn man mal von der main-Methode und einigen Spezialfällen, die zum Beispiel aus den Design-Pattern-Konzepten von Gamma hervorgehen, absieht.

Oder meinst Du den Unterschied zwischen Variablen, die für die Klasse (für die Instanzen der Klasse) und welchen die innerhalb einer Funktion definiert sind? Dann sollte man nur die Variablen in die Klasse aufnehmen, die das Objekt bei weiteren Funktionsaufrufen auch braucht.


----------



## steff aka sId (7. Januar 2005)

Ja meine Frage bezieht sich auf den 2. Punkt also  mit lokalen Variablen meine ich Variablen die innerhalb einer Metode deklariert sind und mit globalen die Variablen die innerhalb der Klasse als Objektvariablen deklariert sind.
Gruß Steff


----------



## Thomas Darimont (7. Januar 2005)

Hallo!

ich denke das es eigentlich nur sehr wenige gute Gründe dafür gibt, in Java "Gloable  Variablen" -> (öffenltiche Klassenvariablen (public static TYPE foo ...) ) zu verwenden. 

1) Zur Definition von Konstanten 
2) Zur Realisierung von Singletons.

Was man dann unter "lokalen Variablen" versteht hängt dann davon ab, ob man Methoden Lokale oder "Instanz Lokale" -> Membervariablen meint. Diese unterschieden sich nämlich hinlänglich ihres Initialisierungs - und Sichtbarkeitsverhaltens.

Membervariablen werden automatisch mit ihren jeweiligen Default Werten initialisiert und Lokale Variablen eben nicht. Weiterhin sind Instanz Varaiblen über mehrere Methodenaufrufe hin sichtbar wohingegen Methoden lokale Variablen eben nur in jener Methode "leben".

Gruß Tom


----------



## hpvw (7. Januar 2005)

Auch, wenn es jetzt die Frage verfehlt:
Selbst einen Singleton würde ich ohne public static Variable machen.
Mir gefällt da das Konzept der "public static Klassenname getInstance()" - Methode in Verbindung mit einer "private static Klassenname singleInstance" besser.
So kann ich nämlich zu jeder Zeit sicher sein, dass das Singleton-Objekt initialisiert ist bzw. für den Aufruf initialisiert wird.

Ich versuche mich jetzt mal an einer möglichen Faustregel (nehmt sie auseinander oder verbessert sie, vielleicht finden wir ja eine gemeinsame Richtlinie):
Instanz-Variablen nutzt man, für Daten, die zu dem Datenstamm des Objekts gehören.
Dazu gehören Daten, die die Eigenschaften des Objekts definieren (z.B. name, vorName und haarFarbe für eine Klasse Person) und Konstanten (die als static), die als Eigenschaften für Funktionsaufrufe oder Instanzvariablen dienen (z.B. BLOND, BRUNETTE, SCHWARZ, ROT für genannte Klasse Person).
Alle anderen Variablen (z.B. Laufvariablen) gehören in die Methoden, in denen sie Verwendet werden.

Ausnahmen gibt es natürlich immer.

Gruß hpvw


----------



## Thomas Darimont (7. Januar 2005)

Hallo!

Du hast natürlich recht. Ich finde das Singleton-Pattern auf basis von privaten Klassenmembers auch besser...

Deine Fastregel kann man so stehen lassen, jedoch würde ich noch hinzufügen, dass man für Konstanten (um die Typ- und Wertsicherheit) zu behalten das Enum Pattern anwenden sollte.

Gruß Tom


----------



## hpvw (7. Januar 2005)

Thomas Darimont hat gesagt.:
			
		

> ... hinzufügen, dass man für Konstanten (um die Typ- und Wertsicherheit) zu behalten das Enum Pattern anwenden sollte.


Kommt das auch von Gamma?
Dann müsste ich die dt. Übersetzung, die ich mir wegen dem Risiko durch meine Englischkenntnisse zugelegt habe, ja verfluchen da taucht es nämlich nicht auf.
Kannst Du es vielleicht knapp erläutern? *sorryhijackingathread*
Nach der vagen Vorstellung, die ich mir gerade vom Enum-Pattern mache, würde ich Dir recht geben


----------



## Thomas Darimont (7. Januar 2005)

Hallo! 

Nochmal zu den Singletons... ich würde sogar empfehlen diese so zu Implementieren


```
/*
 * Created on 07.01.2005@17:37:18
 *
 * TODO Licence info
 */
package de.tutorials;

/**
 * @author Administrator
 * 
 * TODO Explain me...
 */
public class Singleton {
	private static Singleton instance;

	protected Singleton() {
	}

	public static Singleton getInstance() {
		if (instance == null) {
			synchronized (Singleton.class) {
				instance = new Singleton();
			}
		}
		return instance;
	}
}
```

wenn man nämlich den Konstruktor als protected deklariert kann man noch von dieser Klasse ableiten, was bei einem privaten Konstruktor nicht mehr möglich wäre.

@hpvw
Schau doch mal hier:
http://www.tutorials.de/tutorials184160.html&highlight=Enum

Gruß Tom


----------



## RedWing (7. Januar 2005)

Thomas Darimont hat gesagt.:
			
		

> Hallo!
> 
> Nochmal zu den Singletons... ich würde sogar empfehlen diese so zu Implementieren
> 
> ...




```
public Singleton getInstance();
```
  sollte aber wahrsch. static sein 

Gruß

RedWing


... Huch ... ja natürlich ;-)

Gruß Tom


----------



## hpvw (7. Januar 2005)

Sehr elegant, mit dem synchronized, da hab ich bisher immer Glück gehabt   
Ich denke auch, wie RedWing, dass Du bei getInstance wohl noch static meintest.
protected...: So langsam geht der/die/das Singleton in Synthese mit der Factory Method   

Danke für den Link mit den Enum's. Ist wohl doch noch etwas mehr, als ich im Kopf hatte.
Das sieht auf jeden Fall vernünftig und interessant aus, ist aber wohl für die meisten meiner Projekte zuviel des Guten.

Gruß hpvw


----------



## Winnetoupopper (9. Januar 2005)

Thomas Darimont hat gesagt.:
			
		

> Hallo!
> wenn man nämlich den Konstruktor als protected deklariert kann man noch von dieser Klasse ableiten, was bei einem privaten Konstruktor nicht mehr möglich wäre.



Auch wenn  der Topicbezug nur noch durch das Wort "Grundsatzfrage" hergestellt wird, muss ich hier zur Vorsicht aufrufen.
Ein protected Singleton ist schon an sich ne offensive Sache, in Java sogar fatal.

1. Erfordert das Ableiten eines Singletons das -vollkommene- Überschreiben der getInstance-Methode, ein "super" befreit hier nicht.. Das ist sehr offensiv und sollte vor allem in größeren Projekten (> 10 Entwickler) nur mit Vorsicht angewandt werden.

2. In Java wird die Sichtbarkeit "protected" leider als Ableitung von Package betrachtet (OO-technisch natürlich ne Katastrophe!), so kann die erste Direktive eines Singletons (es gibt nur EINS) ausgehebelt werden:

(wie kann man Bilder einfügen?)
http://www.pics.winnetoupopper.de/Multiton.jpg


```
package de.tutorials;

public class Singleton2Multiton 
{
	public Singleton2Multiton( int pAnzahlSingletons )
	{
		for (int i = 0; i < pAnzahlSingletons; i++)
		{
			new Singleton();
		}
	}
}
```


gruß Kev

ach ja, synchronized (Singleton.class)  ist natürlich godlike, auch ich hatte immer Glück *g*


----------



## hpvw (9. Januar 2005)

Nach längerem Nachdenken habe ich gerade meine Zweifel, ob das synchronized an der Stelle richtig schützt.
Müsste es nicht besser vor dem if stehen?
Angenommen Thread1 ruft getInstance auf, es wird eine neue Instanz erzeugt, der Konstruktur braucht aus irgendeinem Grund sehr lange (zum Beispiel verbindet er das Singleton mit einem Sever). Während dessen ruft Thread2 getInstance auf und landet innerhalb des if und wartet bis er auch das Singleton erzeugen darf...
Ich denke, ihr wisst, worauf ich hinaus will?

Gamma sieht zum Erben von Singletons 2 Möglichkeiten:
1. Alle Erben müssen der Superklasse bekannt sein und werden (einmalig beim ersten Aufruf) durch getInstance anhand einer Umgebungsvariablen ausgewählt.
2. Die Erben registrieren sich selbst und werden dadurch bei der Superklasse bekannt. Das bedingt aber, dass sie vor dem ersten Aufruf von getInstance irgendwie ausgeführt werden.

Gerade in Bezug auf Java sieht mir das noch irgendwie nach Würgaround aus.
Ich würde es so lösen:
Zwei getInstance-Methoden
1. getInstance(String type)
2. getInstance()
Die Erben werden in der Superklasse durch einen String identifiziert.
(Man muss natürlich für jeden Erben auch in der Supeklasse rumspielen.)
Es gibt einen default-Singleton (einen Erben oder die Superklasse selbst).
Das Programm erhält so die Möglichkeit, in der main-Methode einen Typ (z.B. einen Algorithmus) zu wählen und im Programm selbst kann immer die einfache getInstance-Methode verwendet werden.
Ist natürlich auch nur ein Workaround.
Das ähnelt sehr stark dem ersten Ansatz von Gamma, aber ich arbeite nicht so gern mit Umgebungsvariablen.

Gruß hpvw

PS: Ich glaube, der Thread ist entführt. Ich hoffe, die Frage wurde bereits ausreichend beantwortet, Steff?

EDIT PPS: Bilder anfügen geht glaube ich über den Button "Anhänge verwalten".


----------



## Thomas Darimont (9. Januar 2005)

Hallo!

Schaut euch doch mal diesen Artikel hier an:
//Hier wird sogar "doppelt" synchronisiert
http://www-106.ibm.com/developerworks/java/library/j-dcl.html

und hier:
http://radio.weblogs.com/0122027/stories/2003/10/20/implementingTheSingletonPatternInJava.html

Auch hier wird empfohlen den Kostruktor des Singletons als protected zu deklarieren.  Jetzt stellt sich eben die Frage, wie man bei einer Singleton Vererbungshierarchie noch die "Eindeutigkeit" dieses Singletons im System garantieren kann... in dem oben genannten Artikel wird eine Lösugsmöglichkeit (-> eine Art SingletonFactory) beschrieben. 

Ein Protected Konstruktor würde auch IMHO das Erzeugen eines Proxy's durch bytecode Manipulation zur Laufzeit erlauben. 



> 1. Erfordert das Ableiten eines Singletons das -vollkommene- Überschreiben der getInstance-Methode, ein "super" befreit hier nicht.. Das ist sehr offensiv und sollte vor allem in größeren Projekten (> 10 Entwickler) nur mit Vorsicht angewandt werden.


Wie willst du denn eine static Methode einer Klasse überschreiben? Du kannst sie zwar redefinieren jedoch ist das dann (in diesem Fall) IMHO kein Überschreiben, weil dann der Mechanismus zur "Methodenfindung zur Laufzeit über die Virtuelle Methoden Tabelle" nicht gegeben ist. -> Keine Polymorphen Methodenaufrufe.

Gruß Tom


----------



## steff aka sId (9. Januar 2005)

Noch einmal kurz zurück zum Thema  Das mit Singleton etc. ist mir schon klar und auch die benutzung von Konstanten.
Ich hab mich eigentlich nur gefragt ob man beim programmieren einer Gui eher auf Instanzvariablen zurück greifen sollte oder eher Methodenvariablen. Kleine Beispiel:

```
public class Gui {
   public Gui(){
       buildWindow();
   }

   private void buildWIndow(){
           JFrame myFrame = new JFrame();
           //und jede Menge anderer Kram für die Gui
    }
}
```
Oder ob man lieber so programmieren sollte:

```
public class Gui
    JFrame myFrame = null;
    public Gui(){
         buildWindow();
    }

    private void buildWindow(){
          myFrame = new JFrame();
          //jede Menge anderer Kram für die Gui
    }
}
```

Gruß Steff


----------

