Εισαγωγή στον Προγ/μό Υπολογιστών Διδάσκων: Μιχάλης Τίτσιας
Οι τιμές και οι τύποι τους Μπορούμε να έχουμε εκφράσεις με τιμές από διαφορετικούς τύπους; Π.χ., 100*3L Απάντηση: Ναι, πριν υπολογιστεί η τιμή της έκφρασης, οι τύποι όλων των τελεστέων αυτόματα μετατρέπονται στον «μεγαλύτερο» τύπο που συμμετέχει στην έκφραση. Κατόπιν υπολογίζεται η τιμή της έκφρασης Δηλαδή 100*3L → 100L*3L → 300L
Μετατροπές short s = 39; int x; x = s; // ok s = x; s = (short) x; // ok // Μπορεί να χαθεί πληροφορία s short 39 x int 39 Επιτρέπονται: char ↔ short → int → long → float → double
Τι θα συμβεί αν βγάλουμε τα breaks; short s = 39; int x; x = s; // ok s = x; s = (short) x; // ok // Μπορεί να χαθεί πληροφορία public void run() { println(This program shows the number of days in a month."); int month = readInt("Enter numeric month (Jan=1): "); switch (month) { case 2: println("28 days (29 in leap years)"); break; case 4: case 6: case 9: case 12: println("30 days"); case 1: case 3: case 5: case 7: case 8: case 11: println("31 days"); default: println("Illegal month number"); } s short 39 x int 39 Επιτρέπονται: char ↔ short → int → long → float → double
Τι θα συμβεί στον παρακάτω κώδικα; short s = 39; int x; x = s; // ok s = x; s = (short) x; // ok // Μπορεί να χαθεί πληροφορία for( ; ;) ; println(“hello”); s short 39 x int 39 Επιτρέπονται: char ↔ short → int → long → float → double
Η διαδικασία κλήσης των μεθόδων Όταν καλείτε μια μέθοδο, θα συμβούν οι ακόλουθες ενέργειες: Η Java αξιολογεί τα ορίσματα στο πλαίσιο της μεθόδου κλήσης. 1. Η Java στη συνέχεια αντιγράφει κάθε τιμή ορίσματος σε μια αντίστοιχη μεταβλητή, η οποία δημιουργείται σε μια νέα περιοχή μνήμης που ονομάζεται πλαίσιο στοίβας. Η ανάθεση ακολουθεί τη σειρά με την οποία εμφανίζονται τα ορίσματα: το πρώτο όρισμα αντιγράφεται στην πρώτη μεταβλητή κτλ. 2. Στη συνέχεια αξιολογούνται οι δηλώσεις στο σώμα της μεθόδου, χρησιμοποιώντας το νέο πλαίσιο στοίβας για τις τιμές των τοπικών μεταβλητών. 3. Όταν Java συναντά ένα return, υπολογίζει την τιμή επιστροφής και τα αντικαθιστά στην κλήση με αυτήν. 4. Στη συνέχεια απορρίπτει το πλαίσιο στοίβας για την μέθοδο και επιστρέφει στον καλούντα, συνεχίζοντας από εκεί που σταμάτησε. 5.
Αναφορές σε αντικείμενα Εσωτερικά, η Java προσδιορίζει ένα αντικείμενο από τη διεύθυνσή του στη μνήμη. Αυτή η διεύθυνση ονομάζεται αναφορά Rational r1 = new Rational(1, 2); heap 2 den 1 num 1008 1004 1000 διαθέτει χώρο στον σωρό (heap) για ένα νέο αντικείμενο Rational. Για παράδειγμα, θεωρείστε ότι το αντικείμενο έχει δημιουργηθεί στη διεύθυνση 1000. Π.χ. όταν Java αξιολογεί τη δήλωση stack 1000 r1 FFFC Η τοπική μεταβλητή r1 κατανέμεται στο τρέχον πλαίσιο στοίβας (stack) και της αποδίδεται η τιμή 1000, που προσδιορίζει το αντικείμενο.
Παράδειγμα «κοινοκτημοσύνης» των αντικειμένων public void run() { Counter c1 = new Counter(10); Counter c2 = new Counter(); println(c1.value); println(c2.value); c2 = c1; c1.increase(); } Τι θα τυπώσει η println(c2.value);
Κληρονομικότητα και προσπέλαση Όταν δημιουργούμε μια υποκλάση που επεκτείνει μια υπάρχουσα υπερ-τάξη, τότε όλες οι μέθοδοι και τα δεδομένα της υπέρ-τάξης (μεταβλητές και σταθερές) κληρονομούνται στην υποκλάση. Ωστόσο το παραπάνω δεν σημαίνει ότι αντικείμενα της υπο-τάξης έχουν αυτομάτως πρόσβαση σε όλες τις μεθόδους και δεδομένα της υπέρ-τάξης. Αυτό εξαρτάται από το πώς έχει οριστεί η προσπέλαση (public, private κτλ). Για παράδειγμα αν στην υπέρ-τάξη υπάρχουν οι δηλώσεις μεταβλητών στιγμιοτύπου private int x; private int y; τότε αντικείμενα μιας υπό-τάξης δεν έχουν άμεση πρόσβαση στις τιμές αυτές. Πχ αν a είναι ένα αντικείμενο της υπό-τάξης τότε οι εντολές int n1= a.x*5; ή a.x++ θα οδηγούσαν σε σφάλμα κατά την μεταγλώττιση. Προκειμένου αντικείμενα της υπό-τάξης να αποκτήσουν πρόσβαση στις παραπάνω τιμές είτε θα αλλάξουμε τους ορισμούς στην υπέρ-τάξης ώστε protected int x; protected int y; το οποίο ενδεχομένως να μην είναι και τόσο καλή λύση (από την σκοπιά της αντικειμεστρεφούς σχεδίασης). Είτε θα ορίσουμε ειδικές μεθόδους στην υπέρ-τάξη της μορφής getValue και setValue με τις οποίες θα έχουμε (έμμεση) πρόσβαση στις τιμές x,y.
Αριθμητική χαρακτήρων Το γεγονός ότι οι χαρακτήρες έχουν παραστάσεις ως ακέραιοι επιτρέπει την χρήση τους σε αριθμητικές εκφράσεις. Π.χ η έκφραση 'A' + 1, όπου η Java θα μετατρέψει το χαρακτήρα 'A' στον ακέραιο 65, θα προσθέσει 1 για να λάβει 66, που είναι ο κωδικός του χαρακτήρα 'B'. Για παράδειγμα, η ακόλουθη μέθοδος επιστρέφει ένα τυχαία επιλεγμένο κεφαλαίο γράμμα: public char randomLetter() { return (char) rgen.nextInt('A', 'Z'); } Ο παρακάτω κώδικας υλοποιεί την μέθοδο isDigit της τάξης Character: public boolean isDigit(char ch) { return (ch >= '0' && ch <= '9'); }
Έλεγχος Συμβολοσειρών για Ισότητα Πολλές εφαρμογές απαιτούν να ελέγξετε αν δύο συμβολοσειρές είναι ίσες, με την έννοια ότι περιέχουν τους ίδιους χαρακτήρες. Αν και μοιάζει λογικό, δεν μπορείτε να χρησιμοποιήσετε το == για το σκοπό αυτό. Ενώ είναι συντακτικά ορθό να γράψετε if (s1 == s2) . . . το if δεν θα έχει το επιθυμητό αποτέλεσμα. Όταν χρησιμοποιείτε το == σε δύο αντικείμενα, αυτό ελέγχει αν τα αντικείμενα είναι όμοια, πράγμα που σημαίνει ότι οι αναφορές τους δείχνουν την ίδια διεύθυνση. Αυτό που πρέπει να κάνετε αντ 'αυτού είναι να καλέσετε τη μέθοδο : if (s1.equals(s2)) . . .
Εσωτερική Αναπαράσταση Πινάκων Οι πίνακες στην Java υλοποιούνται ως αντικείμενα, πράγμα που σημαίνει ότι αποθηκεύονται στο σωρό. Η τιμή που είναι αποθηκευμένη σε μια μεταβλητή πίνακα είναι απλώς μια αναφορά στον πραγματικό πίνακα. double[] scores = new double[5]; Σκεφτείτε, για παράδειγμα, την ακόλουθη δήλωση: stack 1000 scores FFFC H μεταβλητή scores αποθηκεύεται στη στοίβα και της ανατίθεται η διεύθυνση ενός νέου πίνακα στο σωρό: heap 5 length 1004 0.0 scores[0] 1008 scores[1] 1010 scores[2] 1018 scores[3] 1020 scores[4] 1028
Περνώντας πίνακες ως παραμέτρους Όταν περνάτε ένα πίνακα ως παράμετρο σε μια μέθοδο μόνο η αναφορά περνά ως όρισμα. Αυτό έχει ως αποτέλεσμα τα στοιχεία του πίνακα να διαμοιράζονται μεταξύ του καλούντος και του καλούμενου. Αν μια μέθοδος αλλάζει ένα στοιχείο ενός πίνακα, η αλλαγή θα παραμείνει και μετά τον τερματισμό της.