Ergebnis 1 bis 17 von 17

Thema: [Tutorial] Java #2 - Von Variablen und anderen Wundern

  1. #1

    [Tutorial] Java #2 - Von Variablen und anderen Wundern

    Zurück zu Teil 1 - Hello Java

    Musterlösungen zu Teil 1
    Ich denke, die ersten Aufgaben waren so einfach, dass ich die Lösungen nicht weiter kommentieren muss und es kamen auch keinerlei Rückfragen. Deshalb hier nur der reine Code im Spoiler. Die Klassennamen sind natürlich willkürlich gewählt.



    Teil 2 - Von Variablen und anderen Wundern
    Im letzten Teil haben wir fest vorgegebene Texte ausgegeben. Das ist für den Anfang nett, aber auf Dauer langweilig. Um für mehr Abwechslung zu sorgen, müssen wir auf Benutzereingaben reagieren. Um das zu tun, brauchen wir aber erstmal eine Möglichkeit, diese Eingaben zu speichern. Eine Art Behälter also.

    Diese "Behälter" nennen sich Variablen. Sie speichern alles Mögliche, von Zahlen über Texte bis hin zu komplexeren Dingen. Allerdings kann jede Variable nur eine bestimmte Art von Daten speichern. Stellt euch das für den Anfang mal bildlich vor. Flüssigkeiten lagert man in Flaschen, Äpfel in Kisten. Mit etwas Aufwand kann man sicher auch Äpfel in Flaschen pressen und Kisten dicht genug kriegen, um darin Flüssigkeiten zu speichern, aber normal macht man sowas nicht.

    Die elementaren Datentypen
    Das Einfachste, was man speichern kann, sind Zahlen. Für den Computer ist alles eine mehr oder weniger komplexe Anordnung von Zahlen. Jeder Text und jedes Bild sind aus Zahlenwerten zusammengesetzt. Java kennt gleich mehrere Datentypen für Zahlen:

    byte: für ganzzahlige Werte von -128 bis +127, nimmt 1 Byte im Speicher ein.
    short: für ganzzahlige Werte von -32768 bis +32767, nimmt 2 Bytes im Speicher ein.
    int: für ganzzahlige Werte von -2147483648 bis +2147483647, nimmt 4 Bytes im Speicher ein.
    long: für ganzzahlige Werte von -9223372036854775808 bis +9223372036854775807, nimmt 8 Bytes im Speicher ein.

    Jetzt fragt sich der ein oder andere vielleicht, warum es so viele Typen gibt, wenn long doch immer passt. Warum nicht immer den größten Datentyp nehmen, in den schließlich alles reinpasst? Die Frage ist gar nicht so dumm, zumal moderne Prozessoren intern ohnehin nur noch mit int oder long rechnen und beim Schreiben in den Arbeitsspeicher einfach einen Teil abschneiden. Relevant wird das vor allem dann, wenn ihr viele Zahlen speichern wollt. Wenn ihr mal Listen von 1000 Zahlen oder mehr verwaltet (und glaubt mir, das passiert euch früher, als euch lieb ist), macht es dann eben doch einen Unterschied, ob ihr damit 1 KB RAM belegt oder 8. Ich versuche das auch nochmal bildlich darzustellen. Ob ihr eine 0,5 Liter Flasche oder eine zu 1/4 volle 2 Liter Flasche in den Kühlschrank stellt, macht keinen wirklichen Unterschied, aber stellt euch vor, ihr müsst das Zeug palettenweise lagern. Dann seid ihr froh, wenn jede Flasche nur so groß ist, wie sie wirklich sein muss. Als Faustregel gilt hier: wenn ihr einzelne Zahlen verarbeitet, die ihr nur kurz braucht, ist es beinahe egal. Wenn ihr viele Zahlen braucht oder Variablen lange behaltet, solltet ihr euch überlegen, was ihr braucht. Zwar gilt auch hier "im Zweifelsfall eine Nummer größer", aber wenn ihr mit 100% Sicherheit sagen könnt, dass eine Variable nur Werte zwischen 0 und 100 annehmen kann, dann macht es keinen Sinn, ein short zu verwenden.

    Soviel zu den ganzen Zahlen, aber natürlich braucht man gelegentlich auch mal etwas mehr Genauigkeit und will nicht mit Brüchen hantieren. Dafür kennt Java wie praktisch alle modernen Sprachen "Floating Point Numbers" - Fließ- oder Gleitkommazahlen. Hinter diesem doch eher komplex anmutenden Namen verbirgt sich ein recht einfaches Konzept. Wenn die Zahl vor dem Komma (betragsmäßig) groß ist, werden wenige Nachkommastellen gespeichert, wenn der ganzzahlige Anteil (betragsmäßig) klein ist, werden viele Nachkommastellen gespeichert. Auch dafür gibt es in Java wieder mehrere Typen:

    float: für Gleitkommazahlen von -3.40282347e38 bis +3.40282347e38, nimmt 4 Bytes im Speicher ein.
    double: für Gleitkommazahlen von -1.79769313486231570e308 bis +1.79769313486231570e308, nimmt 8 Bytes im Speicher ein.

    Hier kommt bei der Entscheidung, welchen Typ man nimmt noch dazu, dass diese Typen dadurch, dass sie eben Gleitkommazahlen sind, sich nicht nur darin unterscheiden, wie große/kleine Werte angenommen werden können, sondern auch in der Genauigkeit. Da Computer im Binärsystem rechnen und nicht im Dezimalsystem, ist ein float zwar hervorragend geeignet, um 1/1024 exakt darzustellen, dafür hapert es bei 1/1000. Deshalb ist in den meisten Fällen, wenn exakte Werte gebraucht werden, double besser geeignet.

    Dann fehlen uns noch zwei der sogenannten elementaren Datentypen:

    boolean: kann nur die Werte true (wahr) und false (falsch) annehmen, nimmt 1 Byte im Speicher ein.
    char: beinhaltet Zeichen, also Buchstaben, Zahlen, Sonderzeichen, etc. gemäß des Unicode Standards, nimmt 2 Bytes im Speicher ein.

    Alle anderen Datentypen, etwa die im ersten Teil erwähnten Strings sind aus diesen acht elementaren Typen zusammengesetzt.

    Einige Hinweise, besonders für Umsteiger:
    • Java kennt keine unsigned Datentypen, also Typen, die nur positive Zahlen speichern.
    • short, int und long sind im Gegensatz zu anderen Sprachen plattformunabhängig und können sich deshalb von den gleichnamigen C-Datentypen unterscheiden.
    • char ist im Gegensatz zu anderen Sprachen nicht der kleinste Datentyp. Diese Rolle übernimmt hier byte.


    Genug der Theorie, hier kommt der Code!
    Jetzt habe ich euch lange genug mit der Theorie gequält, jetzt wird wieder "richtig" programmiert. Zunächst muss man wissen, wie man eine Variable erstellt oder "deklariert", wie es Programmierer nennen, die sich für gebildet halten. An sich ist das ganz einfach:

    Code (Java):
    typ name;
    typ name = anfangswert;


    Diese beiden Varianten gibt es. Bei der ersten wird eine Variable erstellt und mit dem Standardwert initialisiert. Je nach Typ ist das 0 oder false. Bei der zweiten Variante kann man den Wert, mit dem die Variable initialisiert wird, selbst angeben. Für die Namen gelten wieder die gleichen Regeln wie für Klassen- und Methodennamen. Buchstaben, Zahlen und Unterstriche, erstes Zeichen ein Buchstabe. Sehen wir uns das einmal direkt in einem Programm an.

    Code (Java):
    class Variablenspielchen {
        public static void main(String[] args) {
            byte foo = -23;
            short bar = 42;
            long batz;
            double BATZ = 26.081988;
            boolean isNichWahr = true;
        }
    }


    Die ersten und letzten beiden Zeilen dürften in der Zwischenzeit klar sein. Die werde ich in den nächsten Beispielen auch teilweise weglassen, einfach der Übersicht halber und um sie nicht immer tippen zu müssen. Für ein ausführbares Programm müsst ihr sie aber natürlich trotzdem einfügen. Ich habe hier im Übrigen etwas getan, was man normalerweise dringend vermeiden sollte. Ich habe den Variablen nichtssagende Namen gegeben. Eigentlich sollte man sich angewöhnen, allen Variablen sinnvolle Namen wie alter oder anzahlEinträge zu geben, selbst wenn man sie nur für die nächsten drei Zeilen braucht. Das fördert die Übersicht enorm. Außerdem sollte euch noch eine Sache auffallen. batz und BATZ sind zwei unterschiedliche Variablen. Der Java Compiler unterscheidet zwischen Groß- und Kleinschreibung. Deshalb solltet ihr euch da auf eine einheitliche Form festlegen. Ich schreibe zum Beispiel Klassen groß und (fast) alles andere klein. Das entspricht auch in etwa dem etablierten Standard.

    Toll, jetzt haben wir Werte gespeichert. Kann man damit auch was machen?
    Selbstverständlich. Alles andere wäre auch arg sinnlos, oder? Zuallererst zeige ich euch, wie man Variablen ausgibt. Das ist nicht viel schwerer, als das, was wir in Teil 1 gemacht haben. Alles was sich ändert, ist, dass ihr System.out.println die Variable als Parameter übergebt, statt einen festen Wert einzutragen.

    Code (Java):
    int sinndeslebens = 42;
    System.out.println(sinndeslebens);


    Wie ihr seht, hat sich nicht so unheimlich viel getan. Das Programm gibt wie zu erwarten die Zahl 42 aus. Aber natürlich ist das nicht alles, was man mit Variablen machen kann. Schließlich sind sie dem Namen nach variabel, das heißt, ihr Wert kann sich ändern. Das sieht dann ungefähr so aus.

    Code (Java):
    int zahl1 = 42;
    int zahl2 = 23;
     
    zahl1 = 5;
    zahl2 = zahl1;


    Wie ihr seht, kann man einer Variable also entweder direkt einen neuen Wert zuweisen oder den Wert einer anderen Variable. Nach Ausführung dieses Codes haben also beide Variablen den Wert 5. Es geht aber natürlich noch schöner. Während links vom = immer ein Variablenname stehen muss, können rechts beinahe beliebig komplexe Ausdrücke ausgewertet werden. Dafür stehen zunächst einmal die Operatoren + (Addition), - (Subtraktion), * (Multiplikation) und / (Division) zur Verfügung. Bei der Division ist noch zu beachten, dass grundsätzlich abgerundet wird, wenn mit Ganzzahlen gerechnet wird. Außerdem kann man Klammern setzen.

    Code (Java):
    int zahl1 = 5;
    int zahl2 = -23;
    int zahl3 = 42;
    int zahl4 = 16 * 7;
     
    zahl4 = zahl1 + zahl2 - 16;
    zahl1 = (zahl4 + zahl3) / 2;
    zahl3 = -25 * zahl2;
     
    System.out.println("Zahl 1: " + zahl1);
    System.out.println("Zahl 2: " + zahl2);
    System.out.println("Zahl 3: " + zahl3);
    System.out.println("Zahl 4: " + zahl4);


    Führt den Code einfach mal aus und versucht nachzuvollziehen, wie die Variablen zu ihren neuen Werten gekommen sind. Außerdem sieht man im Beispiel gleich zwei weitere Stellen, an denen man solche Ausdrücke verwenden darf. Bei der Initialisierung von Variablen und in Methodenparametern. Bei letzteren mag euch einiges aber vielleicht etwas komisch vorkommen. Wir addieren hier eine Zahl zu einer Zeichenkette. Was soll das denn? Funktioniert das überhaupt? Ja, das tut es. Der Java Compiler richtet sich nämlich im Zweifelsfall nach dem linken Operanden und passt den rechten möglichst so an, dass er zum linken passt. Das heißt, aus der Variable zahl2 wird erstmal die Zeichenkette "-23" gemacht und dann werden zwei Zeichenketten "addiert", was bei Zeichenketten einfach bedeutet, dass sie aneinandergehängt werden. Denkt nochma kurz drüber nach und überlegt dann, warum im nächsten Beispiel die erste Zeile funktioniert, die zweite aber nicht.

    Code (Java):
    System.out.println("" + 42 + "ist eine tolle Zahl.");
    System.out.println(42 + "ist eine tolle Zahl.");


    Außerdem wie versprochen noch die Demonstration, dass 21 etwas grundlegend anderes ist, als "21". Seht euch folgenden Code an:

    Code (Java):
    System.out.println(21 + 21);
    System.out.println("21" + 21);
    System.out.println("21" + "21");


    Die erste Zeile gibt 42 aus, die beiden anderen 2121. Das kommt daher, dass in der ersten Zeile zwei Zahlen addiert werden und das Ergebnis in eine Zeichenkette umgewandelt wird. In der zweiten Zeile wird der rechte Operand in eine Zeichenkette umgewandelt, um zum linken zu passen und somit werden zwei Zeichenketten miteinander verknüpft. In der dritten Zeile findet gar keine Konvertierung statt, es werden direkt zwei Zeichenketten verknüpft.

    Musterlösungen zu Teil 2
    Folgen. Es ist 2 Uhr morgens und mir fallen grade keine sinnvollen Aufgaben ein.

    Geändert von DFYX (20.10.2009 um 14:32 Uhr)

  2. #2
    Kurze Notiz für die fortgeschritteneren Leser: ich hätte eigentlich gerne noch Sachen wie ++, += und sowas reingenommen, aber das Kapitel wurde immer länger und länger. Evtl. werde ich das nachträglich nochmal umstrukturieren.

    Außerdem hätte ich eigentlich sehr gerne noch Input mit reingenommen, aber folgendes will ich keinem Anfänger antun:

    Code (Java):
    int meinezahl;
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    try {
        meinezahl = Integer.parse(br.readLine());
    } catch(IOException e) {
        System.out.println("Konnte nicht lesen.");
    } catch(NumberFormatException e) {
        System.out.println("Das ist keine Zahl.");
    }


    Hat jemand Ideen, wie ich sowas schonender beibringe?

  3. #3
    Zitat Zitat von DFYX Beitrag anzeigen
    Hat jemand Ideen, wie ich sowas schonender beibringe?
    Nicht wirklich. :-/ Java nimmt einem da eben nichts ab, wenn man einfach Nutzereingaben lesen will, muss man auf Script-Sprachen wechseln. <__<"
    Du könntest erstmal direkt Bytes aus System.in lesen, dann ersparst du dir immerhin die ganzen geschachtelten Konstruktoren. Wenn du dann System.out.write() verwendest, kannst du sie sogar wieder sinnvoll ausgeben. Alternativ sammelst du ein Array von Bytes und machst einen String draus. Und damit, dass das beides ziemlich grauenhaft ist, hast du auch gleich die Motivation, sie mit der "eleganteren" Variante zu quälen.

    Naja, und es gäbe natürlich noch java.util.Scanner, der das Beispiel immerhin schon deutlich vereinfachen würde. *kratz* Hm, eigentlich ist der wohl sogar die Lösung, aber das da oben will ich nicht umsonst getippt haben. XD

  4. #4
    Ich habe oft gesehen, dass auf bestimmte Themen solange verzichtet wird, bis genügend Wissen vermittelt wurde. Andererseits benutzt du auch bereits Packages und Module (Klassen natürlich sowieso), ohne, dass der Teilnehmer weiß wofür sie sind und wie sie funktionieren.
    Was diese angeht, hast du im vorherigen Tutorial geschrieben, dass dafür Grundkenntnisse der Objektorientierung benötigt werden, IMO ist Modulare Programmierung aber nicht (unbedingt) Teil der Objektorientierten Programmierung und kann vorerst zumindest vereinfacht an einem bildlichen Beispiel erklärt und später vertieft werden.

    BTW: Beim Kommentar zum ersten Codebeispiel, im Satz "Bei der zweiten Variante kann man den Typ selbst angeben" sollte "Typ" eigentlich "Wert", oder "Wert, mit dem initialisiert wird" heißen.

    Und bei der Aufzählung der Operatoren hast du die Klammern bei "Multiplikation" vergessen.

    Geändert von Kyuu (20.10.2009 um 13:31 Uhr)

  5. #5
    Zitat Zitat von Kyuu Beitrag anzeigen
    BTW: Beim Kommentar zum ersten Codebeispiel, im Satz "Bei der zweiten Variante kann man den Typ selbst angeben" sollte "Typ" eigentlich "Wert", oder "Wert, mit dem initialisiert wird" heißen.

    Und bei der Aufzählung der Operatoren hast du die Klammern bei "Multiplikation" vergessen.
    Fixed.

  6. #6
    Wieder sehr schönes übersichtliches Tutorial
    (Leider kann ich keine Rep-punkte geben, da ich zuerst ander bewerten musss :/)

  7. #7
    Zitat Zitat von DFYX Beitrag anzeigen
    Kurze Notiz für die fortgeschritteneren Leser: ich hätte eigentlich gerne noch Sachen wie ++, += und sowas reingenommen, aber das Kapitel wurde immer länger und länger. Evtl. werde ich das nachträglich nochmal umstrukturieren.

    Außerdem hätte ich eigentlich sehr gerne noch Input mit reingenommen, aber folgendes will ich keinem Anfänger antun:

    Code (Java):
    int meinezahl;
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    try {
        meinezahl = Integer.parse(br.readLine());
    } catch(IOException e) {
        System.out.println("Konnte nicht lesen.");
    } catch(NumberFormatException e) {
        System.out.println("Das ist keine Zahl.");
    }


    Hat jemand Ideen, wie ich sowas schonender beibringe?
    Du könntest eine Hilfsklasse erstellen die statische eine init und mehrere read Methoden bereitstellt. Oder halt in dieser Klasse ein Console Objekt benutzt. Dann kann man die einfach importieren was für Anfänger ja auch einfach sein sollte. Und wenn du dann Exceptions und OOP abgearbeitet hast kannst du dein Beispiel nochmal erklären.


    @ssj5000:
    Stimmt hast recht.
    Ich wusste garnicht das eine Scanner Klasse existiert, die Java API is irgendwie zu groß.

    Geändert von uncreative (15.11.2009 um 18:03 Uhr)

  8. #8
    Zitat Zitat von uncreative Beitrag anzeigen
    Du könntest eine Hilfsklasse erstellen die statische eine init und mehrere read Methoden bereitstellt. Oder halt in dieser Klasse ein Console Objekt benutzt. Dann kann man die einfach importieren was für Anfänger ja auch einfach sein sollte. Und wenn du dann Exceptions und OOP abgearbeitet hast kannst du dein Beispiel nochmal erklären.
    Anderer Punkt bei OOP: Man muss nicht Sachen neu erfinden die es schon gibt.

    Code:
    Scanner s = new Scanner(System.in);
    int i = s.nextInt()
    http://java.sun.com/j2se/1.5.0/docs/...l/Scanner.html

  9. #9
    Wo bleibt der nächste Teil? Wir wollen doch Java lernen!

    Nee, eigentlich wollte ich nur mal kurz berichten, wie Java bei mir in der Vorlesung beigebracht wird: Wir benutzen BlueJ, eine recht simple IDE mit eingebautem Debugger und vor allem Konsole, und alles, was unsere Methoden an Eingaben brauchen, bekommen sie über Argumente. Ich will damit nicht sagen, dass es hier genau so gemacht werden sollte, da hier der Fokus eher auf dem "ich will schnell etwas sinnvolles damit machen können" liegt, in der Vorlesung aber auf "Lernt, Algorithmen zu entwickeln, Programmierparadigmen anzuwenden und das ganze dann in Java zu implementieren" (weswegen wir auch in der 10. Vorlesung noch nicht über das Implementieren des Sieb von Eratosthenes und das Zusammenfassen von Variablen als Verbunde/Klassen hinaus sind). Und natürlich zäumen wir das Pferd von vorne auf und lernen erstmal, was OOP ist. ^^
    (auch anzumerken ist, dass unsere Vorlesungen alles andere als einsteigerfreundlich sind, und ich vermutlich arge Probleme hätte, wenn ich nicht schon einige andere Sprachen beherrschen würde...)

    Also, leider keine Lösung für dein Problem, Fyx, aber ich hab mir gedacht ich erzähls mal...

  10. #10
    Der nächste Teil kommt, wenn sich ein Freiwilliger findet, der ihn schreibt. Ursprünglich war es ja so ausgemacht, dass immer abwechselnd geschrieben wird. Falls sich aber keiner finden sollte, werde ich demnächt weitermachen. Diese Woche siehts nur aus Zeitgründen ziemlich schlecht aus.

  11. #11
    orc: das dürfte normal sein, die erste Informatik-Vorlesung sieht bei uns recht ähnlich aus– wir hatten jetzt demletzt Gruppierung in Methoden/Klassenvariablen, und an Algorithmen Sieb des Eratosthenes und binary search. Wobei wir keine IDE haben, sondern tatsächlich vim und die Kommandozeile nutzen.

  12. #12
    Wie siehts eigentlich aus? Wird an dem Projekt noch gearbeitet?

  13. #13
    Eigentlich war ja mal geplant, dass das von verschiedenen Leuten abwechselnd geschrieben wird, aber bevor es untergeht, mach ichs halt allein. Ich hab in der Zwischenzeit auch noch ein größeres Projekt (ca. 23000 Zeilen) in Java hinter mir und hab dadurch noch ein paar Einblicke gewonnen, die hilfreich sein könnten.

  14. #14
    Moin!
    Ich find die Tutorials ganz lustig
    Wobei ich eher ein Tutorial für Applets und 2D Anwendungen bräuchte xD
    Irgendwie scheint mir das ziemlich kompliziert zu sein, zumindest hab ich es bis jetzt nicht hinbekommen. Vielleicht bin auch einfach nur untalentiert.

    Aber ich mag Java nicht, da ist vieles so umständlich und irgendwie blöd :P
    Mach es nur für die Schule, bin aber zum Glück ganz gut darin ( 15 Punkte, yeah! ).

    Naja, viel Glück dir / euch noch

  15. #15
    @ Einlesen schöner beibringen
    Von irgendeiner Uni (hatte in iTunes mal einen Podcast zum Thema Algorithmik) gab's mal eine IO-Klasse mit Funktionen wie readInt, readChar, readString und println, die einem das ganze Gespaße abgenommen hat.

    So als Vorschlag, bis man vom Stoff bis zur Fehlerbehandlung vorgedrungen ist.

  16. #16
    Dürfte der Podcast der Algorithmen-Vorlesung der Uni Osnabrück sein, das angesprochene Paket (AlgoTools) lässt sich auf der Website der Veranstaltung runterladen (und da fliegen irgendwo auch die Videos in nicht-iTunes-Format rum). Den Podcast kann ich btw empfehlen, ich hab die Vorlesung letztes Semester belegt und der Prof erklärt echt gut und einsteigerfreundlich.

  17. #17
    Zitat Zitat von Junta Beitrag anzeigen
    Von irgendeiner Uni (hatte in iTunes mal einen Podcast zum Thema Algorithmik) gab's mal eine IO-Klasse mit Funktionen wie readInt, readChar, readString und println, die einem das ganze Gespaße abgenommen hat.
    Hat ssj5000 doch schon geschrieben: Nimm einfach die vorhandene Scanner-Klasse. Wobei man sich drum streiten kann, ob es schlecht ist, sich mit InputStream, etc. auseinander zu setzen, das ist später ganz nützlich.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •