cloud2302 Geschrieben 26. August 2008 Geschrieben 26. August 2008 (bearbeitet) Hi@all, da ich meinen Ausbildungsplastz wechseln muss und mich daher beruflich ab 1.9. mit Java rumschlagen muss, dachte ich mir ich fange jetzt schonmal an ein paar kleinere Programme zu schreiben. Da ich von C bis ABAP schon ziemlich viele Programmiersprachen durch habe, dachte ich, dass es ja eigentlich gar nicht so schwer sein kann sich in Java einzuarbeiten, allerdings scheint Java in einigen Sachen sehr begrenzt zu sein, weswegen ich hier ein paar kleine Fragen zur "schönen" Programmierung in Java stellen möchte, die warscheinlich nur Java-Programmierer mit einiger Erfahrung beantworten können(google etc. kanns ned ): 1. Das fehlen von Namespaces Bei der simpelsten Anwendung "Hello World" und den folgenden Beispielen bin ich darauf gestoßen, das im Beispielcode immer geschrieben wird System.out.println("Hello World"); In C# würde man Beispielsweise schreiben using namespace System.out; //o.ä., ihr wisst was ich meine;) und danach würde es reichen die Funktion println(); einfach so aufzurufen. Da Java wohl keine Namespaces hat, stellt sich mir die Frage wie man solche Sachen im allgemeinen abkürzt :confused: 2. Das DRY-Problem Ich habe in einem Testprogramm eine Klasse Employee, die folgende Attribute enthält: String name; String firstName; String street; String streetNumber; String zip; String site; und eine Methode public void updateValue(String type,String value) { //... } die die Werte(nach Prüfung,Bearbeitung,whatever) füllen soll. In anderen Sprachen würde ich zb. als type "firstName" übergeben und zur Laufzeit einen Zeiger auf den Inhalt von type machen und darüber dann das Attribut firstName befüllen, weil das nicht redundant ist. Da Java keine Zeiger kann, dachte ich an die zweit-"schönste" Möglichkeit, einen Switch auf type und dann das jeweilige Attribut befüllen. Da Switch in Java aber scheinbar nur auf primitive Datentypen geht, dachte ich daran, dass ganze als Char-Array zu switchen(was ja intern auch Zahlen sind), aber auch da bekomme ich die Fehlermeldung, dass er nicht drauf switchen kann. Demnach müsste ich jetzt für jede Möglichkeit ein if/elseif Statement hinzufügen, was meiner Meinung nach eine mehr als schlechte Lösung ist. Wie macht das ein kluger Java-Programmiere ohne DRY? 3. Try-Catch Eine andere Klasse von mir soll Daten aus einer Datei lesen und aufbereiten. Im einfachsten Fall etwas in dieser Art: File myFile = new File("C:\\foo.txt"); FileReader data = new FileReader(myFile); char[] temp = new char[(int)myFile.length()]; data.read(temp); String output = new String(temp); System.out.println(output); Nun meldet mir Eclipse als Kompilerfehler(?!?), dass ich nicht abgefangene Ausnahmen habe. Okay, dass ich gezwungen bin Exceptions abzufangen stört mich noch nicht mal so, vielmehr das ein Catch-Block für jede mögliche Ausnahme von Nöten zu sein scheint. Eine einfache Version wie in C# das try { //.... } catch ( e AS Exception) { Console.WriteLine("Es ist folgender Fehler aufgetreten"+e.msg); } um alle Exceptions auf einmal abzufangen und einfach die vorgefertigte Fehlermeldung auszugeben habe ich nicht gefunden. Wir fängt man alle Exceptions mit nur einem Catch-Block ab? :confused: Mit den anderen Java-Eigenheiten habe ich mich bis jetzt abgefunden, aber diese Sachen liegen mir schwer auf dem Herzen und ich hoffe das ihr mir ein wenig unter die Arme greifen könnt. Danke dafür schon jetzt Liebe Grüße Cloud Bearbeitet 26. August 2008 von cloud2302 Zitieren
Dragon8 Geschrieben 26. August 2008 Geschrieben 26. August 2008 Ok, dann fangen wir doch mal an. 1. Das fehlen von Namespaces Also soweit ich mich richtig erinnere, kann man Namesspaces in C# mit Packages in Java vergleichen, jedoch ist der Teil System.out kein Packages. Sondern, System ist eine normale Klasse, diese hat ein öffentliches (public), statisches (static) Attribut out und diese Attribut wiederrum hat die Methode println(String). Mir ist dementsprechend keine Möglichkeit bekann, dies abzukürzen. 2. Das DRY-Problem Ich denke, du willst anhand des Types in deiner Methode wissen welche Variable jetzt mit dem Wert gefüllt werden soll. Um den OOP Richtlinien zu folgen, würde ich für jedes Attribut eine Setter-(falls gebraucht auch noch eine Getter-) Methode schreiben. Wenn du jetzt unbedingt bei deiner einen Methode bleiben willst, fällt mir als erste Lösung nur ein, die gesamten Attribute als Array zusammen zufassen, dann 6 öffentliche statische int-Konstanten anlegen und denen jeweils den Index des jeweiligen Attributes im Array zuzuweisen. Diese Konstanten können dann einfach an die Methode übergeben werden. Also in ungefähr so: private String[] attr = new String[6](); public static final int NAME = 0; public static final int FIRST_NAME = 1; ... public static final int SITE = 5; public void updateValue(int type, String value) { attr[type] = value; } 3. Try-Catch Du kannst mehrere Exceptions genauso abfangen, wie du es in deinem Code ausschnitt schon beschrieben hattest, mit der Mutterklasse Exception halt, ich finde es zwar ehrlich gesagt nicht so sauber, da eigentlich fast jede Exception meist ne gesonderte Fehlerbehandlung verlangt aber wenn du dir dann nur die jeweilige Meldung ausgeben willst ist Exception.printStackTrace() deine Methode. Die gibt auf der Standard-Fehler-Ausgabe den Stack Trace plus Fehlernachricht aus. Zitieren
cloud2302 Geschrieben 26. August 2008 Autor Geschrieben 26. August 2008 Ok, dann fangen wir doch mal an. Zitat: 1. Das fehlen von Namespaces Also soweit ich mich richtig erinnere, kann man Namesspaces in C# mit Packages in Java vergleichen, jedoch ist der Teil System.out kein Packages. Sondern, System ist eine normale Klasse, diese hat ein öffentliches (public), statisches (static) Attribut out und diese Attribut wiederrum hat die Methode println(String). Mir ist dementsprechend keine Möglichkeit bekann, dies abzukürzen. Asooo, da hab ich zugegebener Maßen nicht drüber nachgedacht, dann muss ein Makro-Tool her das mir solche Sachen ersetzt, kann mir vorstellen das die Sachen in ziemlich lang werden können Zitieren
Dragon8 Geschrieben 26. August 2008 Geschrieben 26. August 2008 Asooo, da hab ich zugegebener Maßen nicht drüber nachgedacht, dann muss ein Makro-Tool her das mir solche Sachen ersetzt, kann mir vorstellen das die Sachen in ziemlich lang werden können Ich finde das hält sich noch in Grenzen, zur Not kann man in Java ja auch innerhalb eines Befehls Zeilenumbrüche einfügen und in ner neuen Zeile weiter schreiben, der Befehl ist ja erst beim Semikolon zu Ende. Da ich aber gelesen habe, dass du Eclipse einsetzt: Schreib mal "syso" an die Stelle wo du was ausgeben willst und drück dann STRG + Leertaste (für die Autovervollständigung), dann macht er daraus auch System.out.println(String); .. wollte damit aber eigentlich auf die generelle Problematik Fallunterscheidung bei Strings hinaus. Dachte da gäbe es irgendeine schönere und saubere Möglichkeit für. Leider gibt es das nicht. Java hat leider noch kein Switch für Objekte, deswegen auch nicht für Arrays, da die ähnlich gehandhabt werden. Jedoch habe ich mal gelesen, dass Switch für Strings in einer der nächsten Versionen noch kommen sollte...keine Ahnung ob das noch stimmt. Zitieren
Plexo Geschrieben 26. August 2008 Geschrieben 26. August 2008 1. Das fehlen von Namespaces Seit Java 5 kann man das static import verwenden: import static java.lang.System.out; [...] out.println("Hallo Welt!"); [...] Siehe auch Static Import Gruß Zitieren
Panke Geschrieben 26. August 2008 Geschrieben 26. August 2008 (bearbeitet) Um den OOP Richtlinien zu folgen, würde ich für jedes Attribut eine Setter-(falls gebraucht auch noch eine Getter-) Methode schreiben. Welche OOP Richtlinien? Hat da einer 15 Richtlinien in Stein gemeißelt? Also ich finde ja, elegant programmieren / schönes OOP geht in Java nicht. cloud2302 mir fällt dazu als Möglichkeit noch ein, ein assoziatives Feld zu nutzen, in denen du Referenzen auf Objekte gleicher Schnittstelle vorhälst. Diese Objekte haben dann eine Methode, der du den neuen Wert übergibst, eventuelle Prüfungen durchführt und den Wert setzt. Als Indizes nimmst du dann die Methodennamen. Das spart dir aber keine Tipparbeit und ist meiner Meinung nach auch nur ein Krampf, um den offensichtlichen Mangel an Funktionszeigern wie in C zu umgehen. Bearbeitet 26. August 2008 von Panke Zitieren
cloud2302 Geschrieben 26. August 2008 Autor Geschrieben 26. August 2008 Nett nett was ihr schreibt, vielen Dank für eure Hilfe. @Panke: Jop, das scheint ein kruder Hack zu sein um Funktionalität nachzubilden die's ned gibt, sei mir ned böse wenn ich das ned ausprobiere Das Gefühl, dass schönes Programmieren mit Java an vielen Stellen nicht möglich(oder üblich) ist, habe ich heute auch noch beim lesen von Fremdcode bekommen. Werde mich wohl oder übel damit abfinden müssen, in Privatprojekten werde ich Java aber bestimmt nicht einsetzen. @Plexo: static import scheint ja richtig cool zu sein, ich muss nur aufpassen das in Maßen und nicht in Massen einzusetzen, kann mir gut vorstellen wie unleserlich der Code sonst wird. @Dragon8: Das habe ich vor ein paar Minuten auch gelesen, allerdings ist das laut dem gefunden Forumsthread auch noch in den Sternen. Dabei habe ich auch direkt gelernt, das man strings nicht mit == vergleichen darf Oo Manche Sachen finde ich in Java ja richtig gut gelöst, aber bei anderen kann man einfach nur den Kopf schütteln...komische Programmiersprache... Zitieren
Dragon8 Geschrieben 26. August 2008 Geschrieben 26. August 2008 @Dragon8: Das habe ich vor ein paar Minuten auch gelesen, allerdings ist das laut dem gefunden Forumsthread auch noch in den Sternen. Dabei habe ich auch direkt gelernt, das man strings nicht mit == vergleichen darf Oo Naja aber das mit "==" ist doch wirklich einfach zu verstehen, das müsste doch in C-Varianten ähnlich sein. "==" vergleicht die Referenz von Objekten aber nicht den Inhalt. Um den Inhalt zu vergleichen verfügt jedes Objekt über eine equals(Object)-Methode. Zitieren
Panke Geschrieben 26. August 2008 Geschrieben 26. August 2008 Naja aber das mit "==" ist doch wirklich einfach zu verstehen, das müsste doch in C-Varianten ähnlich sein. "==" vergleicht die Referenz von Objekten aber nicht den Inhalt. Um den Inhalt zu vergleichen verfügt jedes Objekt über eine equals(Object)-Methode. Dafür gibt's (nicht nur) in C++ Operatorüberladung. In C selber gibt's ja Zeichenketten nicht wirklich. Da hat man ja nur [const] char*, klar dass da kein Inhalt verglichen wird. Zitieren
kein-tee Geschrieben 27. August 2008 Geschrieben 27. August 2008 2. Das DRY-Problem Man könnte hier durchaus auch mit Aufzählungen arbeiten, wenn du dein Schema beibehalten möchtest: String name; String firstName; ... public static enum Type{ name, firstName, ... }; public void updateValue(String type, String value) { switch (Type.valueOf(type)) { case name: ... break; case firstName: ... break; ... } ... } Sinnvollerweise kann man dann auch jenes Beispiel verwenden: public void updateValue(Type type, String value) { switch (type) { case name: ... break; case firstName: ... break; ... } ... } // entsprechender Aufruf updateValue(Employee.Type.firstName, "Homer"); // oder für ganz faule import static package.Employee.Type.firstName; updateValue(firstName, "Homer"); Werte kann man auch per Reflections zuweisen, ohne das Feld 'per Namen' direkt anzusprechen: Field field = this.getClass().getDeclaredField(type); field.set(this, value); Gruß Zitieren
chill3r Geschrieben 27. August 2008 Geschrieben 27. August 2008 zu dem DRY: Wie wärs mit ner Map? Denn was du haben willst ist ja nichts anderes als eine Key->Value zuordnung. Zitieren
Empfohlene Beiträge
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.