try&catch Java

Moin,
neulich hab ich mich mit meinem Lehrer in die Haare bekommen ob man innerhalb eines Java-Programmes ganz bewusst try&catch einsetzen darf um Fehler abzufangen. Dieser Fehler treten ganz gezielt auf. Bsp. Ein 2D Array soll mit irgendwas befuellt werden. Dazu muss aber das Umfeld das Arrays auf seinen Inhalt geprueft werden. An den Raendern will ich ganz bewusst den ArrayIndexOutOfBoundsException Fehler herbeifuehren um zu merken dass ich am Rand bin und nicht z.B. nach links gehen kann um das Array zu ueberpruefen weil es dass ja nicht gibt. Ich bin der Meinung warum soll man da nicht try&catch nehmen, es ist ja schliesslich da um Fehler abzufangen. Ich wuerde so nur die Eigenschaften der Sprache ausnuetzen. Mein Lehrer ist aber der Meinung try&catch sollte nur verwendet werden um moegliche, nicht beachtete Fehler abzufangen. Ein Einsatz von try&catch wie ich ihn sehe seinen "Hackermethoden" :rolleyes: :rolleyes: :rolleyes: :rolleyes: :rolleyes:
Was meint ihr dazu?
Gruss
 
Also ich kann dazu nur sagen, daß man das was du vorhast nie professionell einsetzen würde. Dies hat mehrere Gründe. Der erste und einfachste dürfte wohl sein daß der Code dadurch unleserlicher wird. Ein array.length() ist deutlich lesbarer und verständlicher als eine Schleife die durchs Array "schleift" und von einem Try/Catch-Block umgeben ist. Es ist auch deutlich performanter wie man sich vorstellen kann. Diesen Aspekt sollte man auch nicht vergessen. Ausserdem wage ich zu behaupten, daß man mit zu vielen und eigentlich unnützen Try/Catch-Blöcken in größeren Programmen sehr merkwürdige Effekte erzeugen kann. Mir ist eine durchgeschleifte Exception deutlich lieber bei der Fehlersuche als eine die mehr oder weniger zufällig irgendwo in den untiefen des Programms gecatched wird.
Kurzum, es ist nicht falsch was du machst, aber man sollte aus oben genannten Gründen die Finger davon lassen.

Gruß odigo
 
Schon wieder so ne Glaubensfrage :).
Kurz zur Theorie: Exceptions stellen, wie der Name schon sagt, Ausnahmen dar, also Abweichungen vom Standardverhalten. Kurzes Beispiel: Kommunikationsprotokolle. Diese legen einen Ablauf der Kommunikation fest. Möglich sind z.b. Abweichungen vom Protokoll, dann ist es durchaus legitim, dass die Anwendungen eine eigens definierte ProtocolViolatedException oder sowas wirft (Name gerade frei erfunden), oder z.b. eine entsprechende Exception im Falle eines Verbindungsabbruchs (technischer Fehler, ganz anderes Niveau!).
Man erwartet, dass die Kommunikationspartner sich an das Protokoll halten und die Verbindung nicht wegbricht - Exceptions werden also in unerwarteten Fällen geworfen.

Auf dein Beispiel übertragen:

Wenn du weißt, dass du irgendwann an die Grenzen eines Arrays stößt, solltest du versuchen, dein Programm ohne Exceptions robust hinzukriegen. Die Länge eines Arrays ist zu jeden Zeitpunkt festellbar, das ist also durchaus möglich.
Die Exception würde ich nur dann schmeißen, wenn du nicht erwartest, dass du an die Grenzen kommst (aus welchem Grund auch immer, z.b. weil ein Auswahlmechanismus dir ein falsches Array geliefert hat und du nun glaubst, du operierst auf einem vollkommen anderen oder sowas.)

Man kann also mit einer Exception signalisieren, dass man dieses Ereignis nicht erwartet hat. Inflationäre Verwendung von Exceptions bringt das Problem mit sich, dass dieser Aspekt entwertet wird. Ich habe schon erlebt, dass man einfach neue Exceptions einführt, um eben zwischen erwartet / unerwartet unterscheiden zu können - dann muss man aber evtl prüfen, wann welche Exception geworfen werden soll, und da hätte man es gleich ganz ohne machen können :)

