Zum Inhalt springen

Exception-Frage


bolleee

Empfohlene Beiträge

hi,

ich habe eine Funktion:


public ResultSet querry(String statement)
throws SQLException
{
Statement stmt;
ResultSet result;
try{
stmt = conn.createStatement();
result = stmt.executeQuery(statement);
}
catch (Exception e)
{
System.out.println("Fehler "+e);
}
return result;
}
[/PHP]

Das kompilieren dieser Funktion führt zu folgendem Fehler:

The variable "result" may be accessed here before having been definitely assigned a value.

Mein Wissen über Java ist eher beschränkt, könnt ihr mir daher bei diesem Problem weiterhelfen?

Noch was: wenn ich result mit

[PHP]ResultSet result = new ResultSet();

initialisiere bekomme ich

Interface "java.sql.ResultSet" cannot be used where a class is expected.

Wie ihr vielleicht seht, ich bin ein FiSi und momentan leider aufgeschmissen :(

Könnt ihr mir erklären wie die Methode richtig aussieht?

Link zu diesem Kommentar
Auf anderen Seiten teilen

public ResultSet querry(String statement) 

  { 

   try{ 

   Statement stmt = conn.createStatement();

   ResultSet result = stmt.executeQuery(statement); 

   return result; 

   } 

   catch (Exception e) 

   { 

         System.out.println("Fehler "+e); 

   } 

   return null; 

  } 

besserer Stil

wer catched, muss net throwen

Variablen so lokal wie möglich anlegen

Link zu diesem Kommentar
Auf anderen Seiten teilen


public ResultSet querry(String statement)
throws SQLException
{
Statement stmt;
ResultSet result;
try{
stmt = conn.createStatement();
result = stmt.executeQuery(statement);
}
catch (Exception e)
{
System.out.println("Fehler "+e);
}
return result;
}
[/PHP]

Das kompilieren dieser Funktion führt zu folgendem Fehler:

Du deklarierst eine Variable "result", der Du im try/catch-Block einen Wert zuweist. Tritt ein Fehler im try-Block auf, wird logischerweise der Variablen "result" kein Wert zugewiesen; sie bleibt uninitialisiert. Trotzdem gibst Du sie mit "return result" zurück. Und nicht initialisiert Variablen können weder zurückgegeben noch übergeben werden.

[PHP]ResultSet result = new ResultSet();

initialisiere bekomme ich

Ich weiß nicht, ob Du den Unterschied zwischen Klasse und Interface kennst. Jedenfalls definiert ein Interface nur Methoden, ohne ihren Rumpf anzugeben. Und java.sql.ResultSet ist ein solches Interface. Aufgrund der Tatsache, daß ein Interface nur Methodensignaturen, aber keine Rümpfe enthält, kann man Interfaces nicht initialisieren.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich weiß nicht, ob Du den Unterschied zwischen Klasse und Interface kennst. Jedenfalls definiert ein Interface nur Methoden, ohne ihren Rumpf anzugeben. Und java.sql.ResultSet ist ein solches Interface. Aufgrund der Tatsache, daß ein Interface nur Methodensignaturen, aber keine Rümpfe enthält, kann man Interfaces nicht initialisieren.

Nein den kannte ich noch nicht, aber danke für den Hinweis... das erklärt so einiges :)

Ach ja und die Methode wirft nun auch keine Exception mehr. Fehlerausgabe/Korrektur erledige ich nun nur noch über die Klasse.

Ist das eigentlich vorteilhaft oder sollte man dies von der "Main" aus machen?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nein den kannte ich noch nicht, aber danke für den Hinweis... das erklärt so einiges

Ach ja und die Methode wirft nun auch keine Exception mehr. Fehlerausgabe/Korrektur erledige ich nun nur noch über die Klasse.

Ist das eigentlich vorteilhaft oder sollte man dies von der "Main" aus machen?

da liegt der Sinn der OOP, alles was zum Thema gehört in einer Klasse zu lösen

