# Anführungszeichen in Java



## Leutnant (19. Nov 2010)

Hallo Leute,

da meine bisherige Google-Suche erfolglos blieb(liegt wahrscheinlich eh an mir) wollte ich euch fragen was es mit "leeren" Anführungzeichen auf sich hat, also Anführungszeichen, ohne dass zwischen denen was steht

z.B. bei System.out.Println(<irgendwas> + " " + <irgendwas anderes>)

oder z.B. bei if(tmp == ' ')

wär schön, wenn ihr mir helfen würdet...

mfg Leutnant


----------



## Clahboid (19. Nov 2010)

Vielleicht wirds mit diesem Beispiel deutlich:

```
public class Main {

	public static void main(String[] args){
		int a=2, b=3;
		System.out.println(a+b);
		System.out.println(a+""+b);
	}
	
}
```


----------



## tfa (19. Nov 2010)

Zwischen deinen Anführungszeichen steht ein Leerzeichen. Das wäre ganz einfach ein String oder ein char, der nur aus einem Leerzeochen besteht.

```
""
```
 gibt es auch - ein String aus null Zeichen, der Leerstring eben.


----------



## Terep (19. Nov 2010)

" " ist ein Leerzeichen.

zum Beispiel:

String name1 = "Leutnant"
String name2 = "Guck"

System.out.println ( name1 + " " + name2);

Leutnant Guck

Terep


----------



## Leutnant (19. Nov 2010)

mhm ok, also würde dieser dann bei der ausgabe einfach nicht erscheinen und den gleich einfluss auf z.B. die Ausgabe haben als stünde dieser nicht da?


----------



## bone2 (19. Nov 2010)

Leutnant hat gesagt.:


> Hallo Leute,
> z.B. bei System.out.Println(<irgendwas> + " " + <irgendwas anderes>)


edit: 
	
	
	
	





```
" "
```
 ist ein einzelnes leerzeichen, einfach um die beiden ausgaben optisch lesbar zu trennen


```
' '
```
 ist ein leerzeichen als char



```
""
```
 ist ein String mit länge 0
ist aber meist einfach nur schlecht programmiert, bzw für anfänger die noch überhaupt keine ahnung haben.
damit kann man dem system umständlich sagen, das es <irgendwas anderes> zum String machen soll


----------



## Leutnant (19. Nov 2010)

Ahh ok, habs verstanden, danke euch...:toll:


----------



## hansmueller (19. Nov 2010)

Hallo,

schau dir mal an, was bei folgendem kleinen Programm rauskommt:


```
public class Stringversuch
{	
	public static void main(String[] args)
	{
		String x1 = new String();
		String x2 = "";
		String x3 = null;
		
		System.out.println("Auf null prüfen:");
		System.out.println("x1: " + (x1 == null));
		System.out.println("x2: " + (x2 == null));
		System.out.println("x3: " + (x3 == null));
		
		System.out.println("Auf isEmpty prüfen:");
		System.out.println("x1: " + x1.isEmpty());
		System.out.println("x2: " + x2.isEmpty());
				
		//System.out.println("x3: " + x3.isEmpty());
		
		System.out.println("Die Länge ausgeben:");
		System.out.println("x1: " + x1.length());
		System.out.println("x2: " + x2.length());
		
		//System.out.println("x3: " + x3.length());		
	}
}
```

Wenn du die Auskommentierungen weg machst, fliegt eine NullPointException.

MfG
hansmueller


----------



## Final_Striker (19. Nov 2010)

Der Sinn von dem leeren "" Anführungszeichen ist in dem ersten Beispiel von oben finde ich gut dargestellt.


```
public class Main {

	public static void main(String[] args){
		int a=2, b=3;
		System.out.println(a + b); // Ausgabe:   5
		System.out.println("" + a + b); // Ausgabe:  23
	}
	
}
```

Im ersten Fall wird der Ausdruck zunächst berechnet und dann ausgegeben.
Im zweiten Fall wird der Ausdruck als String interpretiert und die Zahlen werden einfach angehängt.


----------



## bone2 (19. Nov 2010)

Final_Striker hat gesagt.:


> Der Sinn von dem leeren "" Anführungszeichen ist in dem ersten Beispiel von oben finde ich gut dargestellt.



sollte aber nie so gemacht werden


----------



## Landei (19. Nov 2010)