Ein Pro-Argument: Exceptions stellen ein einheitliches System zu Signalisierung von Abweichungen dar - Viele erfinden da da Rad neu und signalisieren sowas über irgendwelche Zustandsvariablen, die nur unnötig die Komplexität der Software hochschrauben ("komplex" as in "für den Menschen schwierig zu verstehen", nicht im Sinne einer Laufzeit).

Contra-Argumente (bitte selbst entscheiden, wie wichtig das ist):
1. try/catch macht den Code unleserlich. Man muss einige Zeilen schreiben, die Einrückungen entsprechen nicht mehr dem eigentlichen Codeablauf usw.. Insbesondere, wenn man mal try/catch schachteln muss, wird das ein Horror. Natürlich ein schwaches Argument, an sollte nicht unbedingt schlechtes SoftwareDesign aufgrund von besserer Lesbarkeit akzeptieren.
2. Exceptions sind teuer, was Laufzeit und Ressourcen angeht. Hier gilt das Gleiche: Lieber etwas Zeit und RAM fressen, als in wilde Frickeleien verfallen. Es gilt natürlich abzuwägen, welcher Punkt überwiegt (z.b. eine kleine Frickelei für eine große Ressourcenersparnis, sowas kommt aber selten vor)

Man muss auch selbst entscheiden, welcher Anforderung man folgt: Entscheidet man anhand jedes Einzelfalls, ist man flexibel, aber die Konsistenz der Codes sinkt. Hält man sich streng an eine Linie, muss man Exceptions entweder ignorieren oder permanent damit um sich schmeißen, beides funktioniert kaum.

Weil ichs noch vorhin vergessen hab: Ein wichtiger Punkt ist: Kann sich die Methode, die evtl. eine Exception generiert, sich selbst um deren Handling kümmern?
Im Beispiel der Kommunikation signalisiert man nur der Anwendeung, was schiefgegangen ist, damit diese geeignet reagieren kann, denn das kann die Methode evtl garnicht wissen.
Ist dagegen ausgeschlossen, dass sich das Verhalten der Software anhand von Informationen definiert, die die Methode nicht kennt, dann sollte sie sich selbst um das Handling kümmern und keine Exception werfen, denn damit versteckt sie die Komplexität nach außen hin.

Und weiterhin wirft man gerade bei Prototypen & Mock-Ups gerne mit Exceptions um sich, da es evtl lange dauert, bis man eine komplexe Methode geschrieben hat, die sich (korrekt) um die Fehler kümmert. Dann nimmt man Exceptions als temporäre & schnelle Lösung in Kauf, in der Absicht, sich später mal drum zu kümmern.
 
Also dass das der Leserlichkeit des Programms schadet, naja... Wenn ich das jetzt mit ein paar if und else Bedingungen eingrenze kann man das genauso unübersichtlich machen wie mit try&catch.
Zur Rechenleistung, wie lange braucht ein PC länger um eine try&catch-Block anstatt z.B. if else abzuarbeiten? 10, 20 ms? Wen juckt das den bei der heutigen Rechenleistung noch...???
 
Hallo,
Original von tanj
Also dass das der Leserlichkeit des Programms schadet, naja... Wenn ich das jetzt mit ein paar if und else Bedingungen eingrenze kann man das genauso unübersichtlich machen wie mit try&catch.
Zur Rechenleistung, wie lange braucht ein PC länger um eine try&catch-Block anstatt z.B. if else abzuarbeiten? 10, 20 ms? Wen juckt das den bei der heutigen Rechenleistung noch...???
was ist das für eine Einstellung? Möchte da jemand krampfhaft an seinem try & catch festhalten?

Wie bereits erwähnt, sind Exceptions Ausnahmen und dienen auf keinen Fall, um irgendetwas festzustellen.

Wenn du später beim Job per try&catch die Array-Grenze überprüfst oder damit testet, ob eine Datei schon vorhanden ist, wird dich dein Chef (zu recht) in die Schranken weisen.
Wäre ich Lehrer, würde ich jedem Schüler der mir so einen Müll abliefert, eine entsprechend schlechte Note geben.