Fehler dort behandeln, wo sie entstehen, gehört für mich eigentlich auch dazu

Link zu diesem Kommentar
Auf anderen Seiten teilen

Fehler dort behandeln, wo sie entstehen, gehört für mich eigentlich auch dazu
Und genau das ist eben nicht Sinn von Exception-Handling (und auch nicht der Sinn von OOP). Fehler sollen dort behandelt werden, wo es sinnvoll ist sie zu behandeln und darauf zu reagieren und eben nicht dort, wo sie entstehen. Sonst könnte man sich das gesamte Exception-Konzept schenken und wie zu den grauen Zeiten von C nur mit Return-Codes arbeiten.
Link zu diesem Kommentar
Auf anderen Seiten teilen

Und genau das ist eben nicht Sinn von Exception-Handling (und auch nicht der Sinn von OOP). Fehler sollen dort behandelt werden, wo es sinnvoll ist sie zu behandeln und darauf zu reagieren und eben nicht dort, wo sie entstehen. Sonst könnte man sich das gesamte Exception-Konzept schenken und wie zu den grauen Zeiten von C nur mit Return-Codes arbeiten.

nenn mir ein Beispiel, wo es sinnvoller ist, fehler nach oben zu werfen

als sie zu behandeln

los eins nur

ich warte..........

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich hätte da was. Stell' Dir ein Spiel vor mit Schnellspeichern. Du startest das Spiel und sagst "An letzter Stelle weitermachen".

Intern versucht nun der "SaveManager" einen Speicherstand "SavePoint" zu initialisieren und übergibt ihm den Ort, wo die Datei liegt. Die Datei hast Du aber vorher aus Versehen gelöscht. Jetzt kommts im Objekt "SavePoint" zu einer FileNotFoundException. Statt jetzt den Fehler lokal zu behandeln und eine Meldung zu bringen "Letzten Speicherstand nicht gefunden" könnte man doch auch den Fehler in den "SaveManager" hoch reichen, der dann nachschaut, ob es noch weitere Spielstände gibt und den letzten laden.

Zugegeben, daß Beispiel hört sich etwas herbeigezogen an, aber Situationen für sinnvolles Hochreichen von Exceptions gibt's sicherlich.

Link zu diesem Kommentar
Auf anderen Seiten teilen

nenn mir ein Beispiel, wo es sinnvoller ist, fehler nach oben zu werfen als sie zu behandeln
Dateioperationen. Wenn ich folgenden Ablauf habe:

(1) Dateireferenz erstellen

(2) Datei zum Schreiben öffnen

(3) Werte in Datei schreiben

(4) Datei schließen

Meine Methode heisst allerdings nur

writeIntoFile(File file, String text) throws IOException

dann will ich darin nicht nach jedem einzelnen Punkt (1-4) überprüfen "ist etwas schief gelaufen?" sondern verlasse mich darauf, dass bei einem Fehler die Verarbeitung unterbrochen wird und eine Exception nach oben weitergereicht wird. Damit habe ich mir in dieser ganz groben Betrachtung schonmal drei Checks gespart. Resultat: Mein Code wird übersichtlicher, der gesamte Programmablauf klarer.

Und nur als Anmerkung: Sämtliche Punkte teilen sich wieder in Unterpunkte auf (FileDescriptor erstellen, Byte für Byte schreiben, etc.). Wenn du hier hingehen willst und bei jedem einzelnen Unterpunkt Fehler abfangen und darauf reagieren willst, wirst du ausser zu Fehlerbehandlung zu wenigen Dingen in deinem Programm kommen.

Und während in Villariba noch Fehler abgefangen werden wird in Villabacho bereits mit der Applikation Geld verdient.

los eins nur

ich warte..........

Wenn du den Sinn hinter einem solchen Konzept nicht wirklich verstehen willst, bitteschön.

Und wenn dir meine Erklärung nicht ausreicht, vielleicht überzeugt dich eine dieser Abhandlungen:

- http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html

- http://www.cplusplus.com/doc/tutorial/exceptions.html

- http://www.codersource.net/csharp_tutorial_exceptions.html

- http://en.wikipedia.org/wiki/Exceptions

Link zu diesem Kommentar
Auf anderen Seiten teilen

Zugegeben, daß Beispiel hört sich etwas herbeigezogen an.

vor allem, weil das normale vorgehen beschreibst ;)

....

(1) Dateireferenz erstellen

(2) Datei zum Schreiben öffnen

(3) Werte in Datei schreiben

(4) Datei schließen

....

schau mal in die java-api-src

glaub net, dass du versuchen willst, sun-programmierer davon zu überzeugen, das du recht hast :marine

Wenn du hier hingehen willst und bei jedem einzelnen Unterpunkt Fehler abfangen und darauf reagieren willst, wirst du ausser zu Fehlerbehandlung zu wenigen Dingen in deinem Programm kommen.

Und während in Villariba noch Fehler abgefangen werden wird in Villabacho bereits mit der Applikation Geld verdient.

quick and dirty heisst das, und ist nicht grade "gute" Programmierung

schnell geschrieben, das ist auch alles ;)

Wenn du den Sinn hinter einem solchen Konzept nicht wirklich verstehen willst, bitteschön.

Und wenn dir meine Erklärung nicht ausreicht, vielleicht überzeugt dich eine dieser Abhandlungen:

:marine eigentor kleiner ;)

c++ gibts kein hoch-throwen , c# laut dem tut auch net :confused:

der stil, bei java einfach alles "hochzuthrowen" hat sich nur eingebürgert, weils so schön einfach ist ;)

mit ordentlichem programmieren hat das nicht viel zu tun,

P.S.:aber wer sagt, das FIs programmieren können, bin gott sei dank keiner ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

wer sagt, das FIs programmieren können, bin gott sei dank keiner
Das nenne ich mal einen unqualifizierten Beitrag, "Kleiner"!

Als begeisteter Leser des Java-Forums möchte ich dich bitten, dich in deinen Ausdrucksformen in Zukunft zu zügeln. Denn ich möchte, dass mir das Lesen auch weiterhin Spaß macht, was mir bei solchen Kommentaren ziemlich schwer fällt. Danke!

@Moderator: Ich schätze die Fragen hier sind eindeutig beantwortet. Ich schlage deshalb das Schließen dieses Threads vor.

Link zu diesem Kommentar
Auf anderen Seiten teilen

der nick sagt alles ;)

ich denke nur, wenn es antworten gibt, dann sollten die auch richtig sein

und wenn mir ein FI mit

Wenn du den Sinn hinter einem solchen Konzept nicht wirklich verstehen willst, bitteschön.

der offensichtlich nicht weiss wovon er redet dummkommt, kontere ich

püh

Link zu diesem Kommentar
Auf anderen Seiten teilen

der nick sagt alles ;)

Jetzt mal immer langsam. Auch ein Smiley macht die Aussage nicht besser.

Aber zurück zum Thema: Du bist also der Meinung, daß das Weiterreichen von Fehlern absolut unnötig und nie sinnvoll zu gebrauchen sei. Hier sind schon ein paar Gedanken dazu geäußert worden. Vielleicht ist es jetzt mal an der Zeit, daß Du Deine Aussage argumentierst? Verrate uns, warum es unsinnig sei, Exceptions an einer anderen Stelle zu behandeln.

Ich bin anderen Meinungen immer aufgeschlossen und wer weiß, vielleicht kannst Du mich ja überzeugen?

P.S.:aber wer sagt, das FIs programmieren können, bin gott sei dank keiner

Ah ja. Was bist Du denn? Welch hohen akademischen Rang hast Du erlangt?

Link zu diesem Kommentar
Auf anderen Seiten teilen

nehmen wir mal an, eingabe

so wie es oft ewähnt wurde

class Eingabe{


File datei;


Eingabe(Sting dateiname);

boolean open();

String[] leseWerte();

boolean close();


}
in der Main dann
Class Main[

Eingabe myEin = new Eingabe("test.txt");

if(myEin.open()){

   String[] werte = myEin.leseWerte();

   myEin.close();

}


werfe ich den Fehler nach oben, fehlen mir eventuelle Umgebungsvariablen,

die in Eingabe da wären, ausserdem kann man eigene Fehlerklassen definieren,

zB "Datei hat nicht die entsprechene länge", wo der vergleichswert ("tatsächliche länge") beim hochthrowen verloren geht, oder mitgegeben werden muss

eine Fehlermeldung sollte so aussagekräftig wie möglich sein, denn dann ist es einfacher sie zu beheben

so wäre eine "zuwenigezeilenException" mit den argumenten "int soll" und "int ist" ausgestattet

eine "DateiNichtVorhanden" bzw "DateiNichtLesbar" mit den Argumenten dateiname ausgestattet

will man das alles nach oben werfen, und das Project nur gross genug

wird die main unlesbar, da eine Ewig lange fehlerbehandlung dort ausgeführt wird

normalerweise sollte ja nicht erkennbar sein, das ein Fehler aufgetreten ist, sondern Welcher, Wo und Warum

Link zu diesem Kommentar
Auf anderen Seiten teilen

Klar. Hier ist es unnötig, die Exception hochzuwerfen. Aber angenommen, man wollte das tun, kann ich zumindest Dein Argument mit den Parametern, die mitgegeben werden müssen, entkräften:

public boolean open() throws Exception {
//...
if(anzZeilen < anzSollZeilen) {
throw new Exception("Zu wenige Zeilen: " + anzZeilen + " statt " + anzSollZeilen);
}
}[/PHP]

So bleiben die Parameter bei der auftretenden Stelle und es wird eine aussagekräftige Fehlermeldung erstellt, die ohne Probleme nach oben weitergereicht werden kann.

Erweitern wir Dein Beispiel um etwas mehr Funktionalität. Der Benutzer kann über die Kommandozeile mehrere Dateien angeben:

[PHP]class Main {
public static void main(String[] args) {
String[][] fehlerhafteDateien = new String[args.length][2];
int i = 0;

for(String datei : args) {
Eingabe eingabe = new Eingabe(datei);
try {
eingabe.open();
//tu was
eingabe.close();
catch (Exception e) {
fehlerhafteDateien[i][0] = datei;
fehlerhafteDateien[i++][1] = e.getMessage();
}
}

//gib die fehlerhaften Dateien mit zugehörigen Meldungen aus
}
}

class Eingabe {
public boolean open() throws Exception {
//...
if(anzZeilen < anzSollZeilen) {
throw new Exception("Zu wenige Zeilen: " + anzZeilen + " statt " + anzSollZeilen);
}
}
}

Das Hochwerfen ist immer dann sinnvoll, wenn das Objekt, in dem der Fehler provoziert wird, ein einfach gestricktes Objekt und das delegierende Objekt einen anderen Weg zum Ziel kennt. Und solch einfach gestrickten Objekte gibt es einige, wenn man Design Patterns und/oder Refactoring nutzt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

@tkdmatze: Ich glaube, du übersiehst da was.

Schau dir in der Java API Doc mal die verschiedenen Konstruktoren der Klasse Throwable an. Du wirst erkennen, dass 2 der Konstruktoren als Parameter ein weiteres Throwable-Objekt erwarten, nämlich den Fehlerursprung.

Wenn du also eine Exception in einem Catch-Block auffängst, dann kannst du eine neue Exception werfen, die vielleicht sogar noch weitere Informationen liefert, welche die "untere" Excpeption einfach nicht hat. Zusätzlich gibst du der neuen Exception die aufgefangene gleich mit.

So gehen dir nicht nur keine Informationen verloren, wie du es befürchtest, sondern du kannst sogar noch mehr Informationen über den Fehler sammeln.

Ein Beispiel für die Implementierung dieser Informationssammlung:

package de.tkdmatze.deinpackage

import /*...*/


public class DBLeser {

    private Statement stmt;


    liesTabelleBla() throws DBLeserException {

        try {

            stmt.execute("SELECT * FROM tabelleBla WHERE id = 4711");

        } catch (SQLException e) {

            throw new DBLeserException("Lesefehler: tabelleBla.", e);

        }

    }


    liesTableBlubb() throws DBLeserException {

        try {

            stmt.execute("SELECT * FROM tabelleBlubb WHERE id = 4711");

        } catch (SQLException e) {

            throw new DBLeserException("Lesefehler: tabelleBlubb.", e);

        }

    }

}

Würdest du die SQLException nicht weiter hochthrowen, hättest du am Ende nix anderes als diese eine SQLException. Im Falle einer nichtsaussagenden Fehlermeldung der Exception ist dir nicht geholfen und du bist dann ziemlich aufgeschmissen bei der Fehlerbehebung.

Auf die obige Weise könntest du zumindest noch weitere Infos zusammen kratzen, die dir letztlich helfen können, den Fehler zu beseitigen.

Gruß

Arvid.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das Hochwerfen ist immer dann sinnvoll, wenn das Objekt, in dem der Fehler provoziert wird, ein einfach gestricktes Objekt und das delegierende Objekt einen anderen Weg zum Ziel kennt.

klingt als ob man sich drauf einigen könnte ;)

allerdings gehts bei dir darum, die nachricht weiterzugeben, nicht das obejct an sich

@ar-sch.de

dein vorgehen ist sicher richtig, wobei du es zwar nach oben (Exception) wirfst, aber ableitest, etwas, was hier nicht zur rede kam

wenn man den ansatz so machst und für die möglichen Fehlern eine entsprechende Exception-Klasse schreibt, kann man dort auch

-Fehlerausgabe

und

-Fehlerbehandlung

in der fehlerklasse implementieren, was du "nach oben" wirfst, ist aber nicht die Reine Exception, sondern halt eine Ableitung davon

jedoch sehe ich nicht viel unterschied in



public class Main{


public static void main(String[] args){

....

try{

liesTabelleBla();

}catch(Exception ex){


ex.gibFehlerAus();

}

}

}


public class DBLeser {

    private Statement stmt;


    liesTabelleBla() throws DBLeserException {

        try {

            stmt.execute("SELECT * FROM tabelleBla WHERE id = 4711");

        } catch (SQLException e) {

            throw new DBLeserException("Lesefehler: tabelleBla.", e);

        }

    }

    }

}
und


