try finally

Simon_Flagg

Bekanntes Mitglied
[Folgediskussion aus Java-Quiz zur Frage http://www.java-forum.org/plauderecke/22639-java-quiz-68.html#post739007

Java:
    private static int fun()
    {
        while (true)
        {
            try
            {
                return 1;
            }
            finally
            {
                return 2;
            }
        }
    }
]

ich denke schon, dass es sich kompilieren lässt, ist ja kein unerlaubtes zeugs drinnen....

meine erste vermutung wäre, dass das finally nur aufgerufen wird, wenn der try-block durch eine exception abgebrochen wird.... also sollte eig das erste return gelten.... --> gibt 1 zurück

lg
 
Zuletzt bearbeitet von einem Moderator:

Simon_Flagg

Bekanntes Mitglied
ich wollte damit ausdrücken, dass der finally-block imho nur ausgeführt wird, wenn er so weit kommt oder wenn eine exception fliegt --> meine vermutung war, dass er nicht ausgeführt wird, wenn die methode durch ein return verlassen wird

lg
 

Sonecc

Gesperrter Benutzer
soweit ich mich erinnere würde das nur dann kompilieren, wenn die Methode eine Exception weiterleitet (also throws Exception)
 

tfa

Top Contributor
Nein, finally wird immer ausgeführt - ganz zu letzt. Du kannst ja wie hier das catch auch weglassen.
In diesem Beispiel sollte also 2 zurückgeliefert werden. Ich kann das nicht testen, weil ich meine IDE so
eingestellt habe, dass so ein finally-return als Fehler angemeckert wird.

soweit ich mich erinnere würde das nur dann kompilieren, wenn die Methode eine Exception weiterleitet (also throws Exception)
Nicht jede Exception muss mit throws deklariert werden, besonders, wenn (wie hier) gar keine fliegen kann.
 

tfa

Top Contributor
Wer Eclipse benutzt, sollte in den Einstellungen unter Java->Compiler->Errors/Warnings bei "Potential programming problems" den Punkt "'finally' does not complete normally" auf "Error" setzen. Dann spart man sich vielleicht ein wenig Bugfixing.
 

Sonecc

Gesperrter Benutzer
Nicht jede Exception muss mit throws deklariert werden, besonders, wenn (wie hier) gar keine fliegen kann.
Dass nicht jede Exception mit throws deklariert werden muss ist mir klar...
Es ging sich dabei auch eher um die Aussage, dass ein Try Block ohne Catch nicht kompilierbar ist.
Dass das Finally sozusagen als Ersatz für den Catch Block ausreicht wusste ich bis dato nicht.
 
G

Gast2

Gast
Dass nicht jede Exception mit throws deklariert werden muss ist mir klar...
Es ging sich dabei auch eher um die Aussage, dass ein Try Block ohne Catch nicht kompilierbar ist.
Dass das Finally sozusagen als Ersatz für den Catch Block ausreicht wusste ich bis dato nicht.

Warum als Ersatz? Der finally Block ist doch kein Ersatz hat eine ganze andere Funktion als der catch Block.
 

Sonecc

Gesperrter Benutzer
Warum als Ersatz? Der finally Block ist doch kein Ersatz hat eine ganze andere Funktion als der catch Block.

Aus deiner Antwort schließe ich, dass du entweder nicht wirklich gelesen hast was ich geschrieben habe oder zu faul warst es zu verstehen. Aber nochmal für dich eine explizite und (hoffentlich) unmissverständliche Erklärung meiner Aussage (die vorher eigentlich auch leicht nachvollziehbar war...)

1. Beachte man das "sozusagen" (Lesen hilft da)
2. Ein Try Statement ohne Catch geht nicht.
Ein Try Block ohne Catch aber mit Finally geht. Finally ersetzt hier also den Catch Block als notwendiger Bestandteil des Try Blocks. Er dient dabei natürlich nicht als allgemeiner Ersatz des Catch blocks. Diese Aussage habe ich aber auch nie getätigt.


Das nächste mal bitte lesen was ich schreibe oder eine halbe sekunde darüber nachdenken. :rtfm:
 
G

Gast2

Gast
Aus deiner Antwort schließe ich, dass du entweder nicht wirklich gelesen hast was ich geschrieben habe oder zu faul warst es zu verstehen. Aber nochmal für dich eine explizite und (hoffentlich) unmissverständliche Erklärung meiner Aussage (die vorher eigentlich auch leicht nachvollziehbar war...)

1. Beachte man das "sozusagen" (Lesen hilft da)
2. Ein Try Statement ohne Catch geht nicht.
Ein Try Block ohne Catch aber mit Finally geht. Finally ersetzt hier also den Catch Block als notwendiger Bestandteil des Try Blocks. Er dient dabei natürlich nicht als allgemeiner Ersatz des Catch blocks. Diese Aussage habe ich aber auch nie getätigt.


Das nächste mal bitte lesen was ich schreibe oder eine halbe sekunde darüber nachdenken. :rtfm:

Klare Sätze formulieren hilft meistens auch.
Das finally ersetzt auch "sozusagen" nicht den catch Block.

Ein try braucht entweder einen catch oder einen finally Block.
 

Murray

Top Contributor
Ein try braucht entweder einen catch oder einen finally Block.
"Entweder oder" verstehen die meisten wohl im Sinne von XOR; das wäre hier aber nicht richtig, denn es kann durchaus beides geben (catch und finally). Der Vollständigkeit halber sei noch erwähnt, dass es auch mehrere catch-Blöcke geben darf.

Also: try braucht mindestens einen catch- oder einen finally-Block. Von "Ersetzen" kann da eigentlich nicht die Rede sein.
 

Andi_CH

Top Contributor
Stimmt irgendwie Marco :)

Aber:
Nein, finally wird immer ausgeführt - ganz zu letzt. Du kannst ja wie hier das catch auch weglassen.
In diesem Beispiel sollte also 2 zurückgeliefert werden. Ich kann das nicht testen, weil ich meine IDE so
eingestellt habe, dass so ein finally-return als Fehler angemeckert wird.
Meine macht eine Warnung :)

Aber WARUM wird nun 2 zurückgegeben - die Aussage "ganz am Schluss" gibt mir keinen Aufschluss.

Da wo "return" steht wird der Kontrollfluss üblicherweise verlassen und somit wäre doch return 1; "ganz der Schluss"
Was meint ihr zum Gedanken, dass sich Java zwar merkt, dass es return 1 machen sollte, aber zuerst den finally Block ausführt und dann seinen guten Vorsatz nicht mehr umsetzen kann?

(Einmal mehr bestätigt sich meine Ansicht dass mehr als ein return statement nur in abosluten Ausnahmefällen toleriert werden sollte.)

Aber es wird noch schlimmer:
fun1 führt zur Ausgabe von -1 aber das kennen wir ja schon, nur wird die Exception verschluckt ???:L - bastelt Java da einen unsichtbaren Exception-Block zwischen try und finally oder ist es wie oben? Java will zwar die Exception schmeissen, wird aber durch das
Code:
return -1
daran gehindert?
Bei fun1 muss kein
Code:
throws Exception
hingeschrieben werden und die Exeption kommt nie im main an.

Warum ist fun2 nicht kompilierbar? Das statement return -1 ist angeblich unerreichbar?

Rätsel über Rätsel ....

Java:
package com.javaforum.test;

import java.io.IOException;

public class Test2 {

	private static int getValue() throws Exception {
		System.out.print("Eingabe : ");
		int i = System.in.read();
		if (i=='0') {
			throw new Exception("Es wurde 0 eingegeben");
		}
		return i;
	}

	public static int fun1() {
		while (true) {
			try {
				return getValue();
			}
			finally {
				System.out.println("Finally");
				return -1;
			}
		}
	}

//		public static int fun2() throws Exception {
//			while (true) {
//				try {
//					return getValue();
//				}
//				finally {
//					System.out.println("Finally");
//				}
//				return -1;
//			}
//		}

