2. Typen, Operationen und Zuweisungen
2. Typen, Operationen und ZuweisungenDieser Unterrichtsblock beschäftigt sich mit den Grundlagen von Variablen und ihren Belegungen.
Am Ende dieses Blocks haben Sie ein Grundverständnis von
|
- 9975 views
2.1 Schlüsselwörter, Literale, Variablennamen, Kommentare
2.1 Schlüsselwörter, Literale, Variablennamen, KommentareMotivation
Auf dieser Seite lernen Sie wie man die wichtigsten Teile der Sprache Java nennt. Zum Beispiel die Teile einer Zuweisung: |
Schlüsselwörter
Java Schlüsselwörter sind:
abstract | continue | for | new | switch |
assert | default | if | package | synchronized |
boolean | do | goto | private | this |
break | double | implements | protected | throw |
byte | else | import | public | throws |
case | enum | instanceof | return | transient |
catch | extends | int | short | try |
char | final | interface | static | void |
class | finally | long | strictfp | volatile |
const | float | native | super | while |
Die Schlüsselworte in Kategorien gruppiert ergeben:
The Schlüsselworte const und goto sind reserviert auch wenn sie im Moment nicht benutzt werden.
true und false sind technisch gesehen boolsche Literale. (Java 7 Spez. §3.10.3). Das Gleiche gilt für das null Literal (Java 7 Spez. §3.10.7).
Namen (Identifier)
Siehe Java Spezifikation: Identifier
Regeln für Namen in Java:
- Gültige Namen dürfen nur aus Buchstaben, Ziffern, und den Zeichen "_" und "$" bestehen. Sie dürfen beliebig lang sein.
- Das erste Zeichen muss ein Buchstabe, "_" oder "$" Zeichen sein.
- Leerzeichen sind nicht erlaubt
- Schlüsselworte der Sprache Java dürfen nicht verwendet werden. (Boolsche Literale und das null Literal dürfen auch nicht verwendet werden)
- Groß- und Kleinschreibung von Buchstaben wird unterschieden
Literale
Literale dienen zum Beschreiben konkreter Werte in der Sprache Java.
Die Syntax wurde mit Hilfe von regulären Ausdrücken beschrieben.
Syntax | Typ | Beispiel |
---|---|---|
number | int | 17, -17 |
number[l|L] | long | 24l, -24L |
0[x|X]hex | int in Hexadezimaldarstellung | 0x01234567890ABCDEF |
0octal | int in Oktaldarstellung | 071 |
0b{0|1} | int in Binärdarstellung (erst seit Java 7, JSR 334) | 0b101010101010 |
[+|-][number].number | double (Fließkommazahl) | -3.1415 |
[+|-]number[f|F] | float (Fließkommazahl) | -3.1415F |
[+|-]number[d|D] | double (Fließkommazahl) | -3.1415E13D |
[+|-]number | int mit Vorzeichen (signed number) | -3, +3 |
[+|-]number.number[e|E][+|-]number | Exponentendarstellung | -3.1415E10 |
'character' | einzelnes Zeichen | 'a' |
"characters" | Zeichenkette | "aB10" |
"" | Leere Zeichenkette | "" |
\b | Zeichenposition 1 nach links (back space) | |
\t | Tabulator | |
\n | Zeilenvorschub | |
\f | Seitenvorschub | |
\r | Wagenrücklauf | |
\" | Doppeltes Anführungszeichen | |
\' | Einfaches Anführungszeichen | |
\\ | Schrägstrich rückwärts | |
\uNNNN | Unicodezeichen (NNNN in hexadezimal) | |
true | Boolscher Wert | true |
false | Boolscher Wert | false |
Zahlen
- Ganzzahlen
- Dezimalzahlen mit den Ziffern 0 bis 9 und Vorzeichen
- Beispiele: 1, -19, 45678
- Hexadezimalen mit den Ziffern 0 bis 9 und als Ziffer interpretierte Zeichen a bis f und einer Präfix 0x
- Beispiele: 0x1, 0xffff, 0xcafebabe
- Oktalzahlen mit den Ziffern 0 bis 7 und einer vorgestellten 0
- Beispiel 012 (=1*81+2*80=1010 , 077 (=7*81+7*80=6310)
- Dezimalzahlen mit den Ziffern 0 bis 9 und Vorzeichen
- Gleitkommazahlen,
- dargestellt im vertrauten Dezimalsystem
- Nachkommateil durch Punkt abgetrennt
- Beispiel: 5.4, 6. (stellt Gleitkommazahl 6.0 dar)
- Nachkommateil durch Punkt abgetrennt
- Zehnerpotenzen zur Basis Zehn werden mit dem Buchstaben e oder E bezeichnet
- Beispiel: 4E-2 stellt 4*10-2= 0.04 da.
- dargestellt im vertrauten Dezimalsystem
Ab JDK 7: Gruppierung in Zahlenliteralen
Seit JDK 7 sind durch die Integration des Projekts "Coin" (JSR 334) die Gruppierung von Zifferngruppen in Zahlenliteralen durch den Tiefstrich '_' möglich.
Der JSR Spezifikation entnommene Beispiele der neuen Syntax:
1234_5678 1_2_3_4__5_6_7_8L 0b0001_0010_0100_1000 3.141_592_653_589_793d 0x1.ffff_ffff_ffff_fP1_023 // Double.MAX_VALUE
nicht erlaubt sind:
_1234 0x_1234 1234_ 0x1.0_p_-1022
Warnung: Java 7,8,9 werden noch nicht überall eingesetzt:
- Bei Verwendung von javac Javaübersetzern von JDK 5 oder 6 wird diese Syntax nicht akzeptiert
- Bei Verwendung des Javaübersetzers mit Optionen zur Verwendung alter Syntaxstandards wie javac -source 1.6 in JDK 7,8,9 wird die neue Syntax auch nicht akzeptiert werden!
Zeichen und Zeichenketten
- Zeichen: Ein einzelnes Zeichen (char) wird in einfachen Hochkommas geschrieben
- Beispiele: 'a', '2', '!', ' '
- Zeichenketten: in Doppelhochkamma eingeschlossene Folgen von Zeichen
- Beispiele: "Das ist eine Zeichenkette",
- Tipp: Zeichenketten dürfen nicht über den Zeilenrand hinwegreichen!
Zeichenketten ohne Namen nennt man Literale.
Kommentare
Kommentare erlauben das Dokumentieren eines Programmes. Sie werden vom Übersetzer ignoriert.
Java benutzt das Kommentarkonzept auch zur Generierung von Dokumentation. Dokumentationskommentare sind eine Sonderform der Kommentare und werden im Abschnitt zur Dokumentation vorgestellt.
Zeilenkommentare, Zeilenendkommentare
Zeilenkommentare beginnen nach dem doppelten Schrägstrich //. Der Javaübersetzer wird alle Zeichen hinter diesem Kommentarzeichen bis zum Ende der Zeile ignorieren.
Beispiel:
int a = 17; // Dies ist ein Zeilenendkommentar // Dieser Kommentar umfasst eine ganze Zeile int b = 18;
Mehrzeilige Kommentare
Java erlaubt es eine ganze Reihe von Zeilen als Kommentar zu kennzeichnen. Mehrzeilige Kommentare werden mit den Zeichen "/*" (Schrägstrich Stern) eingeleitet und mit der Zeichenkombination "*/" (Stern Schrägstrich) beendet. Hiermit kann man ganze Bereiche als Kommentar markieren.
Beispiel:
/* Hier beginnt ein Kommentar diese Zeile gehört zum Kommentar int i=1; diese Zeile wird nicht als Befehl sondern als Kommentar verarbeitet der Kommentar endet in der nächsten Zeile */
- 21798 views
2.2 Datentypen und Wertebereiche
2.2 Datentypen und WertebereicheDie Typen die ein Entwickler in Java vewendet sind entweder primitive Datentypen oder komplexe Datentypen. Die beiden Kategorien unterscheiden sich in den folgenden Eigenschaften:
Primitiver Datentyp | Komplexer Datentyp (Javaklassen) | |
---|---|---|
Operatoren | viele hochoptimierte Operationen | Nur Operatoren für Objekte (Vergleich, Referenzierung). Ansonsten Methoden der Klasse |
Lebensdauer | hängt vom umgebenden Block, bzw. Objekt ab | liegt im Freispeicher. Lebensdauer hängt von der letzten Referenz auf Objekt ab |
Speicherverbrauch | konstant | variabel |
Speicherort | im Prozedurblock oder im Objekt einer Klasse | immer im Freispeicher (Heap) |
Syntax | immer klein geschrieben | Systemklassen beginnen immer mit Großbuchstaben (Es ist guter Stil auch Benutzerklassen mit einem Großbuchstaben beginnen zu lassen). |
Im nachfolgenden Diagramm wird die Klassifikation der wichtigsten Typen gezeigt:
Die nächsten beiden Abschnitte behandeln die hier gezeigten Typen. Der dritte Abschnitt beschäftigt sich mit den Risiken von Zuweisungen zwischen Datentypen mit unterschiedlichen Wertebereichen.
- 13972 views
2.2.1 Primitive Javatypen
2.2.1 Primitive JavatypenGanzzahlige Datentypen
Datentyp | Bits | Wertebereich | Wertebereiche | Konstante min. | Konstante max. |
---|---|---|---|---|---|
byte | 8=1 byte | -27 bis 27-1 | -128 bis +127 | ||
short | 16=2 byte | -215 bis 215-1 | -32768 bis +32767 | ||
char | 16=2 byte | 0 bis 216-1 | 0 bis +65535 (Sonderfall!) | ||
int | 32=4 byte | -231bis 231-1 | -2147483648 bis +2147483647 | ||
long | 64=8 byte | -263 bis 263-1 | −9,223,372,036,854,775,808 to +9,223,372,036,854,775,807 |
Die maximalen und minimalen Werte der Ganzzahltypen ergeben sich aus der Anzahl der Bits und der internen binären Präsentation. Dies ist am Beispiel des 8-Bit Typen Byte aufgeführt:
Java verwendet für die Darstellung negativer Ganzzahlen das Zweierkomplement. Der Vorteil des Zweierkomplement besteht in der einfacheren Implementierung von Arithmetikeinheiten in Prozessoren. Durch das Zweierkomplement kann das Vorzeichenbit bei Additionen und Subtraktion wie ein regulärers Bit des Wertebereichs behandelt werden.
Dies kann man gut am Beispiel der Zahl -1 erkennen. Addiert man zur Zahl -1 (Binärdarstellung 11111111) eine 1 (Binärdarstellung 00000001) so ergibt durch den Übertrag eine 0 (Binärdarstellung 00000000).
Die Anwendung zur Rechten ist in der Lage alle Ganzzahltypen in die Binärdarstellung umzuwandeln. Das Vorzeichenbit wird in Rot dargestellt. Bei allen Typen die mehr als 16 Bit erfordern wird die Ausgabe nach 16 Bit umgebrochen. Das Bit mit der höchsten Ordnung wird zuerst ausgegeben. Das Bit mit der niedrigsten Ordnung wird am Ende ausgegeben. HinweisDer Typ char ist ein Zahlentyp. Man muss jedoch genau ein beliebiges Zeichen (Buchstabe) im Eingabefenster eingeben. Der Typ char unterscheidet sich vom Typ short in der Benutzereingabe und im Wertebereich. |
Zum Herunterladen: BinaerIntApplet.jar Starten Sie die Anwendung mit einem Doppelclick im Download Ordner oder öffen ein Terminal und führen den folgenden Befehl im Download Ordner aus: java -jar BinaerIntApplet.jar Es sollte ein Fenster erscheinen, dass ähnlich dem folgenden Fenster aussieht: Quellcode des Applets und Anleitung zum Starten als Javaprogramm von der Konsole. |
Fließkomma-Standarddatentypen
Die Zahlendarstellung der Fließkommazahlen geschieht nach der Norm IEEE 754 getrennt nach Bits für Vorzeichen (V), Mantisse und Exponent mit unterschiedlicherAnzahl von Bits abhängig vom Typ nach der Regel:
z= (-1)V*Mantisse*2Exponent
Datentyp | Bits | V (bits) |
Mantisse (bits) |
Exponent (bits) |
Zahlenbereich | Dezimalstellen in Mantisse |
---|---|---|---|---|---|---|
float | 32=4 Byte | 1 | 23 | 8 | ≈-3.4*1038 bis +3,4*1038 | 7 |
double | 64=8 Byte | 1 | 52 | 11 | ≈-1.7*10308 bis +1.7*10308 | 15 |
Die Minimal- und Maximalwerte als Konstanten können über die Attribute MIN_VALUE und MAX_VALUE der Klassen Float und Double abgerufen werden.
Die Berechnung der dezimalen Werte ist für den menschlichen Betrachter nicht so einfach wie die Umwandlung von Ganzzahlen.
Der IEEE 754 Standard ist recht anschaulich in Wikipedia beschrieben. Eine 32 Bit Fließkommazahl berechnet sich nach IEEE 754 wie folgt: = (-1)Vorzeichen*2(Exponent-127)*Mantisse |
Für den 32 Bit Typ float ergibt sich so nach dem Standard IEEE 754 das folgende Bitmuster für verschiedene Werte: |
Das Applet zur Rechten ist in der Lage 32 Bit Fließkommazahlen in die Binärdarstellung umzuwandeln. Die Knöpfe auf der rechten Seite erlauben die Eingabe von Extremwerten wie
|
Zum Herunterladen: BinaerFloatApplet.jar Starten Sie die Anwendung mit einem Doppelclick im Download Ordner oder öffen ein Terminal und führen den folgenden Befehl im Download Ordner aus: java -jar BinaerFloatApplet.jar Es sollte ein Fenster erscheinen, dass ähnlich dem folgenden Fenster aussieht: Quellcode des Applets und Anleitung zum Starten als Javaprogramm von der Konsole |
Wahrheitswerte
Datentyp | Bits | Wertebereich | Werte | Konstante |
---|---|---|---|---|
boolean | 8 (in der Oracle VM) | wahr oder falsch | true,false | Boolean.FALSE, Boolean.TRUE |
Die Anzahl der allokierten Bits hängt von der Implementierung ab (Siehe Spezifikation).
Wichtig: Alle Vergleiche (z.Bsp. (a<b) ) haben als Ergebnis einen boolschen Wert!
Zeichen
Java behandelt einzelne Zeichen intern als ganze Zahlen. Man kann auf den Typ char alle Operationen anwenden die auch für Zahlen erlaubt sind. Der wesentliche Unterschied zum Typ short besteht in der Eingabe und Ausgabe, sowie im Wertebereich. Hier werden lexikalische Zeichen ein- oder ausgegeben.
Wichtiger Sonderfall: Der Typ char benutzt 16 Bit zum kodieren wie auch der Typ short. Die Wertebereiche unterscheiden sich jedoch. Der Typ char kodiert nur positive Werte. Im Englischen wird ein solcher Typ "unsigned" gennannt. Es ist ein Typ ohne Vorzeichenbit.
Datentyp | Bits | Wertebereich | Werte | Kommentar |
---|---|---|---|---|
char | 16 | UC='\u0000' bis '\uffff' | 16 Bit Unicode 4.0 Basic Multilingual Plane (BMP) | "supplementary character" Unterstützung seit JDK 1.5 |
- 19203 views
Speicherplatz für boolean
Wieso werden für den Datentyp boolean 8 Bits benötigt? Eigentlich würde doch 1 Bit ausreichen.
- Log in to post comments
Sinnvolle Überlegung
Sie haben recht.
Alle Prozessoren auf denen man Java ausführen kann haben Registergrößen zum Rechnen von 32 oder 64 Bit.
Selbst alte oder einfache Prozessoren haben Registergrößen von 8 oder 16 Bit.
Das Laden und Speichern eines beliebigen Datums aus dem Speicher erfolgt auch immer in Blöcken die ein Vielfaches von 8 Bit (1 Byte) sind.
Die Prozessoren werden nicht effektiver wenn Sie auf kleineren Datenstrukturen arbeiten müssen.
Noch schlimmer:
Wenn man 8 Boolean in ein einzelnes Byte stecken würde, könnte es sein, dass an acht Stellen mit den acht Variablen gleichzeitig gearbeitet werden müsste. 7 Ausführungseinheiten müssten dann immer auf die achte warten die gerade das entsprechende Byte in ihrem Register bearbeitet.
Platzverschwendung: Boolean werden nicht so häufig wie andere Typen verwendet. Es macht bei den heutigen Hauptspeichergrößen für die meissten Anwendungen keinen Unterschied beim Hauptspeicherverbrauch.
- Log in to post comments
2.2.2 Komplexe Javatypen
2.2.2 Komplexe Javatypen
Diese Datentypen werden mit Hilfe von Javaklassen implementiert. Die so erzeugten Datenstrukturen sind Javaobjekte und haben einen anderen Lebenszyklus als primitive Typen die in einer Javaklasse oder einem Programmierblock benutzt werden. Komplexe Datentypen (Javaklassen) haben einen variablegroßen Speicherplatzbedarf. Sie werden auf dem Javafreispeicher (Heap) angelegt. |
Zeichenketten
Zeichenketten sind in Java kein vordefinierter primitiver Typ. Zeichenketten werden im Paket java.lang mit Hilfe der Klasse String implementiert. Die Klasse String kann jedoch ohne eine spezielle Deklaration wie ein primitiver Typ verwendet werden.
Zeichenketten (Strings) sind in Java nicht modifizierbar. Bei jeder Zuweisung wird eine neue Datenstruktur angelegt. Bei primitiven Typen werden die Werte an der gleichen Stelle überschrieben.
Aufzählungstypen
Aufzählungstypen sind seit JDK 5.0 Bestandteil der Sprache.
Aufzählungstypen |
---|
Aufzählungstypen in Java haben einen Wertebereich der aus einer geordneten Menge von Konstanten besteht. Der aktuelle Wert einer Variablen besteht aus einem der Aufzählungskonstanten |
Aufzählungstypen können nur als Bestandteil einer Klasse deklariert werden. Sie können nicht wie die anderen Basistypen innerhalb eines Blocks deklariert werden. Die Syntax einer Deklaration in einer Klasse ist die Folgende:
Beispiel einer Deklaration in einer Klasse:
class AufzaehlungsDemo { enum Kartenfarbe {KARO, HERZ, PIK, KREUZ} enum Wochentag {MONTAG, DIENSTAG, MITTWOCH, DONNERSTAG, FREITAG, SAMSTAG, SONNTAG} }
Bei der Benutzung von Aufzählungstypen kann nur eine zuvor deklarierte Aufzählungskonstante benutzt werden.
Beispiel der Benutzung in einer Klassenmethode der zugehörigen Klasse:
Wochentag heute = Wochentag.MITTWOCH; Kartenfarbe dame = Kartenfarbe.HERZ;
Aufzählungstypen wurden wie Referenzvariablen (die erst später vorgestellt werden) implementiert.
Referenzen
Referenztypen erlauben es auf andere Objekte zu referenzieren. Sie werden im Abschnitt 7 behandelt.
Übergroße Zahlen (Big Decimal)
Die Java BigDecimal Klassen erlauben das Rechnen mit einer beliebigen Präzision. BigDecimal Klassen werden im Rahmen dieser Einführung nicht behandelt.
- 20063 views
2.2.3 Typkonversion bei Zuweisung verschiedener Typen
2.2.3 Typkonversion bei Zuweisung verschiedener TypenDie Sprache Java und ihre (Lautzeitumgebung) sind typsicher. Typsicher bedeutet, dass bei Zuweisungen für Variablen der Typ der Variable und der zugewiesene Typ eines Wertes geprüft werden und nur sichere Zuweisungen erlaubt werden. Der Übersetzer (javac) erkennt dies schon beim Parsen (lesen) des Quellcodes und meldet dies als Fehler.
Beispiel: Der Wertebereich einer Variable vom Type short endet bei 65535. Der Typ int hat jedoch einen Wertebereich der bis 4294967295 reicht. Im folgenden Fall kann es also zu einem Überlauf kommen:
short a; int b; .... a = b;
Der Übersetzer wird einen Fehler melden, da es hier zu einem Überlauf/Unterlauf aufgrund der unterschiedlichen Wertebereiche kommen kann.
Die Zuweisungskompatibilität kann man als Teilmengen mit dem Symbol ⊃ darstellen. In Java gilt die folgenden Beziehung:
double ⊃ float ⊃ long ⊃int ⊃ short/char ⊃ byte
- Alle Zuweisungen von byte ➔ double sind erlaubt. Java führt hier eine implizite Konvertierung (impliziter Cast) durch, weil es eine sichere Operation ist.
- Alle Zuweisung von double ➔ byte werden vom Übersetzer nicht akzeptiert.
Bei Berechnungen vor der Zuweisung kommen eventuell verschieden Typen in Operationen (z.Bsp.) Addition vor.
Hier verfährt Java nach der folgenden Regel:
- Der jeweils kleinere Operandentyp wird vor der Operation in den größeren konvertiert.
- Die Operanden werden jedoch zumindest in den Typ int konvertiert
- Das Ergebnis hat den gleichen Typ wie die beiden Operanden (nach Konvertierung)
Explizite Typkonvertierungen(Casts)
Um Zuweisungen zwischen inkompatiblen Typen zu erzwingen kann man den Zieltyp in runden Klammern dem Ausdruck voran stellen. Diesen Operator nennt man Castoperator (cast im englischen: gießen, betonieren).
Beispiel:
short a; int b; .... a = (short)b;
Hiermit erzwingt man Operationen die unsicher sein können! Es kann zu Überläufen in Wertebereichen oder Präzisionsverlusten kommen kann. Der Entwickler übernimmt hier die Verantwortung und überstimmt den Übersetzer. Der Castoperator sollte daher nur wenn nötig eingesetzt werden.
Das Applet zur Rechten ist in der Lage einen beliebigen Ganzzahltypen auf einen beliebigen anderen Ganzzahltypen zu zuweisen. Die Variable y enthält den Eingabewert. Den Typ von y kann man in der rechten Spalte wählen. Der Wert von y wird mit Hilfe einer Typkonversion (Cast) auf x zugewiesen. Den Typ von x kann man links wählen. Nach der Wahl der Typen und des Eingabewerts kann die Zuweisung mit dem "Enter" Button gestartet werden. Fragen:
|
Zum Testen bitte runterladen: BinaerCastApplet.jar Starten Sie die Anwendung mit einem Doppelclick im Download Ordner oder öffen ein Terminal und führen den folgenden Befehl im Download Ordner aus: java -jar BinaerCastApplet.jar Es sollte ein Fenster erscheinen welches wie folgt aussieht:
Quellcode des Applets und Anleitung zum Starten als Javaprogramm von der Konsole |
- 13499 views
Genauigkeitsverlust bei Konversion von long-->float
Laut "double ⊃ float ⊃ long ⊃int ⊃ short/char ⊃ byte" ist die Zuweisungen von Long-Literalen auf eine Float-Variable vom Compiler akzeptiert. Aber kommt es hier nicht zu Genauigkeitsverlusten, da long 64 Bit Genauigkeit hat und float nur 32 Bit. Und wenn ja, wieso akzeptiert der Compiler das dann trotzdem?
- Log in to post comments
Korrekte Beobachtung
Korrekte Beobachtung. Ein long Typ kann Werte noch ohne Rundungsfehler korrekt darstellen wo ein float Typ schon im Bereich >1 also 20, 21, 22 etc.
Das ganze ist (wahrscheinlich) erlaubt da
- das Zahlenintervall des Typs float größer als das des Typ long ist. Es gibt also keinen Überlauf an den Grenzen der Zahlenintervalle
- Wer mit dem Typ float arbeitet muss wissen, das hier immer gerundet werden kann.
- Log in to post comments
Applet-Funktionsfehler?
Wenn ich in dem Applett auf der linken Seite den Typ byte wähle und auf der rechten Seite den Typ int. Dann müsste doch oben eigentlich in blauer Schrift die Zuweisung "byte x=(byte) y" stehen, oder? Jedenfalls steht dort "byte x=(int) y"; das würde doch gar nicht funktionieren, denn dann würde ich ja immer noch ein Int-Literal einer Byte-Variablen zuweisen.
- Log in to post comments
2.3 Operatoren und Ausdrücke
2.3 Operatoren und AusdrückeAusdrücke
Ausdrücke in Java sind alles was einen Rückgabewert liefert:
- Konstanten
- Variablen
- Methoden
- Operatoren
Operatoren
Java verfügt über
- unäre (einstellige, monadische) Operatoren
- binäre (zweistellige, dyadische) Operatoren
- einen dreistelligen (ternären, tryadischen) Operator (den Bedingungsoperator "_ ? _ : _")
Unäre Operatoren haben einen einzigen Operanden. Beispiele sind:
|
Binäre Operatoren haben zwei Operanden. Beispiele sind:
|
Arithmetische Operatoren
Die arithmetischen Operatoren können auf die folgenden Typen angewendet werden
- byte
- short
- int
- long
- float
- double
Operator | Beispiel | Semantik |
---|---|---|
+ | a + b | Addition: Summe von a und b |
- | a - b | Subtraktion: Differenz an a und b |
* | a * b | Multiplikation: Produkt von a und b |
/ | a / b | Division: Quotient von a und b |
% | a % b | Modulo: Rest einer ganzzahligen Division von a durch b |
Die Division von Ganzzahlen ergibt immer ganzzahlige Ergebnisse!
Java arbeitet ohne eine Erkennung des Überlaufs der Wertebereiche. Der Entwickler muss selbst die entsprechenden Vorsichtsmaßnahmen ergreifen.
Weiterhin gibt es einstellige (unäre) arithmetische Operatoren
Operator | Beispiel | Semantik |
---|---|---|
+ | +a | Der Wert von a bleibt erhalten (Idempotente Operation) |
- | -a | Der Wert von a wird negiert |
++ |
a++ ++a |
Postinkrement: Der Ausdruck behält ursprünglichen Wert . Der Wert von a wurde um 1 erhöht Präinkrement: Der Wert von a wird um 1 erhöht und der Ausdruck erhält den erhöhten Wert von a |
-- |
x-- --x |
Postdekrement: Der Ausdruck behält ursprünglichen Wert . Der Wert von a wurde um 1 erniedrigt Prädekrement: Der Wert von a wird um 1 erniedrigt und der Ausdruck erhält den verminderten Wert von a |
Die folgen drei Anweisungen bewirken das gleiche:
a = a + 1; a++; ++a;
Bei Inkrementen mit gleichzeitiger Zuweisung ergeben jedoch unterschiedliche Werte für den zugewiesenen Wert
Variante 1 | Wert a | Wert b | Variante 2 | Wert a | Wert b |
---|---|---|---|---|---|
a = 10; b = 4; b = a++; |
10 11 |
4 10 (!) |
a = 10; b = 4; b = ++a; |
10 11 |
4 11 (!) |
Beispiel
Quellcode | Konsolenausgabe |
---|---|
package s1.block2.skript; public class PrePostFixTest { public static void main(String[] args) { int x = 10; int y = 100; System.out.println("x = " + x + "; y = " + y); x++; System.out.println("x++ results in " + x); ++x; System.out.println("++x results in " + x); System.out.println("Set x to 0 "); x=0; System.out.println("x = " + x + "; y = " + y); y=x++; System.out.println("y=x++ (Postfix)"); System.out.println("x = " + x + "; y = " + y); y=++x; System.out.println("y=++x (Prefix)"); System.out.println("x = " + x + "; y = " + y); } |
. . . . . x = 10; y = 100 . x++ results in 11 . ++x results in 12 Set x to 0 . x = 0; y = 100 . y=x++ (Postfix) x = 1; y = 0 . y=++x (Prefix) x = 2; y = 2 . |
Arithmetik der Ganzzahlen
- Alle Operationen auf Ganzzahlen ergeben wieder Ganzzahlen. Dies wird nicht unbedingt von der Division erwartet!
- Versuche durch 0 (Null) zu dividieren lösen eine ArithmeticException Ausnahme aus.
Arithmetik der Fließkommazahlen
Bei der Arithmetik mit Fließkommazahlen werden im Gegensatz zu den Ganzzahlen Überläufe erkannt. Die Fließkommazahlen besitzen eine Reihe Konstanten:
Konstante | Semantik |
---|---|
POSITIVE_INFINITY | Positiv unendlich |
NEGATIVE_INFINITY | Negativ unendlich |
MAX_VALUE | Größter darstellbarer Wert |
MIN_VALUE | Kleinster darstellbarer Wert |
NaN | "Not a number" Dieser Wert ist ungleich zu allen anderen Werten im Wertebereich |
Vergleichsoperatoren
Gleichheit bzw. Ungleichheit bezieht sich auf den Wert der Variablen x und y
Operator | Beispiel | Semantik (Bedeutung) |
---|---|---|
== | x == y | ist x gleich y ? |
!= | x != y | ist x ungleich y ? |
< | x < y | ist x kleiner als y ? |
<= | x <= y | ist x kleiner oder gleich y ? |
> | x > y | ist x größer als y ? |
>= | x >= y | ist x größer oder gleich y ? |
Logische Operatoren
Die logischen Operatoren wirken auf den Typ Boolean der nur den Wert wahr oder falsch kennt.
Operator | Beispiel | Semantik (Bedeutung) |
---|---|---|
! | !a | Negation |
& | a & b | Und |
| | a | b | Oder (inklusiv) |
^ | a ^ b | Entweder-Oder |
&& | a && b | bedingt auswertendes Und |
|| | a || b | bedingt auswertendes Oder |
Bedingungsoperator
Der dreistellige (ternäre) Bedingungsoperator (Konditionaloperator) erlaubt eine Zuweisung von dem Ergebnis einer Bedingung abhängig zu machen. Er hat die Form:
<ausdruck1> ? <ausdruck2> : <ausdruck3>
ausdruck1 muss einen boolschen Wert ergeben. Wird ausdruck1 wahr, so wird ausdruck2 der entsprechenden Variable zugewiesen. Wird ausdruck1 unwahr, so wird der ausdruck3 zugewiesen
Hiermit kann man Zuweisungen wie die Folgende formulieren
int maximum; int x = 1; int y =2 ; maximum = (x > y) ? x : y ;
Das Ergebnis ist 2, da y (=2) größer als x (=1) ist.
Bedingt auswertende logische && und || Operatoren
Die bedingt auswertenden Operatoren werten Terme nur soweit aus bis das Endergebnis fest steht. Dies macht sie sehr effizient.
Im Beispiel:
boolean a = ((1<3) || (4>5));
wird der Term (4>5) nicht mehr ausgewertet. Da (1<3) wahr ist, steht das Endergebnis schon fest.
Die bedingt auswertenden logischen Operatoren wendet man neben Ihrem Geschwindigkeitsvorteil auch gerne an um potentielle Fehler und Ausnahmen zu vermeiden.
Ein Beispiel hierfür ist:
if ((a>0) && (Math.sqrt(a)>2))
Die Wurzel wird nur ausgewertet wenn a größer als Null ist.
Vorsicht: Durch die bedingte Auswertung können unterschiedliche Ergebnisse enstehen wenn in einem Ausdruck gleichzeitig ein Wert verändert wird!
Beispiel:
bedingter "Oder" Operator | einfacher "Oder" Operator | |
---|---|---|
Quellcode |
public static void t1() { int a = 3; int b = 5; if ((a>1) || (a<b++)){ System.out.println ("Hallo"); } System.out.println("b= " + b); } |
public static void t2() { int a = 3; int b = 5; if ((a>1) | (a<b++)){ System.out.println ("Hallo"); } System.out.println("b= " + b); } |
Ausgabe |
Hallo b= 5 |
Hallo b= 6 |
Das Postinkrement (b++) in der linkten bedingten oder Bedingung wird nicht ausgeführt, da der Ausdruck (a>1) schon wahr geworden ist.
Bitoperatoren
Mit Bitoperatoren werden alle Bits einer Variablen einzeln manipuliert.
Operator | Beispiel | Bedeutung |
---|---|---|
~ | ~a | Komplement |
& | a & b | Und |
| | a | b | Oder |
^ | a ^b | exklusives Oder |
Beispiel
package s1.block2.skript; public class BitOperator { public static void main(String[] args) { int a = 7; int b = 6; int result; result = a & b; System.out.println("a = " + a + "; b = " + b + " result = " + result); result = a | b; System.out.println("a = " + a + "; b = " + b + " result = " + result); result = a ^ b; System.out.println("a = " + a + "; b = " + b + " result = " + result); } }
Ergebnis
a = 7; b = 6 result = 6 a = 7; b = 6 result = 7 a = 7; b = 6 result = 1
Erklärung
Variable | Dezimal | Binär |
---|---|---|
a | 7 | 0 0000000 00000000 00000000 00000111 |
b | 6 | 0 0000000 00000000 00000000 00000110 |
result = a & b | 6 | 0 0000000 00000000 00000000 00000110 |
Variable | Dezimal | Binär |
---|---|---|
a | 7 | 0 0000000 00000000 00000000 00000111 |
b | 6 | 0 0000000 00000000 00000000 00000110 |
result = a | b | 7 | 0 0000000 00000000 00000000 00000111 |
Bitschiebeoperatoren
Operator |
Beispiel | Bedeutung |
---|---|---|
<< | a << b | Wert des Ausdrucks sind die Bits von a die um b Positionen nach links verschoben wurden. Es wird mit 0 Bits aufgefüllt. |
>> | a >> b | Wert des Ausdrucks sind die Bits von a die um b Positionen nach rechts verschoben wurden. Es wird mit dem höchsten Bit aufgefüllt. |
>>> | a >>> b | Wert des Ausdrucks sind die Bits von a die um b Positionen nach rechts verschoben wurden. Es wird mit dem "0" Bits aufgefüllt. |
Das kleine Programm rechts erlaubt die drei Bitschiebeoperationen zu testen. Es kann die Bits um jeweils eine Stelle verschieben. |
Hier die jar Datei herunterladen. Das Programm dann mit dem Kommandozeilenbefehl: java -jar IntShiftApplet.jar Es erscheint ein Fenster wie folgt:
Quellcode des Applets und Anleitung zum Starten als Javaprogramm von der Konsole. |
Beispiel
package s1.block2.skript; public class ShiftingBits { public static void main(String[] args) { int x = 4; int result; int shift = 1; result = x << shift; System.out.println("x = " + x + "; shift = " + shift + " result = " + result); result = x >> shift; System.out.println("x = " + x + "; shift = " + shift + " result = " + result); result = result >> shift; System.out.println("x = " + x + "; shift = " + shift + " result = " + result); result = result >> shift; System.out.println("x = " + x + "; shift = " + shift + " result = " + result); result = result >> shift; System.out.println("x = " + x + "; shift = " + shift + " result = " + result); } }
Ergebnis
Die interne Darstellung der verwendeten Werte:
Dezimalwert | Binärwert |
---|---|
8 | 0 0000000 00000000 00000000 00001000 |
4 | 0 0000000 00000000 00000000 00000100 |
2 | 0 0000000 00000000 00000000 00000010 |
1 | 0 0000000 00000000 00000000 00000001 |
0 | 0 0000000 00000000 00000000 00000000 |
Zuweisungs- und Verbundoperatoren
Das Gleichzeichen = dient in Java als Zuweisungsoperator. Die Anweisung
x = y + z;
ist nicht als mathematische Gleichung zuverstehen, sondern als Zuweisung des Ausdrucks auf der echten Seite (y+z) auf die Variable x auf der linken Seite.
Zuweisungen wie:
x = y = 8;
sind auch möglich. Sie haben die gleiche Bedeutung wie
y = 8; x = y;
Für die meisten binären Operatoren gibt es Verbundoperatoren mit denen man einer Variable etwas zuweisen kann und gleichzeitig den alten Wert verwenden kann:
Verbundoperator | entspricht |
---|---|
a += b | a = a + b |
a -= b | a = a - b |
a *= b | a = a * b |
a /= b | a = a / b |
a %= b | a = a % b |
a &= b | a = a & b |
a |= b | a = a | b |
a ^= b | a = a ^ b |
a <<= b | a = a << b |
a >>= b | a = a > b |
a >>>= b | a = a >>> b |
Auswertungsreihenfolge
Für Ausdrücke mit mehreren Operatoren gelten die folgenden Regeln in Bezug auf die Reihenfolge der Auswertung:
- Teilausdrücke in runden Klammern werden wie in der Mathematik als erstes ausgewertet
- Ausdrücke mit unären Operatoren werden anschließend ausgewertet
- Zuletzt werden Teilausdrücke mit mehrstelligen Operatoren ausgewertet
Unäre Operatoren haben alle die gleiche Priorität
Ausführungsreihenfolge von Operatoren
Die Ausführungsreihenfolge von Operatoren bestimmt wie ein Term aufgelöst wir.
Tipp: Es ist guter Programmstil Terme übersichtlich zu gestalten. Verwenden Sie im Zweifelsfall Klammern!
Rang | Operator | Beschreibung |
---|---|---|
1 | =, +=, -=, *= ... | Zuweisungsoperator |
2 | ?: | Bedingungsoperator |
3 | || | Logische Oder |
4 | && | Logisches Und |
5 | | | logisches oder bitweises Oder |
6 | ^ | logisches oder bitweises Entweder-Oder |
7 | & | logisches oder bitweises Und |
8 | ==, != | Vergleichsoperatoren: Gleich, Ungleich |
9 | <, <=, >, >= | Vergleichsoperatoren |
10 | <<, >>, >>> | Schiebeoperatoren |
11 | +, - | Addition, Subtraktion, Verketten von Zeichenketten |
12 | *, /, % | Multiplikation, Division, Rest |
13 | ++, --, +, -, ~, ! | unäre (einstellige) Operatoren |
Auswertung von Operatoren mit gleicher Priorität
Es kann vorkommen, dass ein Ausdruck mehrere Operatoren der gleichen Priorität besitzt. In diesen Fällen wird die Auswertereihenreihenfolge durch die Assoziativität der Operatoren bestimmt.
Operatorenasoziativität |
---|
Die Assoziativität von Operatoren ist die Reihenfolge in der Operanden durch Operatoren gleicher Priorität verknüpft werden |
Ist ein Operator linksassoziativ, wird zuerst der linke Operand ausgewertet. Das Beispiel zeigt den Plus- und Minusoperator. Beide haben die gleiche Priorität. Hier wird zuerst der Operand a+b ausgewertet.
Einige Operatoren in Java sind rechtsassoziativ. Ein Beispiel hierfür ist der Zuweisungsoperator
Bewertungsreihenfolge der Operanden eines Operators
Bewertungsreihenfolge der Operanden |
---|
In Java werden die Operanden eines Operators strikt von links nach rechts ausgewertet. |
Diese Regel ist insbesondere wichtig, da Methoden und diverse Operatoren Nebeneffekte haben können. Das bedeutet, dass diese Operatoren den Wert von Variablen während der Auswertung des Gesamtausdrucks verändern. Beispiele sind die Inkrement- und Dekrementoperatoren.
j = i-- -i;
ist ein zulässiger Ausdruck in Java. Der Wert der j zugewiesen wird ist immer 1;
Die Auswertung dieser Zuweisung geschieht in den folgenden Schritten:
- Auswertung des Subtrahenden (und Zwischenspeicherung)
- Dekrement von i
- Auswertung des Minuend und Berechnung der Differenz
- Zuweisung der Differenz auf j
Ein Beispielprogramm zum Testen:
package s1.block2.skript; public class PrePostInkrement { public static void main(String[] args) { int i = 4; int j; j=i-- -i; System.out.println("i: " +i+", j= "+j); } }
Ausgabe:
i: 3, j= 1
Die Auswertung des Ausdrucks und der Zuweisung j= i-- -i; findet wie folgt statt:
i | j | j= i-- -i; | Kommentar |
---|---|---|---|
4 | 0 | j = 4 - i; | Bestimmung des Minuend der Subtraktion |
3 | 0 | j = 4 - i; | Postdekrement von i |
3 | 0 | j = 4 -3; | Bestimmung des Subtrahend der Subtraktion |
3 | 0 | j = 1; | Bestimmung der Differenz |
3 | 1 | Zuweisung |
Regeln für den Ergebnistyp von arithmetischen Ausdrücken (Widening Conversions)
Java kann alle arithmetischen Operationen auch ausführen wenn die Zahlentypen im Ausdruck unterschiedlich sind. Das Ergebnis der Berechnung hängt von den Typen des Ausdrucks ab. Es gilt in der folgenden Reihenfolge:
- Ist einer der Typen ein double, so wird das Ergebnis zum Typ double konvertiert.
- Falls nicht, wird das Ergebnis zu einem float Typen konvertiert wenn ein Typ ein float Typ ist.
- Falls nicht, wird das Ergebnis zu einem long Typen konvertiert wenn ein Typ ein long Typ ist.
- Falls nicht, werden beide Operanden zuerst zu einem int Typen konvertiert.
- 101856 views
Mehrfachzuweisung
Sie schreiben, dass "x=y=8;" die gleiche Bedeutung hat wie "x=8; y=8;". Dabei wird doch x der Wert von y zugewiesen und nicht direkt die Zahl 8, oder? Also müsste "x=y=8;" äquivalent sein mit "y=8; x=y" (da ja die Ausdrücke von rechts nach links ausgewertet werden). Oder?
- Log in to post comments
Richtige Überlegung
Sie haben sehr, sehr wahrscheinlich recht.
Man müsste sich zur finalen Klärung den generierten Bytecode anschauen oder im Debugger zwischen die beiden Zuweisungen kommen.
Der folgende Javacode ist ein starkes Indiz, dass Sie recht haben:
int x,y;
x = y = 8;
//(x = y) = 8; // So etwas geht nicht
x = (y = 8); // So etwas geht. Diese Klammer ist an dieser Stelle wahrscheinlich redundant. y wird hier garantiert vorher belegt.
x = (y = 8)+1; // So etwas geht auch. Damit wird das Prinzip auf die Spitze getrieben. x erhält jetzt den Wert 9.
System.out.println(x);
System.out.println(y);
Hane den Text nach Ihrem Vorschlag geändert.
- Log in to post comments
Hallo Kurs WIBI12C
DHBW-Mannheim - Java Vorlesung - hier sind wir gerade oder ??
Wer guckt alles und findet den comment???
___________c$$$$$$$$$$$$$$$$$$$$$$$$$$h,
________c$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
____d$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
____$$$,d$$$$$$$$$$$$$$$$$$$$$$$$$hc`?$$$$
___$$$u$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$h,?$$
___$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$b$$$
___$$$$$P$$?$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
___$$$$$$$`$$$$$$$$$$$$$$$$$$$$$$$$$d$$$$$$
____$$$$$$c ,nn,?$$$$$$$$$$$$$$$,,`$$$$$$$$
_____$$ MMMMM`$$$$$$$$$$$$F,MMMb`$$$$$$$$
______$$$MMTTM.?$$$$$$$$$$$,MMM $$$$$$$$
_______`$$$$$,M;;;`$$$$$$$$$$´M,,`,$$$$$$
__________?$$$$,
____________?$$$$,( ) $$$$$$$$$$ (´ ),$$$
____________`$$$$.`-´ $$$$$$$$$$,`--´,$$$´
____________$$$$$hh$$$$$????$$$hc$$$$$$$´
___________d$$$$$$$$$ `======´ $$$$$$$;
___________ $$$$$$$$$$$$c,,,,c$$$$$$$$$
____________?$$$$P $$$$$$?????$$??$$$$
______________________$$$$$
_____________________4$$$$$c
____________________,$$$$$$$
__________________z$
________________> z$
_________________
________________`$
_________________?L$$$$$$$$$$$:$
__________________?$$$$$$$$$$$d´
___________________`$$$$$$$$$$F
____________________`?$c`??3$F
____________________CCC_CCC
____________________,;CC_CC;;
____________________`CC__CCC
.,,,,,CCCCCCCCCCCCCCC__CCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCC__CCCCCCC,CCCCCCCCCCC
CCCCCCCCCCCCCCCCCC___CCCCC´`´CCCCCCCCCC
- Log in to post comments
Rechnung
public class PrePostInkrement {
public static void main(String[] args) {
int i = 4;
int j;
j=i-- -i;
System.out.println("i: " +i+", j= "+j);
}
}
Müsste hier für j nicht 0 rauskommen? Und i = 3?
Der Operator -- (also i--;) findet doch erst nach der Zuweisung statt oder?
- Log in to post comments
Erklärung
Ich habe den genauen Ablauf in das Skript eingebaut.
Das Dekrement findet statt nachdem der Minuend bestimmt worden ist.
Das bedeutet, das Dekrement findet nach der Zuweisung des Minuenden statt. Nicht nach der Zuweisung auf j!
Die Zuweisung des Minuenden kann man als Zuweisung auf eine temporäre Variable verstehen.
- Log in to post comments
Ausführungsreihenfolge von Operatoren
Laut diesem Unterpunkt ist Strich vor Punkt. Bitte erklären.
- Log in to post comments
Tippfehler
Bei den unären arithmetischen Operatoren steht "Präidekrement" statt "Prädekrement".
- Log in to post comments
Ternärer Operator rechtsassoziativ?
Hallo,
der ternäre Operator ist ja rechtsassoziativ.
Weshalb ergibt der folgende Ausdruck dann " a größer b"?
int a = 10;
int b = 5;
String r = a > b ? "a größer b" : a < b ? "a kleiner b" : "beide gleich";
System.out.println( r );
Es müsste doch eigentlich erst a < b ausgewertet werden, oder?
- Log in to post comments
2.4 Übungen
2.4 Übungen
2.4.1 Übung: Zuweisungen und TypenErstellen Sie folgende Java-Applikation (Name "Calc"):
|
- Wie groß sind die Wertebereiche der einzelnen Typen?
- Was geschieht wenn man zwei Ganzzahlen (int) dividiert und das Ergebnis ist keine ganze Zahl?
- Was geschieht wenn Sie einen Überlauf in einem Wertebereich einer Variablen provozieren?
2.4.2 Übung: Erlaubte Variablennamen
maxvalue maxValue max_value max value end End 10%ofSum sum10 _10PercentOfSum
2.4.3 Übung: Literale
Warum übersetzt das folgende Programm nicht?
package block2; public class Literale { public static void main(String[] args) { long i1 = 4000000000; long i2 = 4000000000L; System.out.println(i1); System.out.println(i2); } }
2.4.4 Übung: Ausdrücke
Gegeben seien folgende Variablendeklarationen in Java:
long a = 3; int b = 4; short c = 5; byte d = 6;
Welchen Wert liefern die folgenden Ausdrücke und von welchem Typ sind sie?
d / b * a c + b * (d + 1) d / (c - 1) * b / 2 d % b -c % b
2.4.5 Übung: Zuweisungen
long a = 3; int b = 4; short c = 5; byte d = 6;
a = b + 3 * (d + 1); b = c * c; c = b / 3; d = (byte)a + b; d = (byte) ( a + b);
2.4.6 Übung: Ausdrücke
Schreiben Sie einen Java-Ausdruck, der eine ganze Zahl x auf das nächstliegende Vielfache von 100 rundet.
Beispiel:
- der Wert 149 soll auf 100 abgerundet werden
- der Wert 150 auf 200 aufgerundet werden.
2.4.7 Übung: Zeitrechnung
2.4.8 Übung: Polynomberechnung
y = a * x3 + b * x2 + c * x + d
2.4.9 Übung: Abstand zwischen Punkten
Schreiben Sie ein Java-Programm, das die x- und y-Koordinaten zweier Punkte einliest und den Abstand zwischen ihnen berechnet und ausgibt.
Tipp: Math.sqrt() berechnet eine Wurzel
2.4.10 Übung: Berechnung von ∏ (Pi)
Die Kreiszahl ∏ kann durch folgende Näherungsformel berechnet werden:
i ∏ n (-1) 1 1 1 1 --- = ∑ ------- = 1 - --- + --- - --- + --- - ... 4 i=0 2*i+1 3 5 7 9
2.4.11 Übung: Analoge Uhr
Implementieren sie notwendigen Berechnungen zum Anzeigen von Sekunden-, Minuten, Stundenzeigern einer analogen Uhr.
Vorbereitungen
- Erzeugen Sie in einem Verzeichnis die beiden Quelldateien Uhr.java und Zeiger.java. Der Quellcode der beiden Dateien ist weiter unten aufgeführt.
- Übersetzen Sie die beiden Dateien in diesem Verzeichnis mit dem Befehl javac Uhr.java Zeiger.java
- Führen Sie das Programm aus: java Uhr
- Beobachten Sie den blauen Sekundenzeiger. Er wächst in jeder Sekunde um ein Pixel nach rechts unten
Aufgabe
Implementieren Sie die korrekte Position der Spitze der drei Zeiger abhängig von der aktuellen Zeit in der Klasse Zeiger.java
Die korrekte Spitze wird durch eine x und y Koordinate beschrieben. Der Ursprung des Koordinatensystems liegt in der Mitte der Uhr. Postive X-Koordinaten reichen nach rechts. Positive Y-Koordinaten reichen nach unten. Die Richtung der Y-Koordinaten ist typisch für für Java GUIs in Swing oder AWT.
Hinweis: Implementieren Sie zuerst den Sekundenzeiger. Er erlaubt ihnen binnen 60 Sekunden die visuelle Kontrolle Ihrer Programmierung. Die Programmierung der Minutenzeiger und Stundenzeiger sind dann sehr einfach, da sie auf der gleichen mathematischen Formel basieren.
Empfohlendes Vorgehen:
- Erstellen Sie die mathematische Formel für die aktuelle Spitze des Sekundezeigers abhängig von der Sekunde zwischen 0 und 59. Sie benötigen hierzu die Sinus- und Cosinusfunktion sowie die Konstante PI
- Finden sie in der Klasse Zeiger.java die Methoden sekundeX und sekundeY
- Ersetzen Sie in der Trivialimplementierung die Zuweisung xs=s; bzw ys=s; durch die korrekte Implementierung der beiden mathematischen Ausdrücke
- Sichern Sie die Datei Zeiger.java
- Übersetzen Sie die Datei Zeiger.java
- Testen Sie das Ergebnis mit dem Kommando: java Uhr
- Wiederholen Sie Schritt 3-6 bis Sie das gewünschte Ergebnis haben.
- Implementieren Sie den Minuten und Stundenzeiger sinngemäß.
Beispiele der Ausgangssituation und der korrekten Implementierung:
Ausgangssituation | Ziel der Übung |
---|---|
Tipps
- maxRadius: Diese Konstante der Klasse Zeiger gibt die maximale (vernünftige) Zeigergröße vor.
- Nutzen Sie diesen Wert für einen großen regulären Sekundenzeiger
- Skalieren Sie die Minuten- und Stundenzeiger relativ zu dieser Größe (z. Bsp. maxRadius*4/5 )
- die Mathematikbibliothek wurde statisch importiert. Sie können direkt die benötigen trigonometrischen Operation und Konstanten benutzen:
- Beachten Sie die Eingabe- und Ausgabeparameter der trigonometrischen Funktionen! Die Berechnungen erfolgen mit Fließkommazahlen. Das Ergebnis muss aber eine ganzzahlige Pixelposition sein.
- Ganzzahloperation runden immer ab. Erwägen Sie die Benutzung einer Fließkommahilfsvariable
- Benutzen nur double als Fließkommatyp. Die Operationen der Mathematikbibliothek beruhen auf dem Typ double. Sie vermeiden so unnötige Konvertierungen zu float Typen.
Klasse Uhr
/* * Zeichnen einer analogen Uhr in einem JFrame */ import java.awt.*; import java.awt.event.*; import java.util.Calendar; import javax.swing.*; /** * * @author sschneid */ public class Uhr extends JPanel { static int sekunde = 0; static int minute = 0; static int stunde = 0; static String tzString; // aktuelle Zeitzone static int initialHeight; static float zoom = 1; /** * Hauptprogramm der Anwendung. Es werden keine Eingabeparameter benötigt * @param args dieser Parameter wird nicht ausgewertet */ public static void main(String[] args) { JFrame hf; // Das Fenster der Anwendung hf = new JFrame("Uhr"); // Beenden der Anwendung bei Schliesen des Fenster hf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Uhr dieUhr = new Uhr(); // Aufbau des Contentpanes Container myPane = hf.getContentPane(); myPane.add(dieUhr, BorderLayout.CENTER); // Erzeuge einen Menüeintrag zum Beenden des Programms JMenuBar jmb = new JMenuBar(); JMenu jm = new JMenu("Datei"); JMenuItem exitItem = new JMenuItem("Beenden"); exitItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }); jm.add(exitItem); jmb.add(jm); hf.setJMenuBar(jmb); hf.pack(); // Das JFrame sichtbar machen // Gewünschte Größe setzen // 1. Parameter: horizontale Größe in Pixel // 2. Parameter: vertikale Größe in Pixel hf.setSize((int)(2 * Zeiger.maxRadius*zoom + 80), (int)(2 * Zeiger.maxRadius*zoom + 80)); hf.setVisible(true); hf.setAlwaysOnTop(true); // Initialgröße merken. Entspricht Zoomfaktor 1 dieUhr.initialHeight = dieUhr.getHeight(); // Update von Panel in zyklischen Intervallen try { while (true) { Thread.sleep(500); // Schlafe x Millisekunden // Hole Systemzeit und belege statische Variablen Calendar call = Calendar.getInstance(); tzString = call.getTimeZone().getDisplayName(); sekunde = call.get(Calendar.SECOND); minute = call.get(Calendar.MINUTE); stunde = call.get(Calendar.HOUR); dieUhr.repaint(); } } catch (InterruptedException e) { System.out.println( "Die Anwendung wird wegen einer Ausnahme beendet"); } } /** * Überladene Paintmethode. Sie führt alle Zeichenoperationen im Panel aus * @param g vom Laufzeitsystem übergebenes Graphikobjekt. */ @Override public void paint(Graphics g) { super.paint(g); zoom = (float)getHeight()/(float)initialHeight; int maxRadius = Zeiger.maxRadius; int xCenter = (int)(maxRadius*zoom) + 40; int yCenter = (int)(maxRadius*zoom) + 20; float fontSize = g.getFont().getSize2D(); int charCenterOffSet = (int)(fontSize/2); String timeString = stunde + ":" + minute + ":" + sekunde + " " + tzString; // Zeichne Uhrenhintergrung und Koordinatensystem g.setFont(g.getFont().deriveFont(fontSize)); g.setColor(Color.WHITE); // Farbe g.fillArc((int)(xCenter - maxRadius*zoom), (int)(yCenter - maxRadius*zoom), (int)(maxRadius*zoom*2), (int)(maxRadius*zoom*2), 0, 360); g.setColor(Color.BLACK); // Farbe g.fillArc((int)(xCenter - 3*zoom), (int)(yCenter - 3*zoom), (int)(10*zoom), (int)(10*zoom), 0, 360); g.drawLine(xCenter, yCenter, (int)(xCenter + 40*zoom), yCenter); g.drawLine(xCenter, yCenter, xCenter, (int)(yCenter + 40*zoom)); g.drawString("X", (int)(xCenter + 45*zoom), yCenter + +charCenterOffSet); g.drawString("Y", xCenter - charCenterOffSet, (int)(yCenter + 55*zoom)); g.drawString("12",xCenter - charCenterOffSet, (int)(yCenter - maxRadius*zoom)); g.drawString("3", (int)(xCenter + maxRadius*zoom), yCenter + charCenterOffSet); g.drawString("6", xCenter - charCenterOffSet, (int)(yCenter + 2*charCenterOffSet+maxRadius*zoom)); g.drawString("9", (int)(xCenter - maxRadius*zoom - charCenterOffSet), yCenter + charCenterOffSet); // Zeichne aktuelle Zeit zum Debuggen g.drawString(timeString, 0, (int)(yCenter + maxRadius*zoom)); // Zeichne Stundenzeiger g.setColor(Color.BLACK); g.drawLine(xCenter, yCenter, (int)(xCenter + Zeiger.stundeX(stunde)*zoom), (int)(yCenter + Zeiger.stundeY(stunde)*zoom)); g.drawString("h[" + Zeiger.stundeX(stunde) + "," + Zeiger.stundeY(stunde) + "]", 0, (int)(yCenter + maxRadius*zoom - (3*fontSize))); // Zeichne Minutenzeiger g.setColor(Color.RED); g.drawLine(xCenter, yCenter, (int)(xCenter + Zeiger.minuteX(minute)*zoom), (int)(yCenter + Zeiger.minuteY(minute)*zoom)); g.drawString("m[" + Zeiger.minuteX(minute) + "," + Zeiger.minuteY(minute) + "]", 0, (int)(yCenter + maxRadius*zoom - (2*fontSize))); // Zeichne Sekundenzeiger g.setColor(Color.BLUE); g.drawLine(xCenter, yCenter, (int)(xCenter + Zeiger.sekundeX(sekunde)*zoom), (int)(yCenter + Zeiger.sekundeY(sekunde)*zoom-fontSize)); g.drawString("s[" + Zeiger.sekundeX(sekunde) + "," + Zeiger.sekundeY(sekunde) + "]", 0, (int)(yCenter + maxRadius*zoom - fontSize)); } }
Klasse Zeiger
Implementieren sie
import static java.lang.Math.*; /** * * @author sschneid */ public class Zeiger { public static final int maxRadius = 100; // Beeinflusst GUI-Größe ! /** * @param s Sekunden der aktuellen Zeit. Ein Wert zwischen 0 und 59 * @return aktuelle X Koordinate der Zeigerspitze des Sekundenzeigers * auf dem Bildschirm */ public static int sekundeX(int s) { int xs; /* Implementierung Beginn */ xs = s; // Proformazuweisung. Sie ist zu ersetzen /* Implementierung Ende */ return xs; } /** * @param s Sekunden der aktuellen Zeit. Ein Wert zwischen 0 und 59 * @return aktuelle Y Koordinate der Zeigerspitze des Sekundenzeigers * auf dem Bildschirm */ public static int sekundeY(int s) { int ys; /* Implementierung Beginn */ ys = s; // Proformazuweisung. Sie ist zu ersetzen /* Implementierung Ende */ return ys; } /** * @param m Minuten der aktuellen Zeit. Ein Wert zwischen 0 und 59 * @return aktuelle X Koordinate der Zeigerspitze des Minutenzeigers * auf dem Bildschirm */ public static int minuteX(int m) { int xm; /* Implementierung Beginn */ xm = m; // Proformazuweisung. Sie ist zu ersetzen /* Implementierung Ende */ return xm; } /** * @param m Minuten der aktuellen Zeit. Ein Wert zwischen 0 und 59 * @return aktuelle Y Koordinate der Zeigerspitze des Minutenzeigers * auf dem Bildschirm */ public static int minuteY(int m) { int ym; /* Implementierung Beginn */ ym = m; // Proformazuweisung. Sie ist zu ersetzen /* Implementierung Ende */ return ym; } /** * @param h Stunden der aktuellen Zeit. Ein Wert zwischen 0 und 12 * @return aktuelle X Koordinate der Zeigerspitze des Stundenzeigers * auf dem Bildschirm */ public static int stundeX(int h) { int xh; /* Implementierung Beginn */ xh = h; // Proformazuweisung. Sie ist zu ersetzen /* Implementierung Ende */ return xh; } /** * @param h Stunden der aktuellen Zeit. Ein Wert zwischen 0 und 12 * @return aktuelle Y Koordinate der Zeigerspitze des Stundenzeigers * auf dem Bildschirm */ public static int stundeY(int h) { int yh; /* Implementierung Beginn */ yh = h; // Proformazuweisung. Sie ist zu ersetzen /* Implementierung Ende */ return yh; } }
Hilfestellung
Hier nicht weiterlesen, wenn Sie einfache trigonometrische Aufgaben lösen können!
max-Zeit ist bei Sekunden 60, bei Minuten 60, bei Stunden 12
Die X-Koordinate eines Zeigers berechnet sich wie folgt
x-Koordinate: Sinus(aktuelle-Zeit/max-Zeit*2*PI)*zeiger-länge-in-pixel
Die Y-Koordinate eines Zeigers berechnet sich wie folgt
Y-Koordinate: -Cosinus(aktuelle-Zeit/max-Zeit*2*PI)*zeiger-länge-in-pixel
Beachten Sie, dass in Java das Kommutativgesetz nicht vollständig gilt. Der Typ und die Auswertereihenfolge spielen auch eine Rolle!
2.4.12 Gruppenübung
Je eine Gruppe bearbeitet die folgenden Typen:
- short
- char
- int
- long
- float
- double
Jede Gruppe trägt die folgenden Aspekte eines Typs in 5 Minuten vor
- Schlüsselwort des Typ
- Anzahl der verwendeten Bits
- Wertebreich
- Grenzen mit Konstanten dazu
- Echte Obermengen oder Untermengen der anderen Typen nennen
- Beispiel für die Benutzung dieses Types. Das Beispiel sollte nicht optimal für die anderen Typen sein!
- Syntax der Literale um Werte zuzuweisen
- Programmierbeispiele
- Syntax der Literale benutzen und vorstellen
- Typische Operation und Zuweisung
- mehrere interessante Operationen und Zuweisungen die zu Sonderfällen bzw. Extremfällen führen
Zeitvorgaben
- Selbst lesen: 5 Minuten
- Teamdiskussion: 10 Minuten
- Beispiel Programmieren: 20 Minuten
- Zusammenfassung, Abstimmung Vortrag: 5 Minuten
2.4.13 Airline
Vorbereitung
- Legen Sie ein neues Paker Block2 an
- Nutzen Sie die neue Klasse Flughafen
- Kopieren Sie die Klasse Flugzeug aus dem Block1 in den Block2
Aufgabe:
- Legen Sie in der Klasse Flugzeug die folgenden Attribute als öffentliche (public) Attribute an. Wählen Sie einen passenden Typen
- passagiere
- besatzung
- treibstoff
- leergewicht
- maxGewicht
- Legen Sie zwei statische Variablen an in der Form
- static final int durchschnittsGewicht= 75;
- static final double kerosinGweicht= 0.796; // kg/dm3
- Kopieren der Methoden (siehe unten) in die Klasse Flugzeug
- gewicht()
- toString()
- drucken()
- Implementieren der Methode gewicht()
- Deklarieren Sie eine Variable
- berechnen Sie das aktuelle Gesamtgewicht
- geben Sie diese Variable zurück. Ersetzen Sie die 0 in return durch Ihre Variable
- Erweitern Sie die Klasse Flughafen
- Nutzen Sie das Objekt auf das lh1 zeigt.
- Belegen Sie alle Attribute mit vernünftigen Werten
- Rufen Sie die Methode drucken() für lh1 auf.
- Kontrollieren Sie die Werte
- Testen Sie das Programm in der Klasse Flugzeug
- In der Klasse Flugzeug
- Entnehmen Sie dem Treibstofflager des Flughafen 2000 Liter Treibstoff und füllen Sie Ihn in das Flugzeug lh1
Klasse Flugzeug
Im block2 anlegen!
package Airline.block2;
/**
*
* @author stsch
*/
public class Flugzeug {
String kennzeichen;
/**
*
* @return aktuelles Gewicht;
*/
public double gewicht() {
// Berechnen Sie das aktuelle Gewicht:
// 1. Anlegen einer Variablen
// 2. Berechnen des Gewichts
// 3. Variable in return zurückgeben
return 0;
}
public String toString() {return kennzeichen;}
public void drucken() {
System.out.println("Objekt: " + this);
System.out.println("kennzeichen: " + kennzeichen);
System.out.println("passagiere: " + passagiere);
System.out.println("Besatzung: " + besatzung);
System.out.println("Treibstoff: " + treibstoff);
System.out.println("Leergewicht: " + leergewicht);
System.out.println("maxGewicht: " + maxGewicht);
System.out.println("aktuelles Gewicht: " + gewicht());
}
}
Klasse Flughafen
package Airline.block2;
package Airline.block2;
/**
*
* @author stsch
*/
public class Flughafen {
String name;
Flugzeug gate1;
Flugzeug gate2;
Flugzeug gate3;
Flugzeug gate4;
Flugzeug gate5;
Flugzeug gate6;
double treibstoffLager;
public static void main(String[] args) {
Flughafen pad = new Flughafen();
pad.name = "Paderborn";
pad.treibstoffLager = 1000000;
// Boeing 747, https://de.wikipedia.org/wiki/Boeing_747#747-400
Flugzeug lh1 = new Flugzeug();
lh1.kennzeichen ="D-ABTL";
pad.gate1 = lh1;
System.out.println("*** Unser Flughafen ***");
System.out.println("Flughafen " + pad.name);
System.out.println("Am Gate 1: " + pad.gate1);
System.out.println("Am Gate 2: " + pad.gate2);
System.out.println("Am Gate 3: " + pad.gate3);
System.out.println("Treibstoff: " + pad.treibstoffLager);
System.out.println("***********************");
pad.gate1=null;
pad.gate2=lh1;
System.out.println("*** Unser Flughafen ***");
System.out.println("Flughafen " + pad.name);
System.out.println("Am Gate 1: " + pad.gate1);
System.out.println("Am Gate 2: " + pad.gate2);
System.out.println("Am Gate 3: " + pad.gate3);
System.out.println("Treibstoff: " + pad.treibstoffLager);
System.out.println("***********************");
}
}
- 21081 views
2.5 Lösungen
2.5 Lösungen2.5.1 Zuweisungen und Typen
class ArithmeticTest { public static void main (String args[]) { short x = 6; int y = 4; float a = 12.5f; float b = 7f; System.out.println("x is " + x + ", y is " + y); System.out.println("x + y = " + (x + y)); System.out.println("x - y = " + (x - y)); /* ??? */ System.out.println("x % y = " + (x % y)); System.out.println("a is " + a + ", b is " + b); /* ??? */ } }
2.5.2 Erlaubte Variablennamen
siehe Spezifikation Java 7 (Identifier)
Lösung durch Testen mit javac
public class VariableNames { int maxvalue; int maxValue; int max_value; //int max value; int end; int End; //int 10%ofSum; int sum10; int _10PercentOfSum; public static void main(String[] args) { } }
Erklärung
- maxvalue: korrekter Name
- maxValue: korrekter Name
- max_value: korrekter Name
- max value: Leerstelle im Namen ist nicht erlaubt
- end: korrekter Name
- End: korrekter Name
- 10%ofSum: Ziffer als erstes Zeichen ist nicht erlaubt
- sum10: korrekter Name
- _10PercentOfSum: korrekter Name
2.5.3 Literale
Das Programm übersetzt nicht weil
- der Wert 4000000000 ein "Integer"-Literal ist
- der Wert 4000000000 den Wertebereich einer Ganzzahl vom Typ "Integer" übersteigt
- Die Zuweisung auf eine Variable vom Typ "Long" spielt zu diesem Zeitpunkt noch keine Rolle
2.5.4 Ausdrücke
public class Expressions { public static void main(String[] args) { long a = 3; int b = 4; short c = 5; byte d = 6; int result1; long result2; result2 = d / b * a; System.out.println("d / b * a = " + result2 ); result1 = c + b * (d + 1); System.out.println("c + b * (d + 1) = " + result1 ); result1 = d / (c - 1) * b / 2; System.out.println("d / (c - 1) * b / 2 = " + result1 ); result1 = d % b; System.out.println("d % b = " + result1 ); result1 = -c % b; System.out.println("-c % b = " + result1 ); } }
Ergebnis
d / b * a = 3 c + b * (d + 1) = 33 d / (c - 1) * b / 2 = 2 d % b = 2 -c % b = -1
2.5.5 Zuweisungen
public class AllowedAssigments { public static void main(String[] args) { long a = 3; int b = 4; short c = 5; byte d = 6; a = b + 3 * (d + 1); b = c * c; c = (byte)(b / 3); d = (byte)(((byte)a + b)); d = (byte) ( a + b); } }
2.5.6 Ausdrücke
public class Runden { public static void main(String[] args) { int a, result; a =149; result = (a +50)/100*100; System.out.println("Eingabe = " + a + " Ergebnis = " + result); a =150; result = (a +50)/100*100; System.out.println("Eingabe = " + a + " Ergebnis = " + result); } }
Ergebnis
Eingabe = 149 Ergebnis = 100 Eingabe = 150 Ergebnis = 200
2.5.7 Zeitrechnung
public class timeCalculation { public static void main(String[] args) { int a,h,m,s; a = 0; h = a/3600; m = (a-h*3600)/60; s = a - h*3600 - m*60; System.out.println("Sekunden = " + a + " = " + h + ":" + m + ":" +s); a = 59; h = a/3600; m = (a-h*3600)/60; s = a - h*3600 - m*60; System.out.println("Sekunden = " + a + " = " + h + ":" + m + ":" +s); a = 60; h = a/3600; m = (a-h*3600)/60; s = a - h*3600 - m*60; System.out.println("Sekunden = " + a + " = " + h + ":" + m + ":" +s); a = 100; h = a/3600; m = (a-h*3600)/60; s = a - h*3600 - m*60; System.out.println("Sekunden = " + a + " = " + h + ":" + m + ":" +s); a = 3600; h = a/3600; m = (a-h*3600)/60; s = a - h*3600 - m*60; System.out.println("Sekunden = " + a + " = " + h + ":" + m + ":" +s); a = 4000; h = a/3600; m = (a-h*3600)/60; s = a - h*3600 - m*60; System.out.println("Sekunden = " + a + " = " + h + ":" + m + ":" +s); } }
Ergebnis
Sekunden = 0 = 0:0:0 Sekunden = 59 = 0:0:59 Sekunden = 60 = 0:1:0 Sekunden = 100 = 0:1:40 Sekunden = 3600 = 1:0:0 Sekunden = 4000 = 1:6:40
2.5.8 Polynomberechnung
public class Polynom { public static void main(String[] args) { double a, b, c, d, x, y; a = 1.2; b = -2.3; c = 4.5; d = -6.7; x = 8.9; y = a*x*x*x+b*x*x+c*x+d; System.out.print("Ergebnis = "+ y); System.out.println("\n oder..."); y = a*Math.pow(x,3)+b*Math.pow(x,2)+c*x+d; System.out.print("Ergebnis = "+ y); } }
Ergebnis
Ergebnis = 697.1298 oder... Ergebnis = 697.1297999999999
2.5.9 Abstand zwischen Punkten
public class Main { public static void main(String[] args) { double x1,x2, y1, y2, x, y, d; x1 = 1; y1 = 1; x2 = 4; y2 = 5; x = x1-x2; y = y1-y2; d = Math.sqrt(x*x+y*y); System.out.println("distance = " + d); } }
Ergebnis
distance = 5.0
2.5.10 Berechnung von ∏ (Pi)
Hilfe; Java Spezifikation: Division
public class PiCalculation { public static void main(String[] args) { double pi; pi = (1.0 - 1.0/3.0 + 1.0/5.0 - 1.0/7.0 + 1.0/9.0 - 1.0/11.0 + 1.0/13.0)*4; System.out.println("Pi = "+ pi); System.out.println("\n oder ..."); pi=1; for (int i=1;i<=10000;i++) { pi = pi + Math.pow(-1,i)/(2*i+1); } pi=pi*4; System.out.println("Pi = "+ pi); }
Ergebnis
Pi = 3.2837384837384844 oder ... Pi = 3.1416926435905346
2.5.11 Analoge Uhr
import static java.lang.Math.*; /** * * @author stsch */ public class Zeiger { public static final int maxRadius = 100; // Beeinflusst GUI-Größe ! /** * @param s Sekunden der aktuellen Zeit. Ein Wert zwischen 0 und 59 * @return aktuelle X Koordinate der Zeigerspitze des Sekundenzeigers * auf dem Bildschirm */ public static int sekundeX(int s) { int xs; /* Implementierung Beginn */ double sx = sin(s*2*PI/60)*maxRadius; xs = (int)sx; /* Implementierung Ende */ return xs; } /** * @param s Sekunden der aktuellen Zeit. Ein Wert zwischen 0 und 59 * @return aktuelle Y Koordinate der Zeigerspitze des Sekundenzeigers * auf dem Bildschirm */ public static int sekundeY(int s) { int ys; /* Implementierung Beginn */ double sy = -cos(s*2*PI/60)*maxRadius; ys = (int)sy; /* Implementierung Ende */ return ys; } /** * @param m Minuten der aktuellen Zeit. Ein Wert zwischen 0 und 59 * @return aktuelle X Koordinate der Zeigerspitze des Minutenzeigers * auf dem Bildschirm */ public static int minuteX(int m) { int xm; /* Implementierung Beginn */ double mx = sin(m*2*PI/60)*maxRadius*0.75; xm = (int)mx; /* Implementierung Ende */ return xm; } /** * @param m Minuten der aktuellen Zeit. Ein Wert zwischen 0 und 59 * @return aktuelle Y Koordinate der Zeigerspitze des Minutenzeigers * auf dem Bildschirm */ public static int minuteY(int m) { int ym; /* Implementierung Beginn */ double my = -cos(m*2*PI/60)*maxRadius*0.75; ym = (int) my; /* Implementierung Ende */ return ym; } /** * @param h Stunden der aktuellen Zeit. Ein Wert zwischen 0 und 12 * @return aktuelle X Koordinate der Zeigerspitze des Stundenzeigers * auf dem Bildschirm */ public static int stundeX(int h) { int xh; /* Implementierung Beginn */ double hx = sin(h*2*PI/12)*maxRadius*0.5; xh = (int)hx; /* Implementierung Ende */ return xh; } /** * @param h Stunden der aktuellen Zeit. Ein Wert zwischen 0 und 12 * @return aktuelle Y Koordinate der Zeigerspitze des Stundenzeigers * auf dem Bildschirm */ public static int stundeY(int h) { int yh; /* Implementierung Beginn */ double hy = -cos(h*2*PI/12)*maxRadius*0.5; yh = (int)hy; /* Implementierung Ende */ return yh; } }
2.5.13 Airlines
Klasse Flughafen
package Airline.Block2;/**
*
* @author stsch
*/
public class Flughafen {
String name;
Flugzeug gate1;
Flugzeug gate2;
Flugzeug gate3;
Flugzeug gate4;
Flugzeug gate5;
Flugzeug gate6;
double treibstoffLager;
public static void main(String[] args) {
Flughafen pad = new Flughafen();
pad.name = "Paderborn";
pad.treibstoffLager = 1000000;
// Boeing 747, https://de.wikipedia.org/wiki/Boeing_747#747-400
Flugzeug lh1 = new Flugzeug();
lh1.kennzeichen ="D-ABTL";
pad.gate1 = lh1;
System.out.println("*** Unser Flughafen ***");
System.out.println("Flughafen " + pad.name);
System.out.println("Am Gate 1: " + pad.gate1);
System.out.println("Am Gate 2: " + pad.gate2);
System.out.println("Am Gate 3: " + pad.gate3);
System.out.println("Treibstoff: " + pad.treibstoffLager);
System.out.println("***********************");
pad.gate1=null;
pad.gate2=lh1;
System.out.println("*** Unser Flughafen ***");
System.out.println("Flughafen " + pad.name);
System.out.println("Am Gate 1: " + pad.gate1);
System.out.println("Am Gate 2: " + pad.gate2);
System.out.println("Am Gate 3: " + pad.gate3);
System.out.println("Treibstoff: " + pad.treibstoffLager);
System.out.println("***********************");
lh1.leergewicht = 184567;
lh1.maxGewicht = 412770;
lh1.passagiere = 200;
lh1.besatzung = 10;
lh1.drucken();
}
}
Klasse Flugzeug
package Airline.Block2;/*
*
* @author stsch
*/
public class Flugzeug {
String kennzeichen;
static final int durchschnittsGewicht= 75;
static final double kerosinGweicht= 0.796; // kg/dm3
public int passagiere;
public int besatzung;
public double treibstoff;
public double leergewicht;
public double maxGewicht;
/**
*
* @return aktuelles Gewicht;
*/
public double gewicht() {
// Berechnen Sie das aktuelle Gewicht:
// 1. Anlegen einer Variablen
// 2. Berechnen des Gewichts
// 3. Variable in return zurückgeben
double meinGewicht = leergewicht + passagiere*durchschnittsgewicht+
besatzung*durchschnittsgewicht+treibstoff*gewichtKerosin;
return meinGewicht;
}
public String toString() {return kennzeichen;}
public void drucken() {
System.out.println("Objekt: " + this);
System.out.println("kennzeichen: " + kennzeichen);
System.out.println("passagiere: " + passagiere);
System.out.println("Besatzung: " + besatzung);
System.out.println("Treibstoff: " + treibstoff);
System.out.println("Leergewicht: " + leergewicht);
System.out.println("maxGewicht: " + maxGewicht);
System.out.println("aktuelles Gewicht: " + gewicht());
}
}
- 10469 views
2.6 Webcast: Java Variablen, Zuweisungen und Operatoren
2.6 Webcast: Java Variablen, Zuweisungen und OperatorenEin graphisch animierter Webcast der die genauen Vorgänge des folgenden Beispielprogramms erläutert:
public class Mitarbeiter { ... public static void main (String[] args) { int a; long b; String eingabe; eingabe = args[0]; a = 15; a++; b = 2*a; System.out.println("Ausgabe :" + eingabe + b); } }
Das folgende Video dauert 8 Minuten.
Wichtige Aspekte:
- genaue Lebensdauer von Variablen
- genaues Vorgehen bei einem Cast
- Verwalten von temporären Datenstrukturen
- 5955 views
Klassenattribute
Sind mitarbeiterID und name nicht Objektattribute? Klassenattribute werden doch normalerweise mit static implementiert?
- Log in to post comments
2.7 Fragen
2.7 Fragen
|
2.7.1 GanzzahlarithmetikGanzzahloperationen haben eine Reihe von Eigenheiten. Es wird auf eine Variable a eine Variable b zugewiesen die um 25% größer sein soll. Hierfür gibt es drei Möglichkeiten. Im ersten Fall sei a klein (=6). Welches ist die beste Implementierung? Welche Operationen sind heikel? |
Implementierung | Ergebnis | |
---|---|---|
. |
int a = 0; int b = 6; a = b*5/4; a = b/4*5; a = b*(5/4); |
Was ist die beste Implementierung wenn man weiß das b groß ist? Z.Bsp. b= 230? Welche Operation ist heikel?
2.7.2 Sichere Zuweisungen
Welche der folgenden Zuweisungen sind sicher b.z.w unsicher?
Eine Zuweisung sei unsicher wenn bei der Zuweisung abhängig von der gewählten Variablenbelegung Datenverluster auftreten können.
Analysieren Sie die sechs Zuweisungen auf potentielle Datenverluste. Die Werte von a_short, b_int, c_long wurden absichtlich am oberen Ende des jeweiligen Wertebereichs gewählt um den Präzisionsverlust zu provozieren.
Hinweis: Vergleichen Sie die Wertebereiche der Ausgangs und Zielvariablen.
Ignorieren Sie die Auswertelogik. Das Programm ist ausführbar. Es wird die Belegungen der einzelnen Variablen auf der Konsole drucken. Es wird bei jedem Fall von Präzisionsverlust einen Text "(Fehler)" hinter die Ausgabe anfügen.
public class UebungTypkonversion {
public static void main(String[] args) {
// Alle Werte sind der drittgrößte Wert des jeweiligen Wertebereichs
short a_short = Short.MAX_VALUE-2; // short = 16 bit
int b_int = Integer.MAX_VALUE-2; // int = 32 bit
long c_long = Long.MAX_VALUE-2; // long = 64 bit
// cast auf float: Welche Zuweisungen können zu Präzisionsverlusten führen?
float c_float = a_short;
float d_float = b_int;
float e_float = c_long;
// cast auf double:Welche Zuweisungen können zu Präzisionsverlusten führen?
double f_double = a_short;
double g_double = b_int;
double h_double = c_long;
// Auswertelogik und Kontrolle
System.out.println("a_short=" + a_short);
System.out.println("a_int=" + b_int);
System.out.println("a_long=" + c_long);
System.out.print("short auf float= " + c_float + " ");
// Sind die Werte nach der Rückkonvertierung noch gleich?
if (a_short == (short)c_float) {System.out.println("(OK)");}
else {System.out.println("(Fehler)");}
System.out.print("int auf float= " + d_float);
if (b_int == (int)d_float) {System.out.println("(OK)");}
else {System.out.println("(Fehler)");}
System.out.print("long auf float= " + e_float);
if (c_long == (long)e_float) {System.out.println("(OK)");}
else { System.out.println("(Fehler)");}
System.out.print("short auf double= " + f_double + " ");
if (a_short == (short)f_double) {System.out.println("(OK)");}
else {System.out.println("(Fehler)");}
System.out.print("int auf double= " + g_double);
if (b_int == (int)g_double) {System.out.println("(OK)");}
else {System.out.println("(Fehler)");}
System.out.print("long auf double= " + h_double);
if (c_long == (long)e_float) {System.out.println("(OK)");}
else { System.out.println("(Fehler)");}
}
}
- 6332 views
2.8 Antworten
2.8 Antworten2.8.1 Ganzzahlarithmetik
Bei Ganzzahldivisionen werden alle Ergebnisse abgerundet.
Option a.) ist hier die optimale Lösung da der Rundungsfehler relativ gesehen am kleinsten ist wenn man zuerst multipliziert um dann eine möglichst große Zahl zu teilen.
Option c.) ist schlecht, da da 5/4 schon innerhalb der Klammer auf 1 abgerundet wird.
Option b.) ist ebenfalls schlecht da 6/4 ebenfalls auf 1 abgerundet wird
Implementierung | Ergebnis | |
---|---|---|
. |
int a = 0; int b = 6; a = b*5/4; a = b/4*5; a = b*(5/4); |
. . a=7 a=5 a=6 |
Die Variable b ist sehr groß b= 230:
- Option b.) ist vorteilhaft.
- Hier wird die Multiplikation zum Risiko. Der maximale 32 Bit Ganzzahlwert (231-1) kann bei Option a.) und b.) überschritten werden. Der Überlauf wird vom Laufzeitsystem nicht gemeldet und das Ergebnis ist falsch da negativ. Ein Überlauf des Wertebereichs durch die Mutiplkation ist wahrscheinlich schlimmer als ein Rundungsfehler durch eine frühe Division.
2.8.2 Sichere Zuweisungen
Konsolenausgaben:
a_short=32765
a_int=2147483645
a_long=9223372036854775805
short auf float= 32765.0 (OK)
int auf float= 2.14748365E9(Fehler)
long auf float= 9.223372E18(Fehler)
short auf double= 32765.0 (OK)
int auf double= 2.147483645E9(OK)
long auf double= 9.223372036854776E18(Fehler)
Die Mantisse des Typ float ist nicht groß genug um extrem große (oder kleine) Werte des Typs int und long präzise zu verwalten.
Die Mantisse des Typ double ist nicht groß genug, um extrem große (oder kleine) Werte des Typs long präzise zu verwalten.
- 4294 views
2.9 Lernziele
2.9 Lernziele
Am Ende dieses Blocks können Sie:
|
Lernzielkontrolle
Sie sind in der Lage die folgenden Fragen zu Typen, Operationen und Zuweisungen zu beantworten.
Interessante Fragen aus den Übungen:
- Frage zur Ganzzahlarithmetik beantworten
- Fragen aus den Übungen beantworten:
- 2.4.2 Erlaubte Variablenamen
- 2.4.3 Übung Literale
- 2.4.4 Ausdrücke
- 2.4.5 Zuweisungen
- 2.4.6 Java-Ganzzahlarithmetik zum Runden benutzen
Feedback
- 5156 views
Unterschiede zwischen Ganzzahl- und Fließkommaarithmetik
Ganzzahlarithmetik:
- extrem schnell
- präzise bei Addition, Subtraktion, Multiplikation solange das Ergebnis im Wertebereich bleibt
- keine Fehlermeldungen beim Überschreiten des Wertebereichs
- Javaausnahme nur bei der Division durch Null.
Fließkommanarithmetik
- schnell auf modernen 64 Bitprozessoren
- Alle Operationen sind mehr oder weniger ungenau. Dies hängt von der Größe der Mantisse und des Exponenten ab.
- Besondere Zustände wie "Infinity" oder "Not a number"
- Javaausnahmen beim Überschreiten der Wertbereiche.
- Log in to post comments