Skip to the content.

1.3 Αριθμοί, μεταβλητές, εκφράσεις

© Γιάννης Κωστάρας


<- ->

Σ’ αυτό το μάθημα θα κάνουμε τα πρώτα μας βήματα στη γλώσσα προγραμματισμού Java. Η γλώσσα Java αποτελείται από: λέξεις-κλειδιά (keywords), μεταβλητές (variables ή identifiers), σταθερές (constants ή literals), τελεστές (operators) και σημεία στίξης (punctuators).

Οι λέξεις-κλειδιά (keywords) είναι δεσμευμένες λέξεις που αποτελούν τις εντολές της γλώσσας (π.χ. int, String, for, public, try).

Οι μεταβλητές (variables ή identifiers) είναι, όπως θα δούμε, διευθύνσεις μνήμης για ν’ αποθηκεύουμε δεδομένα ή αποτελέσματα πράξεων.

Οι σταθερές (constants ή literals) είναι επίσης θέσεις μνήμης που αποθηκεύουν δεδομένα που δεν μπορούν να μεταβληθούν κατά την εκτέλεση του προγράμματος.

Οι τελεστές (operators) είναι διάφορες πράξεις που υποστηρίζει η γλώσσα (π.χ. +, %, ++, && <=) και χρησιμοποιούνται σε εκφράσεις.

Τα σημεία στίξης (punctuators) είναι χαρακτήρες που έχουν ειδικό νόημα για τον μεταγλωττιστή (π.χ. ; , . { }).

Σχόλια

Η Java υποστηρίζει τριών ειδών σχόλια.

Σχόλιο μιας γραμμής:

int radius;          // Αυτό είναι ένα σχόλιο μιας γραμμής

Σχόλιο πολλαπλών γραμμών:

/* 
 * Αυτό είναι ένα σχόλιο
 * πολλαπλών γραμμών.
 */
int radius;          

Σχόλιο τεκμηρίωσης (Javadoc):

/** 
 * Αυτό είναι ένα σχόλιο
 * τεκμηρίωσης κώδικα (Javadoc).
 */
int radius;          

Τα σχόλια Javadoc σας επιτρέπουν να τεκμηριώνετε τον κώδικά σας και να παράγετε τη διεπαφή των κλάσεών σας (Application Program Interface - API) σε μορφή HTML. Π.χ. εδώ βλέπετε το API των κλάσεων της Java 10. Θα μάθουμε πώς να γράφουμε τα δικά μας σχόλια Javadoc τη 2η εβδομάδα.

Αριθμοί

Η Java υποστηρίζει τους παρακάτω αριθμητικούς τύπους:

Σημείωση. Στο API της γλώσσας μπορείτε να βρείτε χρήσιμες εντολές όπως π.χ. η Integer.parseInt(String s, int radix) που επιτρέπει τη μετατροπή ενός αριθμού σε μια άλλη βάση (radix, π.χ. δυαδικό σύστημα) στο δεκαδικό σύστημα. Π.χ. Integer.parseInt("0101", 2). Θα μιλήσουμε για Strings στο επόμενο μάθημα. Mελετήστε τις άλλες εντολές (μεθόδους) που παρέχει η κλάση Integer.

Αριθμητικοί τύποι δεδομένων

Οι παρακάτω πίνακες δείχνουν τους αριθμητικούς τύπους δεδομένων που υποστηρίζονται από τη γλώσσα καθώς και το εύρος τιμών καθενός από αυτούς.

Πίνακας 1.3.1 Ακέραιοι τύποι δεδομένων

Τύπος δεδομένων Αποθηκευτικός χώρος Εύρος τιμών Ελάχιστη, Μέγιστη τιμή
byte 1 byte –128 -> 127 (-2^7 to 2^7-1) Byte.MIN_VALUE, Byte.MAX_VALUE
short 2 bytes –32,768 -> 32,767 (-2^15 to 2^15-1) Short.MIN_VALUE, Short.MAX_VALUE
int 4 bytes –2,147,483,648 -> 2,147,483,647(-2^31 to 2^31-1) Integer.MIN_VALUE, Integer.MAX_VALUE
long 8 bytes –9,223,372,036,854,775,808 -> 9,223,372,036,854,775,807 (-2^63 to 2^63-1) Long.MIN_VALUE, Long.MAX_VALUE