	public static void main(String[] args) {
		try {
			System.out.println(fun1());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
 
S

SlaterB

Gast
Warum ist fun2 nicht kompilierbar? Das statement return -1 ist angeblich unerreichbar?
aus genau diesem Grund, ist doch erklärbar oder hast du eine Vermutung wie es erreicht werden könnte?

dass man die Zeile nur löschen/ auskommentieren muss macht es technisch zu einem Fehler der trivialen Sorte,
könnte auch automatisch behandelt werden,
dennoch schon gut dass der Compiler energisch auf dieses falsche Vorgehen hinweist

nur wird die Exception verschluckt ???:L
so läuft das eben
 

Andi_CH

Top Contributor
aus genau diesem Grund, ist doch erklärbar oder hast du eine Vermutung wie es erreicht werden könnte?

Aus genau welchem? WEISS es jemand oder stellen wir alle nur Vermutungen an?

Bevor mir nicht jemand wirklich den Kontrollfluss aufzeigt werde ich den Unterschied nicht verstehen und einfach sagen "ist so weil ist so" wird zwar im Militär öfters gemacht, ist aber niht sinnvoll.

Bewiesen ist, dass der Kontrollfluss durch das finally geht - wo geht er dann durch? Ich habe ja nur Vermutungen angestellt und das diese nicht zwingend stimmen ist auch bewiesen - ich hätte beim Urbeispiel ja auch 1 erwartet :bahnhof:

(Oder ist das dasselbe Mysterium wie z.B. das Memory Mangemant oder der GC? Da weiss auch niemand wirklich wie es funktioniert)
 
S

SlaterB

Gast
viel ist es nicht was finally so besonders macht, wird immer ausgeführt, dessen return zählt höher, Exceptions könnten übersprungen werden,
wurde alles schon genannt bzw. kann man einfach ausprobieren,
dass es daran Zweifel gibt dachte ich nicht, ja, ich versichere dir diese Eigenschaften, aber nur 'weil es so ist', erklären kann ich sie dir nicht,
genausowenig wie alle anderen Java-Syntaxen, etwa ein continue; oder break; in einer Schleife

wenn man von diesen Dingen ausgeht ist die Exception 'unerreichbar' komplett erklärt
(oder noch nicht klar? einfach den Ablauf nach-denken, welche Alternativen sorgen für Zweifel?),
zu dem Punkt gibt es also nichts mehr zu sagen, falls es dir nicht um die Erklärung der Grundfunktionen von finally geht,
die muss dann jemand anders oder das Internet liefern

> GC? Da weiss auch niemand wirklich wie es funktioniert

hast du eine konkrete Frage zur allgemeinen Funktionalität dazu? wie es intern wirklich aufgebaut ist, weiß ich auch wieder nicht,
aber was dort erreicht wird ist ja relativ klar und z.B. selber nachprogrammierbar,
es muss nur ein Thread laufen der alle Objekte und Referenzen darauf verwaltet, ab und zu aktiv wird und aufräumt, dabei am kompliziertesten noch Netze von Verknüpfungen erkennt,
nichts unmögliches für jedermann, wenn es auch sicher effiziente und weniger effiziente Umsetzungen gibt..
 
Zuletzt bearbeitet von einem Moderator:

ThreadPool

Bekanntes Mitglied
Naja es ist laut JLS so, dass das finally immer nach dem try ausgeführt wird. Und es ist wohl so wie SlaterB schon vermutete dass wenn der finally-Block normal läuft und sich dort ein return findet dieses > als das return des try-Blocks ist. Fliegt eine Exception im try-block wird das finally wohl erst ausgeführt nachdem der dafür zuständige catch-block gelaufen ist, wenn es keinen catch-Block gibt wird der aktuelle Thread beendet nachdem alle finally's gelaufen sind. D.h. es ist wohl so das wenn du in main() (deinem Beispiel) die Exception fängst das finally aus fun2() erst danach ausgeführt wird.

EDIT: Kleine Korrektur, da ich die Beispiele nicht ausgeführt hatte, zur Ausführung weshalb bei fun1() keine Exception propagiert wird hilft denke ich die JLS weiter Blocks and Statements

PS: So mysteriös ist das Speichermanagement und die Funktionalität des GC's nicht, im verlinkten Paper sind zwar nicht die Algorithmen (im feinsten Detailierungsgrad) dargelegt aber es gibt weitere Literaturhinweise. [1]

[1] http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf
 
Zuletzt bearbeitet:

_Andi91

Bekanntes Mitglied
Finally wird in der Regel IMMER zuletzt ausgeführt.

Eine Ausnahme is zB folgendes Konstrukt:

Java:
try
{
	System.exit(0);
}
finally
{
	System.out.println("test");
}

Hier findet keine Ausgabe statt und die VM wird beendet.
 

Andi_CH

Top Contributor
PS: So mysteriös ist das Speichermanagement und die Funktionalität des GC's nicht, im verlinkten Paper sind zwar nicht die Algorithmen (im feinsten Detailierungsgrad) dargelegt aber es gibt weitere Literaturhinweise. [1]

[1] http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf

Da es ja nicht mysteriös ist, kannst du mir sicher genau sagen wann der GC welche Objekte wegräumt und wann das allozierte Memory dem umgebenden Betriebssystem wieder zur Verfügung steht :D Ja ja, auch das würde eben dazu gehören um nicht von "geheimnissvoll" zu reden (ist IMO ein Synonym für mysteriös)

Ich weiss nicht mehr ob es dieses oder eine anderes Papier war, in dem wir Antworten betreffend Memorymanagement suchen sollten - jede Gruppe eine andere Frage - KEINE hat eine nur annährend konkrete Antwort gefunden wie es verbindlich funktioniert.

Der Dozent, ein sehr erfahrener Javaprogrammierer aus der Industrie meinte nur "Wenn sie meinen etwas herausgefunden zu haben verlassen sie sich nicht drauf - beim nächsten Bugfix könnte alles anders sein" :D

Verglichen mit dem ist das Verhalten mit return in finally direkt verständlich ;-)
 

Antoras

Top Contributor
Auf die Frage wie der GC oder andere Teil der JVM funktionieren wirst du hier keine Antwort finden - da musst du dich schon an die Leute wenden, die die JVM programmiert haben oder eben selbst in deren Sourcen gucken.
Wenn du wissen willst wie ein GC oder Exceptions im allgemeinen funktionieren dann findest du dazu genügend Quellen im Netz, die das im Detail erklären - ich wüsste aber nicht was daran interessant sein sollte zu wissen wie der GC oder eben Exceptions der JVM im speziellen funktionieren. Wie sich Exceptions auf Java-Ebene verhalten ist genauesten dokumentiert, aber wenn du eben wissen willst wie sie auf Maschinen-Ebene funktionieren, dann bleibst dir eben nur der Blick in die Sourcen.
 

Andi_CH

Top Contributor
Hast du die Vorgeschichte auch gelesen???

Das mit dem Memorymanagement und dem GC war nur ein Beispiel - allerdings wurde ich irgendwie gedrängt, das etwas detailierter auszuführen (na ja - angeblich drücke ich mich immer so unverständlich aus - oder liegt es daran dass man nur ein posting liest bevor man Antwort gibt ???)

Ich habe KEINE Antworten zum Thema MM und GC gesucht - ich weiss dass es da keine gibt.
Sorry, aber ich bin immer so direkt!
 

Antoras

Top Contributor
Ich hab alles gelesen, war aber verwirrt durch das hier:
WEISS es jemand oder stellen wir alle nur Vermutungen an?

Bevor mir nicht jemand wirklich den Kontrollfluss aufzeigt werde [...]

Bewiesen ist, dass der Kontrollfluss durch das finally geht - wo geht er dann durch? [...]

(Oder ist das dasselbe Mysterium wie z.B. das Memory Mangemant oder der GC? Da weiss auch niemand wirklich wie es funktioniert)
Da konnte ich nicht genau rauslesen ob du nur wissen wolltest warum ein return in einem finally ausgeführt wird oder wie das intern implementiert ist. Da das mit dem finally aber schon geklärt war bin ich zu letzterem tendiert.
 

Ähnliche Java Themen

Neue Themen


Oben