try&catch enstellt völlig die Logik des Programmes. Ein array.length() oder file.exists() ist viel leichter zu verstehen als eine Schleife die die grenze Ermittelt oder file.open()...


Also lass von dieser hirnrissigen Idee ab, und verwende ganz normal if-else Anweisungen um sowas festzustellen.
 
Abgesehen davon wird die Laufzeit eines Programmes unabhaengig von der Rechenleistung des Systems ermittelt.
D.h.
Dein Code mag zwar auf einem High-End-Rechner schneller laufen als guter code auf einem langsameren Rechner, aber auf dem gleichen System ist dann der gute Code wieder schneller, und rate mal welchen Code man dann benutzt?
 
Um es klar zustellen, nein ich will nicht krampfhaft daran festhalten, ich möchte es nur gut erklärt und diese Erklärung auch gut begründet bekommen. Und try&catch die Lesbarkeit des Source beeinflusst zieht nun mal bei mir nicht.
Es ist halt wieder die Frage was schnell und langsam heißt (messbar oder wirklich merkbar).

Und nein, ich hab keine schlechte Note bekommen, dass war eine normale Unterrichtsdiskussion und die Argumente meines Lehrers fand ich schlicht zu schwach.
Also ich würd ganz gerne wissen warum man es nicht verwenden sollte außer das es "hirnrissig ist", Geschwindigkeit beeinflusst (in welchem Ausmaß?) und dass es der Leserlichkeit des Source schadet.
 
Hallo,
1. Die Logik des Programmes wird total zerstört. Du verwendest 'negierte Aussagen', was wirklich befremdlich ist (testet also nicht, was du testen willst, sondern überprüfst, ob ein Fehler auftritt, wenn du es machst)
Wenn man überprüfen möchte, ob eine Datei noch nicht existiert (!file.exists()), damit man auch nichts überschreibt, würde man per try&catch überprüfen, ob man die Datei öffnen kann. Wenn ja (try): Datei vorhanden. Bei catch: Datei nicht vorhanden

2. Solch Code wird schnell unübersichtlich. Besonders diese umgedrehte Logik ist sehr schwer zu blicken.
Ansonsten poste doch mal ein Beispiel, bei dem du gerne try&catch verwenden würdest

3. Du zweckentfremdest try&catch. Dieses ist dafür da, (unvorhergesehene) Ausnahmen zu behandeln. Du führst diese Ausnahme aber extra herbei, was absolut keinen Sinn ergibt.
Wenn man das ins echte Leben übersetzt, würdest du überprüfen ob die Straße frei ist, indem du losfährst, und wenn der Airbag nicht los geht, dann war die Straße frei, und wenn doch, dann ist sie nicht frei.
Der normale Weg wäre aber, zu gucken (überprüfen), ob die Straße frei ist und dann loszufahren.

4. Das Programm wird dadurch langsamer. Siehe Definition Exception: "After a method throws an exception, the runtime system attempts to find something to handle it."
Wenn man dies in Schleifen oder häufig verwendeten Funktionen hat, wird es merklich langsamer.


5. In einem try Block kann auch ne ganz andere Exception ausgelöst zu werden also du sie erwartest. Diese springt dann auch in den Catch-Block und somit läuft die Ersatzroutine ab.
Wenn du per try&catch überprüfst, ob du auch keine Datei überschreibst, und es so aufgebaut hast:
- try-Block: Datei vorhanden
- catch-Block: Datei nicht vorhanden -> Was auch immer mit der Datei machen

Es kann sein, dass die Datei vorhanden ist, du dennoch in den catch-Block abrutschst und die Routine ausgeführt wird, die eigentlich nur ausgeführt werden soll, wenn die Datei eben noch nicht vorhanden ist.

6. Wegen 5. kann dein Programm nicht feingliedrig sein, da der catch-Block auch ausgeführt werden kann, wenn eine Exception auftritt, die man nicht erwartet (was Ausnahmen so an sich haben)
 
Try/catch ist an sich eine nette Idee gegenüber der früheren Methoden mit der Fehlercodeabfrage. Wer mit C programmiert oder WinAPI nutzt, weiß schon, wie teilweise unpraktisch und ätzend diese Methode ist.