public class Main{


public static void main(String[] args){

....

try{

liesTabelleBla();

}catch(Exception ex){

}

}

}


public class DBLeser {

    private Statement stmt;


    liesTabelleBla() throws Exception {

        try {

            stmt.execute("SELECT * FROM tabelleBla WHERE id = 4711");

        } catch (SQLException e) {

           gibFehlerAus();

        }

    }

    }

}

in beiden Fällen sind alle infos da, dein Vorgehen wäre dann anders, (hast vllt schlechtes beispiel genommen)

wenn eine Heirarchie dahintersteht, die mehr als 2 Stufen hat

zB

Main>>Eingabe>>SQL-Eingabe>>Bauinfos>>liesTabelleBla

Main>>Verarbeitung>>Aktualisiere>>Bauinfos>>liesTabelleBla

wo ein Fehler in liesTabelleBla, nicht wüsste, ob er grad in Eingabe passiert ist, oder einem anderen Modul(Verarbeitung)

Link zu diesem Kommentar
Auf anderen Seiten teilen

jedoch sehe ich nicht viel unterschied
Ich sehe hingegen einen recht großen Unterschied.

Bei der von dir aufgezeigten zweiten Variante lässt sich zwar vielleicht ermitteln, von welcher Klasse aus die Methode liesTabelleBla() aufgerufen wurde und sicher auch noch die Klasse darüber und so weiter. Das gibt ja der Stacktrace schließlich einiges her.