Πίνακας 1.3.2 Τύποι δεδομένων κινητής υποδιαστολής σύμφωνα με το πρότυπο ΙΕΕΕ 754

Τύπος δεδομένων Αποθηκευτικός χώρος Εύρος τιμών Ελάχιστη, Μέγιστη τιμή
float 4 bytes -3.40282347E+38 -> -1.4E-45 και 1.4E+45 -> 3.4028235E+38 Float.MIN_VALUE, Float.MAX_VALUE
double 8 bytes -1.7976931348623157E+308 -> -4.9E-324 και 4.9E-324 -> 1.7976931348623157E+308 Double.MIN_VALUE, Double.MAX_VALUE

Σημείωση Υπενθυμίζουμε ότι 1 byte = 8 bits (1 bit είναι ένα δυαδικό ψηφίο, δηλ. 0 ή 1)

Καλό είναι να χρησιμοποιείτε τον κατάλληλο τύπο δεδομένων ανάλογα με τις ανάγκες του προγράμματός σας. Αν χρησιμοποιήσετε τύπο δεδομένων με μεγαλύτερο εύρος τιμών από αυτό που χρειάζεται το πρόγραμμά σας, τότε σπαταλάτε άσκοπα μνήμη. Αν από την άλλη, χρησιμοποιήσετε τύπο δεδομένων με μικρότερο εύρος τιμών απ’ ότι χρειάζεται το πρόγραμμά σας, τότε κινδυνεύετε να έχετε υπερχήλιση (overflow) και τα αποτελέσματα που θα πάρετε να μην είναι σωστά.

Μεγάλη προσοχή επίσης στις πράξεις μεταξύ δεδομένων κινητής υποδιαστολής, όπως βλέπετε στο παρακάτω παράδειγμα:

jshell> 2.0d - 2.01d
$1 ==> -0.009999999999999787

Λόγω του τρόπου αναπαράστασής τους από τους Η/Υ, δεν μπορείτε να βασίζεστε στις πράξεις τέτοιων αριθμών. Η Java παρέχει κάποιες κλάσεις (BigInteger, BigDecimal) γι’ αυτό το σκοπό, όπως θα δούμε σε ακόλουθα μαθήματα. Αν θέλετε να συγκρίνετε δυο αριθμούς τύπου float χρησιμοποιήστε την εντολή Float.compare(float,float) και για τύπου double την Double.compare(double, double) αντίστοιχα.

Προτεραιότητα αριθμητικών πράξεων

Η προτεραιότητα των αριθμητικών πράξεων φαίνεται στον ακόλουθο πίνακα (όσο πιο πάνω τόσο μεγαλύτερη η προτεραιότητα).

Πίνακας 1.3.3 Προτεραιότητα αριθμητικών πράξεων

+ - Πρόσημα
() Παρενθέσεις
* / % *= /= %= Πολλ/σμός, Διαίρεση, Υπόλοιπο διαίρεσης (a / b) * b + r = a, εκχωρήσεις
+ - += -= Πρόσθεση, Αφαίρεση, εκχωρήσεις
< > <= >= == != Μεγαλύτερο, μικρότερο, μεγαλύτερο ίσο, μικρότερο ίσο, ίσο, άνισο

Π.χ. πόσο κάνει η παρακάτω πράξη:

jshell> 5 + 2 * 4

Αν απαντήσατε 28 τότε δε λάβατε υπόψιν σας την προτεραιότητα των τελεστών όπως φαίνεται στον παραπάνω πίνακα. Καθώς ο πολλ/σμός (*) έχει υψηλότερη προτεραιότητα από την πρόσθεση, θα εκτελεστεί πρώτα και μετά η πρόσθεση.

Η σωστή απάντηση είναι 13.

Λογικοί τύποι δεδομένων και λογικές πράξεις

Πίνακας 1.3.4 Λογικός τύπος δεδομένων

Τύπος δεδομένων Αποθηκευτικός χώρος Εύρος τιμών
boolean 1 byte true,false

Πίνακας 1.3.5 Λογικές πράξεις

! Όχι (Not)
&&, || Λογικό ΚΑΙ (And), Ή (Or)
&, | Λογικό ΚΑΙ (And), Ή (Or)

Παρακάτω φαίνονται οι πίνακες αληθείας των πράξεων αυτών (F: Ψευδής, T: Αληθής):

x ~x
F T
T F
x y x && y ή x & y
F F F
F T F
T F F
T T T
x y x || y ή x | y
F F F
F T T
T F T
T T T

Όπως παρατηρείτε, υπάρχουν δυο είδη λογικών τελεστών για το λογικό ΚΑΙ και το λογικό Ή. Η διαφορά τους είναι η εξής:

Αυτό πολλές φορές μπορεί ν’ αποτελέσει πηγές λάθους (bugs). Π.χ. στο παρακάτω παράδειγμα (που χρησιμοποιεί πίνακες ή συστοιχίες για τις οποίες θα μιλήσουμε σε επόμενο μάθημα αυτής της εβδομάδας), ο πίνακας array μπορεί να έχει τιμή null, αλλά επειδή χρησιμοποιείται ο τελεστής & αντί για τον &&, ελέγχονται όλες οι παραμέτροι με αποτέλεσμα π.χ. η array.lenght να επιστρέφει λάθος εκτέλεσης καθώς προσπαθούμε να καλέσουμε τη μέθοδο length στην array που είναι null.

if (array != null & i >= 0 & i < array.length) {
	// ...
} else {
	// ...
}

Δυαδικές πράξεις (προαιρετικό, εκτός ύλης)

Πίνακας 1.3.6 Δυαδικές πράξεις

~ Όχι (Not)
&, |, ^ Λογικό ΚΑΙ (And), Ή (Or), Xor
<<, >>, >>> Αριστερή, δεξιά ολίσθηση (Πολλ/σμός επί, διαίρεση με δύναμη του 2)

Παρακάτω φαίνονται οι πίνακες αληθείας των πράξεων αυτών (F: False, Ψευδής, T: True, Αληθής):

x ~x
F T
T F
x y x & y
F F F
F T F
T F F
T T T
x y x | y
F F F
F T T
T F T
T T T
x y x ^ y
F F F
F T T
T F T
T T F
jshell> int i=0
i ==> 0	// 00000000
jshell> ~i
$6 ==> -1	// 11111111
jshell> (~i)+1	// 100000000  υπερχείλιση (overflow)
$7 ==> 0	// 00000000

Οι τελεστές ολίσθησης ολισθαίνουν κατά ένα ή περισσότερα bits την αναπαράσταση ενός αριθμού αριστερά ή δεξιά. Η διαφορά των δυο δεξιών τελεστών ολίσθησης είναι η εξής:

Η αναπαράσταση των αρνητικών αριθμών στη C/C++ γίνεται απλά αντιστρέφοντας το πιο σημαντικό bit (Most Significant Bit ή MSB) δηλ. το αριστερότερο bit. Στη Java η αναπαριστάση αρνητικών αριθμών ακολουθεί το συμπλήρωμα ως προς 2 (2’s complement). Για να πάρουμε τον αρνητικό αριθμό με συμπλήρωμα του 2 ενός θετικού αριθμού πρέπει να αντιστρέψουμε τα ψηφία του και να προσθέσουμε 1. Π.χ. θεωρώντας 8 bit (1 byte):

00000101 // 5
11111010 +1
11111011 // -5

Η Java χρησιμοποιεί 32 bits για την αναπαράσταση αρνητικών αριθμών με συμπλήρωμα ως προς 2.

Παραδείγματα χρήσης τελεστών ολίσθησης:

0b00000000000000000000000000001011 << 1   -> 0b00000000000000000000000000010110  // 11 << 1  ==> 22  αριστερή ολίσθηση <=> πολλ/σμός επί 2
0b00000000000000000000000000001011 >> 1   -> 0b00000000000000000000000000000101  // 11 >> 1  ==> 5   δεξιά ολίσθηση <=> διαίρεση με 2
0b00000000000000000000000000001011 >>> 1  -> 0b00000000000000000000000000000101  // 11 >> 1  ==> 5   δεξιά ολίσθηση <=> διαίρεση με 2
jshell> 0b00000000000000000000000000001011
$1 ==> 11

jshell> 0b00000000000000000000000000001011 >> 1
$2 ==> 5

jshell> Integer.toBinaryString(0b00000000000000000000000000001011 >> 1)
$3 ==> "101" // "00000000000000000000000000000101"

jshell> 0b00000000000000000000000000001011 >>> 1
$4 ==> 5

jshell> Integer.toBinaryString(0b00000000000000000000000000001011 >>> 1)
$5 ==> "101" // "0000000000000000000000000000101"
0b10000000000000000000000000001011 << 1   -> 0b00000000000000000000000000010110  // -2147483637 << 1   ==> 22   αριστερή ολίσθηση <=> πολλ/σμός επί 2
0b10000000000000000000000000001011 >> 1   -> 0b11000000000000000000000000000101  // -2147483637 >> 1   ==> -1073741819   δεξιά ολίσθηση <=> διαίρεση με 2
0b10000000000000000000000000001011 >>> 1  -> 0b01000000000000000000000000000101  // -2147483637 >>> 1  ==> 1073741829   δεξιά ολίσθηση <=> διαίρεση με 2 αλλά MSB 0 
jshell> 0b10000000000000000000000000001011
$6 ==> -2147483637

jshell> 0b10000000000000000000000000001011 >> 1
$7 ==> -1073741819

jshell> Integer.toBinaryString(0b10000000000000000000000000001011 >> 1)
$8 ==> "11000000000000000000000000000101"

jshell> 0b10000000000000000000000000001011 >>> 1
$9 ==> 1073741829

jshell> Integer.toBinaryString(0b10000000000000000000000000001011 >>> 1)
$10 ==> "1000000000000000000000000000101"
//    ή 01000000000000000000000000000101

Η εφαρμογή των παραπάνω τελεστών σε τύπους char, byte, short τους μετατρέπει αυτόματα σε int προτού εφαρμοστεί ο τελεστής και το αποτέλεσμα είναι int. Μόνο τα 5 χαμηλότερα bits του ορίσματος δεξιά από τον τελεστή χρησιμοποιούνται. Αντίστοιχα, για long, μόνο τα 6 χαμηλότερα bits του ορίσματος δεξιά από τον τελεστή χρησιμοποιούνται (ώστε να μην επιτρέπεται ολίσθηση μεγαλύτερη από τον αριθμό των bits του long).

Εικόνα 1.3.1 Αναπαράσταση αρνητικών αριθμών 16-bit με συμπλήρωμα ως προς 2 (Πανεπιστήμιο του Princeton)

Ας δούμε μερικά παραδείγματα πράξεων δυαδικών αριθμών:

jshell> byte x=0b10
x ==> 2
jshell> Integer.toBinaryString(x<<1)
$1 ==> "100" // 4 = 2*2
jshell> Integer.toBinaryString(x>>1)
$2 ==> "1"   // = 2/2
jshell> byte y=0b11
y ==> 3
jshell> Integer.toBinaryString(x&y) // ΚΑΙ
$3 ==> "10"
jshell> Integer.toBinaryString(x|y) // Ή
$4 ==> "11"
jshell> Integer.toBinaryString(x^y) // XOR
$5 ==> "01"
x 10
y 11
x & y 10
x | y 11
x ^ y 01

Τύπος δεδομένων χαρακτήρας

Πίνακας 1.3.7 Τύπος δεδομένων χαρακτήρας