Sagt wer?


----------



## Eldorado (19. Nov 2010)

Ich sehe auch keinen Grund, warum man es so nicht machen sollte... Ich denke nicht, dass es wenn überhaupt nen großen Performance-Unterschied macht...aber wenn ihr ein Gegenbeispiel habt, dann nur her damit


----------



## bone2 (19. Nov 2010)

es werden unnütze objekte erzeugt. warum sollte man das wollen wo es etliche bessere wege gibt


----------



## Final_Striker (19. Nov 2010)

bone2 hat gesagt.:


> es werden unnütze objekte erzeugt.



Nein, denn das wird von Compiler weg optimiert. ;-)

edit:

daraus wird dann:


```
public static void main(string args[])
{
   int a = 2;
   int b = 3;

   System.out.println(a + b);
   System.out.println((new StringBuilder()).append(a).append(b).toString());
}
```


----------



## hdi (19. Nov 2010)

> Nein, denn das wird von Compiler weg optimiert



Da muss gar nix weg optimiert werden. Strings die man ohne Konstruktor erzeugt, wie eben einfach ein "" landen im sogenannten String Constant Pool. Du kannst das tausend mal in den Code schreiben und es bleibt trotzdem immer bei genau einem Objekt, da bei dieser String-Erzeugung der Pool erst nach einem String mit selbem Inhalt durchsucht wird. Wird er gefunden, wird darauf referenziert und kein neuer String erstellt.

Anders wär's dann wenn man new String("") hätte. Hier würden wirklich immer neue Objekte erstellt werden, dazu würde ich auch nicht raten (Wobei der GC seine Arbeit da bestimmt auch gut macht)

edit: bzw kann sein dass in letzterem Fall dann diese Optimierung vom Compiler vorgenommen wird.


----------



## bone2 (19. Nov 2010)

[c]System.out.println("" + a + b);[/c] macht der compiler zu [c]System.out.println(String.valueOf(a) + String.valueOf(b));[/c]?

ich brauch unbedingt mehr stunden pro tag um alles zu lernen...^^

@hdi was denn nun  beides?


----------



## hdi (19. Nov 2010)

> @hdi was denn nun beides?



Strings die ohne Konstruktor erzeugt werden gibt es pro Zeichenkette genau einen im Speicher, egal wie oft du das in den Code schreibst.

Bei allen Strings die per Konstruktor erzeugt werden findet dann wohl so ne Optimierung statt von der ihr redet, das weiss ich nicht so genau.

edit: Also alles was ich sagen will ist: Wenn man keinen guten Grund dafür hat, einen String per Konstruktor zu erzeugen, sollte man ihn IMMER ohne Konstruktor erzeugen. So ist sichergestellt dass nur genau soviel Speicher belegt wird wie gerade so nötig.


----------



## nrg (19. Nov 2010)

hdi hat schon recht.

was man imho vermeiden soll sind so sachen wie

String s = "";
for (int i = 0; i < 10000; i++)
s = s + i;

das wird aber dann wirklich "weg optimiert" und macht auch Sinn . finde man sollte aber manche sachen explizit tun


----------



## hdi (19. Nov 2010)

Ja in so einem Fall würd ich auch ein 
	
	
	
	





```
System.gc()
```
 hinter die Schleife hängen. Auch wenn jetzt bestimmt Leute kommen die mir sagen dass ich ihnen erstmal beweisen soll dass es etwas bringt, und ich kläglich daran scheitern würde


----------



## Noctarius (19. Nov 2010)

hdi hat gesagt.:


> Ja in so einem Fall würd ich auch ein
> 
> 
> 
> ...



Beweise mir, dass es etwas bringt und scheiter kläglich daran


----------



## nrg (19. Nov 2010)

kleine Beispiel zu Literale und Pool:


```
public static void main(String[] args) {
		String[] array = new String[100];
		for (int i = 0; i < array.length; i++)
			array[i] = "";
		
		for (int i = 0, j = array.length-1; i < array.length/2; i++)
			System.out.println(array[i] == array[j--]);
	}
```

was hier instanziiert wird ist lediglich 1 String Objekt (bzw. 2, weil das "true" ja auch zu einem wird und afaik im pool landet - oder nicht?)

edit: um den Vergleich zu sehen könnte man dann auch mal array_ = new String(""); schreiben_


----------



