Eine IOException deutet erstmal auf einen beliebigen I/O Fehler hin. [In diesem Fall kann eine IOException fliegen wenn beispielsweise (evtl. an anderer Stelle) der Stream bereits geschlossen wurde. Ein zweiter Aufruf von close() würde dann eine IOException werfen.]
EDIT:
Der letzte Teil ist Käse Aber eine IOException kann auftreten wenn der Stream nicht ordnungsgemäß geschlossen werden kann, bspw. Hardwaredefekt oder ähnliches.
Lese/Schreibzugriff auf Datei vom Betriebssystem verweigert, Hardware-Defekt (nicht lesbarer Festplatten-Sektor), um mal zwei Bsp zu nennen, bei denen eine IOException fliegt. Da es eine checked Exception ist musst du sie nun mal mit einem try-catch abfangen. (oder weiterwerfen)
allerdings musst nicht zwingend jede mögliche Exception einzeln abfangen.
Du kannst es auch pauschaler so handhaben :
Java:
try{// do something}catch(Exception ex )// fängt alle möglichen Exceptions ab, die zuvor geworfen werden können !!{System.out.println( ex.getMessage );// liefert einen String mit Details zur aufgetretenen ExceptionSystem.out.println( ex.getStackTrace );// liefert den Stacktrace zur aufgetretenen Exception}
allerdings musst nicht zwingend jede mögliche Exception einzeln abfangen.
Du kannst es auch pauschaler so handhaben :
Java:
try{// do something}catch(Exception ex )// fängt alle möglichen Exceptions ab, die zuvor geworfen werden können !!{System.out.println( ex.getMessage );// liefert einen String mit Details zur aufgetretenen ExceptionSystem.out.println( ex.getStackTrace );// liefert den Stacktrace zur aufgetretenen Exception}
Das geht zwar; besser ist es m.E. aber, nur die Exceptions abzufangen, mit denen man an der Stelle rechnet (bzw. rechnen muss) und die dann entsprechend behandelt.
Wenn man sich die Schreibarbeit sparen will, könnte man im konkreten Fall auch einfach nur die IOException fangen, denn auch eine FileNotFoundException ist eine IOException. Aber selbst das würde ich nicht machen, denn die Fehlerbehandlung (bzw. die Fehlermeldung, die man dem Benutzer anzeigt) sollte ja unterscheidliche sein, je nachdem, ob die Datei nicht existiert oder ob man aus irgendwelchen Gründen nicht daraus lesen konnte.
das problem ist dass du damit alles abfaengst. Hat man einen programmierfehler und es tritt eine NullPointer auf, faengt man die auch damit ab und moeglicherweise unentdeckt.
Es gilt als Faustregel, nur die Exceptions fangen, die auch wirklich geschmissen werden koennen - alles andere ist und bleib ausnahme
das problem ist dass du damit alles abfaengst. Hat man einen programmierfehler und es tritt eine NullPointer auf, faengt man die auch damit ab und moeglicherweise unentdeckt.
damit magst Du Recht haben - zumindest bei meinem oben geposteten Code!
Ok, ich muss dabei sagen, dass ich die auftretenden Exceptions bei mir allerdings auch nicht mit println ausgebe, sondern stets mit einer eigenen Dialog-Klasse auf die GUI bringe.
Das hatte ich hier aus Übersichtlichkeitsgründen weggelassen und nur (quasi als Anregung) das println verwendet !
Ist auch in Java 5 schon schlechte Praxis alles auf einmal abzufangen. Gerne darf man IOException fangen um alle Exceptions bei File-Access zu bekommen aber nur ganz selten sollte man Exception und NIEMALS!!!! Throwable fangen. Wie willst du denn sinnvoll auf einen OutOfMemoryError reagieren?
Ja ok, es gibt da Gameserver die schicken den einfach ins Nirvana *hust* *Kopf schüttel*
PS: Nein natürlich wurde das nicht geloggt und ich habe 3 Stunden nach dem Fehler gesucht.
nun habe ich in meinem ersten Post auch nicht geschrieben, dass man es so machen MUSS, sondern lediglich, das man es auch so machen KANN.
Im übrigen klappt die Umsetzung beim uns hier wunderbar. Es wird der Exception-Text über eine entsprechende Logik (mit RegEx, Stringvergleich ...) ausgewertet und in einen entsprechenden Ausgabetext umgesetzt.
Dabei ist bislang noch nie ein Fehler im Nirvana oder sonstwo verschwunden
Es kommt doch nur drauf, keine Exception einfach so zu verschlucken. Ob man jetzt alle einzeln fängt oder nicht.
Ich habe kein Problem mit folgendem Code:
Natürlich sollte man Redundanzen vermeiden, ExceptionHandler Utils sind meist eine gute Idee (nicht nur für Exception translation), aber immer alle java.lang.Exceptions zu fangen um sie dann im catch Block per Stringvergleich RegEx wieder auseinander zu fieseln ist nicht so dolle.
Ich versteh das so, dass dem Anwender eine vernünftige Meldung präsentiert werden soll. Da kann es nötig sein, die Exceptions auseinander zu nehmen. Dann aber eher mit [c]instanceof[/c] als mit Stringvergleich; die Messages können sich schnell mal ändern.
instanceof, re-throw mit angehängtem catch block, sogar mehrere catch Blöcke (solange ohne redundanzen) sind imho besser als Stringvergleich & regEx
Das Exception "Konzept" in Java hat viele Lücken, in Java 7 wird zumindest eine Sache korrigiert, checked exceptions zB. aber bleiben leider für immer..
EDIT: Da wurde während meiner Tipparbeit einiges dazwischen geschrieben - kann sein, dass sich das überschneidet ;-)
Es kommt doch auch immer draufan was man gerade macht - wenn ich etwas schliesse und es geht schief, ist es mir egal warum -
Was mir aber nicht egal ist, ist wenn etwas aufgrund einer Exception nicht ausgeführt wird.
Das sieht mittlerweile so aus und in der produktiven Version wird sogar printStackTrace (vermutlich per Flag) unterdrückt. Ja, es ist mir auch egal, wenn irgendwie eine NPE auftreten würde.
Ich habe locker Exception anstelle von IOException verwendet, da im konkreten Fall dieser Applikation gar nichts zu tun ist, wenn der Server abgeschmiert ist. Es wird einfach wieder versucht den zu erreichen.
zu Beachten ist der konkrete Fall:
Das steht in einem finally-Block drin, als ist der Zustand der Sockets nicht immer genau bekannt.
Abräumen ist immer ein Spezialfall
Warum trat das auf?
Na ja - der Server war gerade bei einem Breakpoint am Warten ) als im Client eine Exception auftrat und im finally-Block eine Folge-Exception - Resultat: der provider-Socket wurde nicht geschlossen, aber grundsätzlich können Netzwerkausfälle oder Abstürze jederzeit auftreten, also ist auch im Betrieb damit zu rechnen.
Klassischer Fehler, wenn bei in.close eine Exception fliegt, wird out und providerSocket nicht mehr geschlossen.
NPEs fangen kann Programmierfehler verschleiern, ein entwickelr der sowas schreibt interessiert sich auch nciht für einen eventuellen Stacktrace im Log bzw. auf der Konsole, was ihn aber meist interessiert ist wenn die App sich beendet
Es hat eben auch Fälle von NPE s gegeben - im letzten Detail habe ich das nicht analysiert - eben das alles steht in einem finally Block - es ist also schon etwas Unvorhergesehens passiert und diese Exceptions haben nach wie vor ein Stacktrace bzw mahcen einen Logfile-Eintrag.
@maki
ist es nicht denkbar, dass durch einen vorherigen Laufzeitfehler manche der 3 Variablen null geblieben sind?
dann kann eine nichtgefangene NullPointerException andere dahinterstehene geöffnete Objekte offen lassen?
das klingt für mich nach einen respektablen Grund,
ganz egal wie der vorherige Code aufgebaut ist, es ist doch ganz leicht bei sowas standardmäßig try/catch Exception hinzuschreiben,
besonders wenn es wie oft gefordert RuntimeExceptions wären,
sollte man dann bei jeder Methode nachschauen, welche Exception dort fliegen, falls überhaupt dokumentiert?
andersrum welchen Grund gibt es sich auf IOException zu beschränken?
dass in einer solchen Situation ein Programmierfehler null untergeht, würde bedeuten dass wie angesprochen die Logs wirklich ignoriert werden,
zur Programmier- + zur Laufzeit, und dass der Code quasi nie lief, nie auch nur einmal erfolgreich aus dem Socket gelesen wurde usw.,
ist das realistisch und in Relation gleichwertig?
aber wenn durch eine Exception eine Referenz auf null bleibt, hätte man mit der ursprünglichen Exception anders umgehen sollen imho.
Das merkt man recht schnell wenn man keine NPEs fängt und "schluckt" (nur loggen sehe ich als schlucken an)
ganz egal wie der vorherige Code aufgebaut ist, es ist doch ganz leicht bei sowas standardmäßig try/catch Exception hinzuschreiben,
besonders wenn es wie oft gefordert RuntimeExceptions wären,
sollte man dann bei jeder Methode nachschauen, welche Exception dort fliegen, falls überhaupt dokumentiert?
andersrum welchen Grund gibt es sich auf IOException zu beschränken?
dass in einer solchen Situation ein Programmierfehler null untergeht, würde bedeuten dass wie angesprochen die Logs wirklich ignoriert werden
Warum man nur auf erwartete Exceptions reagieren soll?
Nun, bei unerwarteten Excetpion weiss man meist nicht wie man richig damit umgehen sollte
Wenn man Exceptions nicht sinvoll behandeln kann, sollte man sie nicht fangen.
Wenn man trotzdem Resourcen schliessen möchte, kann man erstmal alles fangen, muss dann unerwartete Exception aber wieder weiterwerfen, so könnte man null referenzen verursacht durch Exception vermeiden.
Man kann eben nicht auf jede mögliche & unmöglcihe Exception vernünftig reagieren, Code der das umsetzt durch einen re-throw verschluckt nix was er nicht kennt.
Wie gesagt, eine Anwendung die sich verabscheidet weil ein wirklich unerwartetes Ereignis eingetreten ist bekommt viel mehr Aufmerksamtkeit als ein Logeintrag, "geht ja trotzdem"
Die Chance dass man dann einen neuen Fall im Code behandelt steigen.
Socket s =null;InputStream in =null;OutputStream out =null;try{
s =newSocket("",40);
in = s.getInputStream();// hier tritt Exception auf, in bleibt null
out = s.getOutputStream();}catch(IOException e){// ?}finally{try{
in.close();}catch(IOException ex){
ex.printStackTrace();}// close out + s}
würdest du das finally so gut finden, in der Annahme, dass das catch schon für Ordnung sorgt?
was sollte das catch denn hier computer-mögliches machen, prüfen ob in + out null sind und ann dort bereits den Socket s schließen?
(mal abgesehen davon dass dieser vielleicht schon zu ist falls hier überhaupt ohne Programmierfehler die Situation auftreten kann)
meiner Ansicht nach kann das catch nicht dabei helfen,
oder sollte die Initialisierung generell ganz anders aufgebaut sein? was schwebt dir da vor wenn es bei einem finally für in + out + s bleibt?
die Alternative nach Lehrbuch wäre, im finally (in != null) zu prüfen, dagegen kann ich nichts sagen,
das ist sicher sauberer im Hinblick auf NullPointerException,
aber wer weiß was sonst noch so passieren kann..
Wie gesagt, eine Anwendung die sich verabscheidet weil ein wirklich unerwartetes Ereignis eingetreten ist bekommt viel mehr Aufmerksamtkeit als ein Logeintrag, "geht ja trotzdem"
Die Chance dass man dann einen neuen Fall im Code behandelt steigen.
in diesem Fall wäre der Null-Problematik eh ein anderer Fehler, der gewiss auffällt, vorausgegangen,
dass Fehler auftreten können, obwohl alles funktioniert, mag theoretisch nicht auszuschließen sein,
aber was ist eigentlich so schlimm an solchen Fehlern? :bae:
besonders wenn sie durchaus nicht verschluckt sondern geloggt werden, irgendwann wirds schon auffallen,
stattdessen auf höherer Ebene ohne Not einen funktionierenden Prozess abbrechen damit der Fehler, der eigentlich gar nicht stört, zügig bearbeitet wird?
Bei solchen fällen hilft das natürlich nix, muss schon im finally geprüft weren ob man nicht null dereferenziert.
Aber in diesem Beispiel wird ja nicht java.lang.Exception gefangen, sondern IOException
Woher weis man das eine Exception "nicht so schlimm" ist wenn es eine unerwartete ist?
Das kann man doch nur in zwei Fällen:
- der Code der durch die Exception nicht mehr ausgeführt wird ist egal
- das Programm an sich ist egal
*g*
Wie gesagt, nur loggen ist nicht immer eine richtige Behandlung, das gilt imho für NPEs.
Denke dass viele Entwickler einfach nicht einsehen wollen dass man nicht auf jede Exception vernünftig reagieren kann und man manchmal schon das auftreten einer bestimmten/unbestimmten Exception "Game over" heisst.
Exception handling soll ja nicht vor Fehlern des Programmierers schützen...
Ein Log dass mir der User nicht schickt ist genaugut wie eine Exception die mir der User bzw. das Programm verschweigt, wenn das Programm noch bei mir ist und extreme Ausnahmen/Fehler nicht nur geloggt werden steigen die Chancen auf Korrektur.
nicht einfach meintest allein auf IOException umzustellen.., denn bei null fliegt das um die Ohren, da muss auch noch ein Null-Check rein,
mit catch Exception könnte es so bleiben,
falls du meinst dass eine null dort in der jeweils einen Zeile so dramatisch ist, kann ich dir das nicht ausreden..,
edit:
mit null-Prüfung kann man die eigene Variable checken, aber wehe innerhalb des Objektes (falls eigene Klasse, z.B. Wrapper um Stream)
ist irgendwas nicht in Ordnung und dann irgendwo dort null,
das ist sicher etwas spannender zu erfahren, aber deshalb den nicht geschlossenen Socket zu riskieren?..,
vielleicht doch catch(Exception) und die Exception an eine Methode übergeben die bestimmte Fehler gesondert aufmerksam loggt
Deswegen auch der Hinweis "wenn du hier nur IOException erwartest"
Wenn da mehr erwartet wird reicht das natürlich nciht so.
IOException wäre ein Anfang gewesen, ist immer problematisch bei so kleinen Snippets, weil das drumherum (noch ein try/catch? re-throw? finally block mit System.exit(0)?) eben auch sehr wichtig ist, aber von Exception auf IOException ist der Anfang imho.
Zu deinem edit:
NPE -> Programm beendet sich -> Socket geschlossen