Τύπος δεδομένων Αποθηκευτικός χώρος Εύρος τιμών Ελάχιστη, Μέγιστη τιμή
char 2 bytes (16-bit Unicode) '\u0000' - '\uffff' Character.MIN_VALUE, Character.MAX_VALUE

Είναι ο μόνος τύπος δεδομένων της γλώσσας που είναι μη προσημασμένος (δηλ. παίρνει μόνο θετικές τιμές).

Πίνακας 1.3.8 Πράξεις

+ char μετατρέπεται σε int
++ προσαύξηση
-- προσαφαίρεση

Οι χαρακτήρες αναπαρίστανται στους Η/Υ ως δυαδικοί αριθμοί. Υπάρχουν διάφορα πρότυπα αναπαράστασης χαρακτήρων στους Η/Υ έτσι ώστε να αναπαρίστανται με τον ίδιο κωδικό. Το πιο γνωστό τέτοιο πρότυπο είναι ο κώδικας ASCII.

jshell> char char1 = 'α'
char1 ==> 'α

jshell> char char2 = 'γ'
char2 ==> 'γ

jshell> char char3 = char1 + char2
|  Error:
|  incompatible types: possible lossy conversion from int to char
|  char char3 = char1 + char2;
|               ^-----------^

jshell> int char3 = char1 + char2
char3 ==> 1892

jshell> int char1 = 'α'	 // κωδικός ASCII
char1 ==> 945

jshell> char char1 = 945  // κωδικός ASCII
char1 ==> 'α'

jshell> ++char1
$1 ==> 'β'

jshell> --char1
$2 ==> 'α'

Μετατροπές τύπων δεδομένων (casting)

Μερικές φορές είναι απαραίτητο να μετατρέψετε μια μεταβλητή ενός τύπου δεδομένων σ’ έναν άλλον, όπως φαίνεται στο ακόλουθο σχήμα:

Εικόνα 1.3.2 Διάγραμμα μετατροπών τύπων δεδομένων

Όταν η μετατροπή γίνεται σε κάποιον τύπο δεδομένων μεγαλύτερης χωρητικότητας (διεύρυνση τύπου δεδομένων), τότε δεν υπάρχει πρόβλημα (έμμεση μετατροπή), όταν όμως γίνεται σε κάποιον τύπο δεδομένων μικρότερης χωρητικότητας (συρρίκνωση), τότε μπορεί να χαθεί ακρίβεια με ίσως τραγικά αποτελέσματα.

Η σύνταξη μετατροπής σε άλλον τύπο δεδομένων (casting) γίνεται ορίζοντας τον νέο τύπο δεδομένων μέσα σε παρενθέσεις μπροστά από το δεδομένο. Στο παρακάτω παράδειγμα βλέπουμε πώς μπορεί να χαθεί ακρίβεια κάνοντας casting ενός ακέραιου αριθμού σε byte (το byte μπορεί να πάρει τιμή μέχρι το 127):

jshell> (byte)260
$1 ==> 4 

(Ο τύπος byte ‘χωράει’ μέχρι το 127 (βλ. πίνακα 1.3.1). Το αποτέλεσμα (υπερχείλισης) υπολογίζεται ως εξής: 260 % 128 = 4).

Ας δούμε άλλο ένα παράδειγμα. Τι επιστρέφει η παρακάτω ακολουθία μετατροπών;

jshell> (int) (char) (byte) -1
$2 ==> 65535

αντί για -1! Η μετατροπή (byte) -1 μετατρέπει τον ακέραιο -1 σε byte (32 bits -> 8 bits). Η 2η μετατροπή μετατρέπει το byte σε char (8 bits -> 16 bits). Η τρίτη μετατρέπει το char σε int (16 bits -> 32 bits). Η μετατροπή int -> byte αφήνει τον -1 αμετάβλητο. Η μετατροπή όμως byte -> char όχι, γιατί ο τύπος δεδομένων char είναι απρόσημος (0 - 2^16-1), με αποτέλεσμα ο -1 να μετατρέπεται στον 2^16-1 ή 65535:

jshell> Integer.toBinaryString(-1)
$3 ==> "11111111111111111111111111111111"

jshell> Integer.toBinaryString((int) (char) (byte) -1)
$4 ==> "1111111111111111"

Μεταβλητές

Τα δεδομένα που χρησιμοποιούμε στα προγράμματά μας αποθηκεύονται στη μνήμη του Η/Υ και καλούνται από την Κ.Μ.Ε. για επεξεργασία. Η μνήμη του υπολογιστή μπορεί να θεωρηθεί ως ένας μεγάλος μονοδιάστατος πίνακας από bytes, όπως φαίνεται στο ακόλουθο σχήμα.

Εικόνα 1.3.3 Αναπαράσταση της κύριας μνήμης του Η/Υ ως μονοδιάστατος πίνακας από bytes

Για πολλούς λόγους (π.χ. ασφάλειας) δεν μπορούμε να έχουμε άμεση πρόσβαση σε μια διεύθυνση μνήμης. Αντιθέτως, πρόσβαση στη μνήμη μας παρέχει η γλώσσα προγραμματισμού μέσω κλήσεων του Λ.Σ. Πώς όμως μπορούμε να προσπελάσουμε τη θέση μνήμης που μας παρείχε το Λ.Σ.; Αυτό γίνεται μέσω των μεταβλητών. Οι μεταβλητές είναι ονόματα που η γλώσσα προγραμματισμού αντιστοιχίζει με τη βοήθεια του Λ.Σ. σε κάποια φυσική διεύθυνση μνήμης.

Το όνομα μιας μεταβλητής μπορεί να περιλαμβάνει λατινικούς χαρακτήρες a..Z, A..Z αριθμούς 0..9, $ και _. Δεν μπορεί να αρχίζει όμως με αριθμητικό ψηφίο ούτε μπορεί να είναι δεσμευμένη λέξη (δηλ. κάποια από τις εντολές) της γλώσσας. Από την έκδοση 9 και μετά το _ είναι δεσμευμένη λέξη της γλώσσας.

Επίσης, ο τύπος δεδομένων που διαλέξαμε για να ορίσουμε μια μεταβλητή λέει στη Java πόσες θέσεις μνήμης να δεσμεύσει γι’ αυτή τη μεταβλητή (ανάλογα με το εύρος τιμών του τύπου δεδομένων). Π.χ. για έναν ακέραιο δεσμεύονται 4 bytes συνεχόμενων θέσεων μνήμης.

Π.χ.

int myVar;    // ορισμός μια νέας μεταβλητής με όνομα myVar τύπου int

Μπορείτε ν’ αρχικοποιήσετε μια μεταβλητή τη στιγμή του ορισμού της:

Τύπος_μεταβλητής όνομα_μεταβλητής = έκφραση

Π.χ.

int x = 3;
int y = 5*x*x-2;        // y=5∙x^2-2 
jshell> /vars

Πίνακας 1.3.10 Προτεραιότητα τελεστών

+ - Πρόσημα
++ -- προσαύξηση, προσαφαίρεση (προθεματικός, επιθεματικός)
(cast) Μετατροπή δεδομένων
! Λογικό ΟΧΙ
() Παρενθέσεις
* / % Πολλ/σμός, Διαίρεση, Υπόλοιπο διαίρεσης (a / b) * b + r = a
+ - Πρόσθεση, Αφαίρεση
< > <= >= == != Μεγαλύτερο, μικρότερο, μεγαλύτερο ίσο, μικρότερο ίσο, ίσο, άνισο
^ && || Λογικοί τελεστές XOR, AND, OR
=, +=, -=, *=, /=, %= Τελεστές εκχώρισης

Πίνακας 1.3.11 Τελεστές εκχώρησης

= += -= *= /= %= ++ -- <<= >>= >>>= &= |= ^=
int x = 3;
int answer = x++ * 10;  // answer = 30, x = 4
x = 3;
answer = ++x * 10;      // answer = 40, x = 4

Η δήλωση var