Aber mit der ersten Variante kann man noch zusätzlich ermitteln, unter welchen Umständen die Methode liesTabelleBla() aufgerufen wurde, als sie abflog. Man könnte da also Daten in den "oberen" Klassen haben, die letztlich den Fehler ganz unten in irgend einer Weise verursachen, an die man aber von der unteren Klasse aus nicht mehr rankommt (kann es alles geben). Mit dem Hochthrowen neuer Exceptions kann man jene Information halt sammeln. Und zwar da, wo sie sind - nämlich weiter oben.

Das ist spätestens dann sinnvoll, wenn man Fremdbibliotheken nutzt, dessen Sourcen man nicht hat und in etwa folgendes rauskommen könnte, weil alles sofort ausgegeben wird:

Exception in thread "main" test.TestException

	at test.TestBla.machWas(unknown source)

	at de.tkdmatze.deinpackage.DeineKlasse.rufeTestBlaAuf(DeineKlasse.java:12)

	at de.tkdmatze.deinpackage.DeineKlasse.main(DeineKlasse.java:20)
Dagegen wäre es doch schöner, zumindest zu wissen, mit welchen Parametern die Methode #TestBla.machWas() aufgerufen wurde, oder? Dann hätte man vielleicht sowas:
de.tkdmatze.DeineException: Abflug mit den Parametern A="123", B="456"

	at de.tkdmatze.deinpackage.DeineKlasse.rufeTestBlaAuf(DeineKlasse.java:12)

	at de.tkdmatze.deinpackage.DeineKlasse.main(DeineKlasse.java:20)

caused by test.TestException

	at test.TestBla.machWas(unknown source)

...Das an dieser Stelle nur als kleines und sehr triviales Beispiel.

Ich hab eben mal in der Wikipedia folgenden Satz gefunden: "Es ist sinnvoll, Exceptions abzufangen, um zusätzliche Informationen anzureichern und erneut auszulösen."

Das ist das, was ich auch zu erklären versuche. Die Fehlerquelle zu haben ist schön und gut, aber ohne die Fehlerursache zu kennen, ist das recht nutzlos. Und oft geben einfache Exceptions in den unteren Programmschichten darauf keine Antwort. Von ihnen kriegt man nur die Quelle, mehr nicht.

...So, nun hab ich aber genug vom Diskutieren.

Schönes restliches Wochenende noch!

Gruß,

Arvid.

post scriptum: Neue Exceptions werfen, nennt man im Übrigen nicht Ableiten. Das nennt man neue Exceptions werfen. ;) Ableiten ist das Spezialisieren einer allgemeinen Klasse durch eine Unterklasse.

Link zu diesem Kommentar
Auf anderen Seiten teilen

quick and dirty heisst das, und ist nicht grade "gute" Programmierung schnell geschrieben, das ist auch alles [...] der stil, bei java einfach alles "hochzuthrowen" hat sich nur eingebürgert, weils so schön einfach ist
Mal unabhängig von den Beispielen, die hier ja zu genüge gepostet worden sind, und die du wunderbar ignorierst bzw. den Sinn darin nicht sehen willst: Warum hat sich dann das Konzept Fehler durch Exceptions zu behandeln (übrigens nicht nur in Java - Eiffel konnte es schon immer, Pascal und verwandte Sprachen auch seit längerer Zeit, sogar PHP hat sie in Version 5 als Sprachkonzept integriert) inzwischen in allen modernen Sprachen Einzug gehalten und wird in großen Enterprise Projekten und nicht nur in Qick&Dirty Schnellschüssen durchgesetzt?

Ach ja - richtig, wahrscheinlich weil an allen diesen Projekten nur konzeptlose Coder gesessen haben, die alles schnell fertig haben mussten. Hätte ich auch selbst drauf kommen können. Ich klink mich aus und überlass dem Troll das Spielfeld.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...