## hdi (19. Nov 2010)

> bzw. 2, weil das "true" ja auch zu einem wird und afaik im pool landet - oder nicht?


edit: Ja - und eine Sache ist noch ganz interessant: Strings im Pool werden vom GC niemals entfernt! Die bleiben über die komplette Laufzeit im Speicher bestehen, selbst wenn sie nicht referenziert werden.

(Was ich davor geschrieben hab war Bullshit, hatte nich dran gedacht dass bei solchen Vergleichen sowieso max. 2 Strings "true" und "false" im Pool angelegt werden)


----------



## nrg (19. Nov 2010)

hm. also da bin ich nicht deiner Meinung. Finde es gibt nie einen Grund einen String mit new zu instanziieren...

Bei dem Beispiel hätten wir dann _1 Leerstring zur kompletten Laufzeit im Pool_* vs.* _100 Leerstrings solange aufm Heap od. Stack bis der GC sich mal dazu bequemt anzufangen_. da ist mir Option 1 lieber...

edit: bezog sich auf hdi's post vor seinem edit


----------



## hdi (19. Nov 2010)

@nrg wie gesagt das war bullshit, wobei ich mich nicht auf das +"" bezogen hab sondern auf das "true". Also nochmal ganz klar: Ja, bei dieser Sache um die es hier geht auf jeden Fall OHNE new arbeiten.


----------



## nrg (19. Nov 2010)

mich würde noch das Beispiel interessieren, bei dem new String(...) Sinn macht. also ich kenne ehrlich gesagt keins.


----------



## hdi (19. Nov 2010)

> mich würde noch das Beispiel interessieren, bei dem new String(...) Sinn macht. also ich kenne ehrlich gesagt keins.


Sagen wir mal du willst ne Beziehung zwischen zwei Instanzen dadurch bestimmen ob sie den selben "Vater" haben oder weiß der Geiger.. Und das ist halt jetzt ein String. Du willst das Risiko nich eingehen dass zwei Väter zufälligerweise die selbe Zeichenkette haben, zB weil sie zufällig erzeugt werden und der Fall eintreffen könnte, daher prüfst du das nicht per equals() sondern per Identität:


```
data1.getParent() == data2.getParent();
```

Liefert false auch falls die zufälligerweise die selbe Zeichenkette haben, aber halt doch nich das selbe sind.

Ob dieses Beispiel krass herkonstruiert ist? Ja. Und? Lass mich doch in Ruhe .. ^^


----------



## Noctarius (19. Nov 2010)

nrg hat gesagt.:


> mich würde noch das Beispiel interessieren, bei dem new String(...) Sinn macht. also ich kenne ehrlich gesagt keins.



Selber schreiben eher selten, die APIs brauchen es aber schon, oder wie kommt dein String aus der Textdatei in ein Stringobjekt? =)


----------



## hdi (19. Nov 2010)

> die APIs brauchen es aber schon, oder wie kommt dein String aus der Textdatei in ein Stringobjekt? =)


Versteh ich jetzt nicht.. Du meinst da wird auf die Erzeugung ohne new verzichtet eben weil solche Strings zur Laufzeit nicht mehr aus dem Speicher geräumt werden? Ist ja nicht so dass Sun die Option der Erzeugung ohne new nicht hat..


----------



## Noctarius (19. Nov 2010)

Nein gerade da braucht man eine Konstruktor-Instanzierung, z.B. [c]new String(byteArray);[/c]


----------



## tfa (19. Nov 2010)

Ja, aber [c]new String(string);[/c] ist Blödsinn und kann immer weggelassen werden.


----------



## Noctarius (19. Nov 2010)

tfa hat gesagt.:


> Ja, aber [c]new String(string);[/c] ist Blödsinn und kann immer weggelassen werden.



Ok das eigentlich schon


----------



## hdi (19. Nov 2010)

> Ja, aber
> 
> 
> 
> ...


Hm wie gesagt: Solche Literale machen sich im Speicher breit und gehen nie wieder weg. Also gerade in so nem Bsp wo man ne Textdatei mit 10000 Strings einliest sollte man das lieber per new String(string) machen, damit die Dinger auch wieder wegkommen wenn der Scope endet bzw sie nicht mehr referenziert werden. Mit solchen eindeutig einmaligen Strings würd ich den Pool nich vollklatschen..