Όπως είδαμε στο πρώτο μάθημα αυτής της εβδομάδας, η Java είναι μια στατική γλώσσα προγραμματισμού, πράγμα που σημαίνει ότι πρέπει να ορίζουμε εξ’ αρχής τον τύπο δεδομένων μιας μεταβλητής. Από την έκδοση 10 όμως και μετά, η γλώσσα υποστηρίζει την δήλωση var με την οποία μπορούμε να ορίζουμε μεταβλητές χωρίς να δηλώνουμε τον τύπο τους και ο μεταγλωττιστής μπορεί να συνάγει (infer) τον τύπο δεδομένων από την αρχική τιμή τους, π.χ.

jshell> var i = 0;
i ==> 0

jshell> ++i
$1 ==> 1

jshell> var k;
|  Error:
|  cannot infer type for local variable k
|    (cannot use 'var' on variable without initializer)
|  var k;
|  ^----^

Η var μπορεί να συνάγει (infer) μόνο τύπους τοπικών μεταβλητών (local variable type inference), επομένως, εκτός από το παραπάνω, και τα παρακάτω προκαλούν λάθη μεταγλώττισης:

jshell> public class MyClass { 
  var aField = calc(x, y);
  
  int calc (int x, int y) {
	  return x + y;
  }
}
|  Error:
|  'var' is not allowed here
|    var aField = calc(x, y);
|    ^-^

jshell> void aMethod(var v) {}
|  Error:
|  'var' is not allowed here
|  void aMethod(var v) {}
|               ^-^

Σημείωση: Η var είναι ανάλογη της auto της C++11.

Σημείωση: Η var δεν είναι λέξη κλειδί της γλώσσας! Ο μεταγλωττιστής δεν παραπονιέται αν γράψουμε var var = 42;.

Σταθερές

Ενώ οι μεταβλητές μπορούν ν’ αλλάξουν την τιμή τους κατά τη διάρκεια εκτέλεσης του προγράμματος, αυτό δεν μπορεί να γίνει με τις σταθερές. Ορίζετε μια σταθερά με τη λέξη final:

final double PI = 3.14159; 
final int ARRAY_SIZE = 100;
PI = 4;

Ασκήσεις

  1. Να ανταλλάξετε τις τιμές δυο μεταβλητών a και b. Π.χ. αν a = 3 και b = 4 τότε μετά την εκτέλεση του προγράμματός σας a = 4 και b = 3.
  2. Να μετατρέψετε μια θερμοκρασία από βαθμούς Φαρενάιτ σε βαθμούς Κελσίου
  3. Να υπολογίσετε τον ετήσιο φόρο που θα πληρώσει κάποιος που παίρνει μισθό 800 ευρώ το μήνα και η κλίμακα φορολόγησης είναι 50%
  4. Να υπολογίσετε τις ώρες, τα λεπτά και τα δευτερόλεπτα ενός χρόνου που δίνεται σε δευτερόλεπτα. Π.χ. “4700 δευτερόλεπτα είναι 1 ώρα 18 λεπτά και 20 δευτερόλεπτα”.
  5. Να γραφτεί ένα πρόγραμμα το οποίο να υπολογίζει το άθροισμα και τη διαφορά 2 τριψήφιων αριθμών και να εμφανίζει το αποτέλεσμα όπως παρακάτω:
 456      456
+123     -123
----     ---- 
 579      333

6) Να γραφτεί ένα πρόγραμμα που να τυπώνει το εμβαδόν ενός τριγώνου με πλευρές a, b, c. Το εμβαδόν ενός τριγώνου δίνεται από τον τύπο E=√s(s-a)(s-b)(s-c), όπου 2s=a+b+c.

7) (Προαιρετική) Πώς μπορούμε να ελέγξουμε αν ένας αριθμός είναι δύναμη του 2 χρησιμοποιώντας μόνο πράξεις bit;

Πηγές

  1. Kabutz H. (2018). “Java 10: Inferred Local Variables”, JavaSpecialists Newsletter, Issue 255

<- ->