Vom designtechnischem her: wenn man try/catch immer nutzt, wie möchte man zwischen gewollten und ungewollten Fällen unterscheiden? Man kann auch ungewollt von anderen Methoden geworrfene Exception catchen und so einen Fehler "übersehen".
Bedenke auch, dass die meisten Programmierer nach diesem Denkmuster vorgehen (Try/Catch =>für Ausnahmen) - sobald man auf fremde Bibliotheken angewiesen ist (oder welche schreibt), sollte man diese "Muster" schon respektieren ;)

Sonst:
Geschwindigkeit beeinflusst (in welchem Ausmaß?) und dass es der Leserlichkeit des Source schadet.
Probiere es einfach aus. Es kommt immer darauf an.
z.b hier ist der Unterschied nur gering (1.5 fache)
Code:
{
		int[][] array=new int[4000][4000];
		int i=0;
		int k=0;
		long time=System.currentTimeMillis();
		 while (i<array.length)
		 {
			 try
			 {
				 array[i][k]=1;
				 k++;
			 }catch (ArrayIndexOutOfBoundsException ex)
			 {
				 k=0;
				 i++;
			 }
		 }
		 System.out.println(System.currentTimeMillis()-time);
		 time=System.currentTimeMillis();
		 for (int l=0;l<array.length;l++)
			 for (int m=0;m<array.length;m++)
				 array[l][m]=2;
		 System.out.println(System.currentTimeMillis()-time);
			}
hier schon deutlicher:
Code:
{
		int[][] array=new int[400000][4];
		int i=0;
		int k=0;
		long time=System.currentTimeMillis();
		 while (i<array.length)
		 {
			 try
			 {
				 array[i][k]=1;
				 k++;
			 }catch (ArrayIndexOutOfBoundsException ex)
			 {
				 k=0;
				 i++;
			 }
		 }
		 System.out.println(System.currentTimeMillis()-time);
		 time=System.currentTimeMillis();
		 for (int l=0;l<array.length;l++)
			 for (int m=0;m<array[0].length;m++)
				 array[l][m]=2;
		 System.out.println(System.currentTimeMillis()-time);
			}
Dazu noch: im BIN Ordner der Java-JDK existiert die JCONSOLE
diese zeigt viele nette Statistiken über CPU und RAM verbrauch einzelner Programme.

Manchmal ist die nachträgliche Reaktion auf Fehler einfach zu teuer und ineffizient.
Beispiel: man schreibt ein Tool, welches über SFTP mehrere Ordner synchronisiert.
Nun - man kann entwerder stur die Ordner und Dateien durchgehen (z.B mit dem Downloadversuch) und auf Exceptions warten (sind ja verfügbar) oder doch vorher anfragen, ob die Datei überhaupt verfübgar ist ;)

Genauso wie man eigentlich bedenkenlos bei Bedarf neue Klassen anlegen und verwerfen kann -
meistens ist es kein Problem. Schreibt man allerdings ein Tool zur Datenverwaltung und Anzeige (z.B Daten auf der Festplatte) und verwendet pro Datei eine Klasse, bekommt man mit dieser vorgehnsweise schnell Probleme, sobald der User sich durch die Ordner durchklickt.

Es ist also insofern in den meisten Fällen wirklich nur Geschmackssache und kann nur in gewissen Fällen zu Problemen führen.

PS :auf einem schwachen Rechner (Handy, PDA usw) wird man diese Geschwindigkeitsunterschiede noch sehr deutlicher spüren. Vor allem Speichermehraufwand wird sich bemerkbar machen.
 
Moin,
bei mir ging es konkret darum, dass ich ein 2D-Array dass erstmal mit 0en gefuellt ist mit einsen befuellen will. Dies haengt aber von der direkten Umgebung ab, So darf kein Feld befuellt werden, wenn über, unter, links oder rechts neben ihm schon eine 1 ist. Welches Feld gefuellt werden soll, bestimmen zwei Randomzahlen. In den meisten Fällen kann ich also nach oben, unten. links und rechts gehen, nur in den Ausnahmen wo eine der beiden Zahlen eine 0 bzw. das Maximum der Arraygroesse ist geht das nicht. Und genau diese Ausnahmen wollte ich mit try&catch abfangen um dann genauer zu pruefen was das fuer Zahlen sind.
 
Zurück
Oben