----------



## nrg (19. Nov 2010)

wohin ich jetzt den return (zb von readLine) zuweise ist doch völlig egal. darin liegt doch nur die referenz auf ein objekt, das von readLine instanziiert wurde. und ob das nun aufm pool oder heap liegt, kann ich ja garnicht mehr entscheiden....

ausser ich mach echt new String(....readLine()); was imho totaler schmarrn wäre - wenn nicht sogar doppelt gemoppelt


----------



## hdi (19. Nov 2010)

> wohin ich jetzt den return (zb von readLine) zuweise ist doch völlig egal. darin liegt doch nur die referenz auf ein objekt, das von readLine instanziiert wurde. und ob das nun aufm pool oder heap liegt, kann ich ja garnicht mehr entscheiden....



Da haste natürlich Recht! Aber sagen wir für den Fall man liest es per byte-Array ein und macht dann selber Strings daraus. Okay, wer macht das schon ^^ Naja ich wollte das ja nur mal erwähnen, denn ich wusste das bis vor kurzem nicht dass der GC den Constant Pool gar nicht bereinigen kann. Und da man als Java-Programmierer per Gewohnheit keinen Gedanken an den Speicher verschwendet kann das halt vllt in einigen, zugegeben seltenen Fällen, derbe schief gehen wenn man das nicht weiß.


----------



## nrg (19. Nov 2010)

hdi hat gesagt.:


> denn ich wusste das bis vor kurzem nicht dass der GC den Constant Pool gar nicht bereinigen kann.



das war mir jetzt aber auch neu. danke für die info

edit: aber bei permanent laufenden taskapplikationen oder services muss doch irgendwann der pool geleert werden. weiß da jemand mehr dazu?


----------



## stareagle (19. Nov 2010)

Moin,

es klang ja schon an, dass es die Verwendung von leeren Strings nicht unbedingt der unbedingt der beste Stil ist. Allerdings war diese Methodik zum Teil bis Java 1.5 (aka Java 5) bzw. 1.6 (aka Java 6) der einfachste Weg bestimmte Dinge zu erreichen. Mittlerweile gibt es aber andere Möglichkeiten.


```
System.out.println(<irgendwas> + " " + <irgendwas anderes>)
```

Wie bereits in den anderen Antworten erläutert sollen die beiden Werte als Strings interpretiert werden. Alternativ kann man z.B. 


```
System.out.printf("%i%i\n", irgendwas, irgendwasAnderes);
```

verwenden. (Das '\n' ist erforderlich das printf keinen Zeilenumbruch erzeugt). Oder, falls man das Ergebnis in einer Variable ablegen möchte:


```
String result = String.format("%i%i", irgendwas, irgendwasAnderes);
```

Intern nutzen diese Methoden die Klasse Formatter. Alternativ kann man, wenn man noch mit Java 1.4 arbeiten muss (Formatter gibt es erst seit 1.5) mit MessageFormat arbeiten.


```
if(tmp == ' ')  {
...
}
```

Hier soll geprüft werden, ob der String tmp leer ist. Alternativ kann man folgendes machen:


```
if(tmp.length == 0) {
...
}
```

Das funktioniert in jeder Version von Java. Alternativ kann man seit 1.6 folgendes machen:


```
if(tmp.isEmpty()) {
...
}
```

Weitere Details in der JavaDoc zu String, Formatter und MessageFormat.

Gruß

Stareagle


----------



## Landei (19. Nov 2010)

nrg hat gesagt.:


> mich würde noch das Beispiel interessieren, bei dem new String(...) Sinn macht. also ich kenne ehrlich gesagt keins.



Ich schon! Angenommen, du hast gerade einen zehn Kilometer langen String aus einer Datei gelesen und pickst dir jetzt ein Stückchen heraus, etwa so:


```
String riesig = loadFromFile();
String klein = riesig.substring(42, 44);
```

Jetzt kann dein Riesenstring solange nicht garbage collected werden, wie du den String klein noch referenzierst, denn substring erzeugt nicht etwa ein eigenes char-Array, sondern es verweist auf das originale, nur halt mit angepaßtem Offset und Länge. Um dieses Verhalten zu vermeiden und riesig schon ins Nirvana zu entlassen, während man mit klein noch herumdoktert, kann man einfach schreiben:


```
String riesig = loadFromFile();
String klein = new String(riesig.substring(42, 44));
```

Problem gelöst.


----------



## nrg (19. Nov 2010)

danke. das klingt plausibel.

Weisst du vllt auch eine Antwort auf die andere Frage? hdi meinte, dass der gc nicht den pool säubere. Jetzt stellt sich für mich die Frage: wann wird der Pool geleert?

angenommen man hat eine Applikation, die Tage/Wochenlang läuft. Dort werden mit Sicherheit viele Literale anfallen. Wenn sich der Pool echt nicht leert, würde ja die Anwendung nach paar Tagen mit einem PoolOverflow (oder sowas in der Art ) von der Stange kippen. Ich könnte mir vorstellen, dass der Pool einfach wieder komplett geleert wird, wenn er voll ist... Aber vllt weiß das ja jemand besser..


----------



## AwsmDude (22. Nov 2010)

hdi hat gesagt.:


> Ja in so einem Fall würd ich auch ein
> 
> 
> 
> ...



Bring das bitte keinem in deinem Kurs bei...


----------



## hdi (22. Nov 2010)

> Bring das bitte keinem in deinem Kurs bei...


Und da kommt ja auch schon der erste  Wie ich schon sagte: Mir ist bewusst dass dieser Befehl mehr eine Bitte ist und der GC seine Sache schon selbstständig gut macht. Aber es kann durchaus Situationen geben indem man nachhelfen kann. Bei allem was ich bisher gesehen hab ich gc() nämlich genauso eine "Bitte" wie es repaint() ist: In der Theorie passiert evtl nichts, aber in der Praxis? Eig immer... Und es kann hilfreich sein dem GC einen Tipp zu geben, falls nachher noch weitere größere Speicherallokationen erfolgen. 

Egal, ich kann dir keinen ordentlichen Benchmark dafür machen, genauso wie du mir keinen für eine gegenteilige Behauptung machen kannst  Also lassen wir's einfach gut sein..

PS: Und ich erwähne das in meinem Kurs übrigens auch unter dieser Bemerkung, dass man es eig. nicht verwenden muss und sollte, und es nur für so spezielle Fälle hilfreich sein _kann_ die bei 99% der Programmierer in 99% ihrer Applikationen nicht vorkommen.

PPS: Ich find's auch lustig wie solche Posts immer von "Gästen" kommen. Wenn du der GC Profi hier bist, dann zeig dich doch..


----------



## AwsmDude (22. Nov 2010)

System.gc() ist nie hilfreich.
Ich bin zwar nicht der erste, aber gut. Liest wohl die erste Seite nicht noch mal wenn es neue Beiträge gibt.
Invoking System.gc() can have serious impact | blog.codecentric.de

Hier auch direkt etwas von Sun/Oracle (auch im oberen Link verlinkt):
Chapter 4 Tuning the Java Runtime System


Kann mich übrigens nicht "zeigen", da ich kein Account habe.


----------



## hdi (22. Nov 2010)

> Ich bin zwar nicht der erste, aber gut. Liest wohl die erste Seite nicht noch mal wenn es neue Beiträge gibt.


Eigentlich schon, sorry welchen Beitrag meinst du? Den von Nocatrius? Das war ein Spaß von ihm, er hat mich ja nur zitiert um mich zu ärgern  

Zu deinen Links: Das mit dem Ausschalten der Optimierungen bei einem expliziten gc() hab ich in der Tat noch nie gehört  Also vielen Dank dafür!  :toll:


----------



## AwsmDude (22. Nov 2010)

Ich denke es war zum einen natürlich als Scherz gedacht, aber natürlich auch um zu sagen "System.gc() bringt nichts". 
Glaube nicht, dass Noctarius ein Fan von System.gc() Aufrufen ist.

Bitte.


----------



## hdi (22. Nov 2010)

Ja das war mir klar, aber eben auch dass er mir jetzt wohl keinen konkreten Beweis dafür anbringen kann  Hat er ja auch nicht gemacht.. Wir hatten die Diskussion hier halt schon öfters, vllt habe ich nich alles mitbekommen aber wie gesagt die Infos aus deinen Links waren mich absolut neu.

Ein "Fan" war ich übrigens auch nie, is nich so dass ich jedes Programm mit nem


```
args = null;
System.gc();
// just to make sure:
System.gc();
```

gestartet hätte


----------

