This shows you the differences between two versions of the page.
Both sides previous revision Previous revision | |||
java:objects [2017/03/01 15:31] gthanos |
java:objects [2018/02/16 16:03] (current) gthanos |
||
---|---|---|---|
Line 2: | Line 2: | ||
Μέχρι τώρα αναφέραμε στην [[ oop:introduction | "Εισαγωγή στον Αντικειμενοστραφή Προγραμματισμό" ]] ότι η κλάση είναι το βασικό σχέδιο μέσα από το οποίο δημιουργούνται επιμέρους αντικείμενα που φέρουν τα χαρακτηριστικά της κλάσης. Επίσης, δείξαμε πως ορίζουμε μία κλάση μέσα από παραδείγματα, αλλά δεν δείξαμε πως δημιουργούμε αντικείμενα από τις κλάσεις που ορίσαμε. | Μέχρι τώρα αναφέραμε στην [[ oop:introduction | "Εισαγωγή στον Αντικειμενοστραφή Προγραμματισμό" ]] ότι η κλάση είναι το βασικό σχέδιο μέσα από το οποίο δημιουργούνται επιμέρους αντικείμενα που φέρουν τα χαρακτηριστικά της κλάσης. Επίσης, δείξαμε πως ορίζουμε μία κλάση μέσα από παραδείγματα, αλλά δεν δείξαμε πως δημιουργούμε αντικείμενα από τις κλάσεις που ορίσαμε. | ||
+ | |||
+ | Η δημιουργία αντικειμένων γίνεται με χρήση του τελεστή **new**. Για παράδειγμα, για να δημιουργήσουμε ένα αντικείμενο της κλάσης **Point** αρκεί να γράψουμε | ||
+ | |||
+ | <code java> | ||
+ | /* δημιουργεί ένα αντικείμενο τύπου Point | ||
+ | * με συντεταγμένες 3,5 και το αναθέτει στη | ||
+ | * μεταβλητή p που είναι τύπου Point. | ||
+ | */ | ||
+ | Point p; // (a) | ||
+ | p = new Point(3,5); // (b) | ||
+ | </code> | ||
+ | |||
+ | Μπορείτε να σκεφτείτε τη μεταβλητή **p** ως ένα δείκτη σε αντικείμενα τύπου **Point**. Αρχικά ο δείκτης είναι μη αρχικοποιημένος δείχνοντας στην τιμή **null**. Στην επόμενη γραμμή καλείται ο κατασκευαστής ο οποίος δημιουργεί ένα αντικείμενο τύπου **Point** με συντεταγμένες 3,5 και αναθέτει το αντικείμενο αυτό στη μεταβλητή **p**. Τα παρακάτω σχήματα απεικονίζουν εποπτικά την διαδικασία. | ||
+ | |||
+ | {{ java:createobject.png }} | ||
+ | |||
+ | |||
+ | ===== Ένα πιο εκτεταμένο παράδειγμα ===== | ||
Παρακάτω δίνεται η κλάση **CreateObjectDemo** που δημιουργεί συγκεκριμένα αντικείμενα του τύπου **Point** και **Rectangle** και εκτυπώνει τα αποτελέσματα στην κονσόλα. Οι κλάσεις **Point** και **Rectangle** δίνονται επίσης παρακάτω: | Παρακάτω δίνεται η κλάση **CreateObjectDemo** που δημιουργεί συγκεκριμένα αντικείμενα του τύπου **Point** και **Rectangle** και εκτυπώνει τα αποτελέσματα στην κονσόλα. Οι κλάσεις **Point** και **Rectangle** δίνονται επίσης παρακάτω: | ||
Line 48: | Line 66: | ||
} | } | ||
| | ||
- | public Rectangle(int initWidth, int initHeight) { | + | public Rectangle(int initWidth, int initHeight, int originX, int originY) { |
width = initWidth; | width = initWidth; | ||
height = initHeight; | height = initHeight; | ||
- | origin = null; | + | origin = new Point(originX,originY); |
} | } | ||
| | ||
Line 84: | Line 102: | ||
// Move rectangle origin by dx,dy | // Move rectangle origin by dx,dy | ||
- | public void move(int dx, int dy) { | + | public void moveOrigin(int dx, int dy) { |
origin.setX( origin.getX() + dx ); | origin.setX( origin.getX() + dx ); | ||
origin.setY( origin.getY() + dy ); | origin.setY( origin.getY() + dy ); | ||
Line 94: | Line 112: | ||
public class CreateObjectDemo { | public class CreateObjectDemo { | ||
- | public static void main(String[] args) { | + | public static void main(String[] args) { |
- | + | | |
- | // Declare and create a point object and two rectangle objects. | + | // Declare variables |
- | Point originOne = new Point(23, 94); | + | Point originOne, originTwo; |
- | Rectangle rectOne = new Rectangle(100, 200, originOne); | + | Rectangle rectOne, rectTwo; |
- | Rectangle rectTwo = new Rectangle(50, 100); | + | // Create objects |
- | + | originOne = new Point(23, 94); | |
- | // display rectOne's width, height, and area | + | originTwo = new Point(15, -33); |
- | System.out.println("Width of rectOne: " + rectOne.getWidth() ); | + | rectOne = new Rectangle(100, 200, originOne); |
- | System.out.println("Height of rectOne: " + rectOne.getHeight() ); | + | rectTwo = new Rectangle(50, 100, originTwo); |
- | System.out.println("Area of rectOne: " + rectOne.getArea()); | + | |
- | + | // display rectOne's width, height, and area | |
- | // set rectTwo's position | + | System.out.println("[rectOne] xPos: " + rectOne.getOrigin().getX() + ", yPos: " + rectOne.getOrigin().getY()); |
- | rectTwo.setOrigin(originOne); | + | System.out.println("[rectOne] width: " + rectOne.getWidth() + ", height: " + rectOne.getHeight()); |
- | + | ||
- | // display rectTwo's position | + | // set rectTwo's position |
- | System.out.println("X Position of rectTwo: " + rectTwo.getOrigin().getX()); | + | rectTwo.setOrigin(originOne); |
- | System.out.println("Y Position of rectTwo: " + rectTwo.getOrigin().getY()); | + | // display rectTwo's position |
- | + | System.out.println("[rectTwo] xPos: " + rectTwo.getOrigin().getX() + ", yPos: " + rectTwo.getOrigin().getY()); | |
- | // move rectTwo and display its new position | + | |
- | rectTwo.move(40, -20); | + | // move rectTwo and display its new position |
- | System.out.println("X Position of rectTwo: " + rectTwo.getOrigin().getX()); | + | rectTwo.moveOrigin(40, -20); |
- | System.out.println("Y Position of rectTwo: " + rectTwo.getOrigin().getY()); | + | System.out.println("[rectTwo] xPos: " + rectTwo.getOrigin().getX() + ", yPos: " + rectTwo.getOrigin().getY()); |
- | } | + | |
+ | // display rectOne's position | ||
+ | System.out.println("[rectOne] xPos: " + rectOne.getOrigin().getX()+", yPos: " + rectOne.getOrigin().getY()); | ||
+ | |||
+ | // assign originOne value to originTwo | ||
+ | originTwo = originOne; | ||
+ | } | ||
} | } | ||
</code> | </code> | ||
- | Για να μεταγλωτίσουμε τα παραπάνω πρόγραμμα αρκεί να γράψουμε | + | Αποθηκεύστε και τα τρία αρχεία στον ίδιο κατάλογο. Για να μεταγλωττίσετε τα παραπάνω πρόγραμμα αρκεί να γράψετε |
<code> | <code> | ||
Line 129: | Line 153: | ||
</code> | </code> | ||
- | και για να το τρέξουμε γράφουμε | + | Για να το τρέξετε γράφετε |
<code> | <code> | ||
Line 138: | Line 162: | ||
<code> | <code> | ||
- | Width of rectOne: 100 | + | [rectOne] xPos: 23, yPos: 94 |
- | Height of rectOne: 200 | + | [rectOne] width: 100, height: 200 |
- | Area of rectOne: 20000 | + | [rectTwo] xPos: 23, yPos: 94 |
- | X Position of rectTwo: 23 | + | [rectTwo] xPos: 63, yPos: 74 |
- | Y Position of rectTwo: 94 | + | [rectOne] xPos: 63, yPos: 74 |
- | X Position of rectTwo: 63 | + | |
- | Y Position of rectTwo: 74 | + | |
</code> | </code> | ||
- | Από τα παραπάνω αξίζει να προσέξουμε τα εξής. | + | ==== Επεξήγηση του παραπάνω κώδικα ===== |
- | - Εκτελούμε την κλάση η οποία περιέχει την μέθοδο **main** η οποία εκκινεί την εκτέλεση του προγράμματος <code>public static void main(String[] args) { .... } </code> | + | |
- | - Η κλάση Rectangle έχει δύο κατασκευαστές οι οποίοι καλούνται εναλλάξ στη συνάρτηση **main** προκειμένου να αρχικοποιήσουν τα αντικείμενα (**objects**) ''rectOne'' και ''rectTwo''. | + | |
- | - Κάθε κατασκευαστής φροντίζει να αρχικοποιεί όλα τα πεδία, ακόμη και αυτά για τα οποία δεν υπάρχει αντίστοιχη παράμετρος. | + | |
- | - H συνάρτηση ''System.out.println()'' εκτυπώνει ένα αλφαριθμητικό (string) ακολουθούμενο από χαρακτήρα αλλαγής γραμμής. | + | |
- | ===== Δήλωση Reference μεταβλητών και δημιουργία αντικειμένων ====== | + | Στο παραπάνω πρόγραμμα ορίζονται στη μέθοδο ''main'' τα εξής |
- | + | ||
- | Στο παραπάνω πρόγραμμα ορίζονται στη συνάρτηση ''main'' τα εξής | + | |
<code java> | <code java> | ||
- | Point originOne = new Point(23, 94); | + | // Declare variables |
- | Rectangle rectOne = new Rectangle(100, 200, originOne); | + | Point originOne, originTwo; |
- | Rectangle rectTwo = new Rectangle(50, 100); | + | Rectangle rectOne, rectTwo; |
+ | // Create objects | ||
+ | originOne = new Point(23, 94); | ||
+ | originTwo = new Point(15, -33); | ||
+ | rectOne = new Rectangle(100, 200, originOne); | ||
+ | rectTwo = new Rectangle(50, 100, originTwo); | ||
</code> | </code> | ||
- | Τα παραπάνω μπορούν να γραφούν αναλυτικότερα ως εξής. | + | Οι πρώτες δύο γραμμές ορίζουν τις μεταβλητές ''originOne'', ''originTwo'',''rectOne'' και ''rectTwo''. Οι μεταβλητές δυνητικά δείχνουν σε τύπους δεδομένων **Point** και **Rectangle**. Προς το παρόν όμως το περιεχόμενο των μεταβλητών αυτών είναι απροσδιόριστο (στην πραγματικότητα ο compiler αρχικοποιεί τις μεταβλητές αυτές στην τιμή **null**). |
- | <code java> | + | |
- | Point originOne; | + | |
- | Rectangle rectOne, rectTwo; | + | |
- | originOne = new Point(23, 94); | + | <WRAP tip 80% center round> |
- | rectOne = new Rectangle(100, 200, originOne); | + | __Σε αναλογία με την γλώσσα C__, φανταστείτε τις μεταβλητές αυτές ως pointers που δεν είναι αρχικοποιημένοι σε κάποια υφιστάμενη διεύθυνση μνήμης. Η τιμή τους είναι απροσδιόριστη και η προσπάθεια να γράψουμε στη διεύθυνση μνήμης όπου δείχνουν θα προκαλέσει τερματισμό του προγράμματος από το λειτουργικό σύστημα. |
- | rectTwo = new Rectangle(50, 100); | + | </WRAP> |
- | </code> | + | |
- | Οι πρώτες δύο γραμμές ορίζουν τις μεταλητές ''originOne'', ''rectOne'', ''rectTwo''. Οι μεταβλητές δυνητικά δείχνουν σε τύπους δεδομένων Point, Rectangle, Rectangle. Προς το παρόν όμως το περιεχόμενο των μεταβλητών αυτών είναι απροσδιόριστο (στην πραγματικότητα ο compiler αρχικοποεί τις μεταβλητές αυτές στην τιμή **null**). | + | Η παρακάτω εικόνα δείχνει την ύπαρξη των τεσσάρων μη αρχικοποιημένων δεικτών. Όλοι αρχικά δείχνουν στην τιμή **null**. |
- | //__Σε αναλογία με την γλώσσα C__, φανταστείτε τις μεταβλητές αυτές ως pointers που δεν είναι αρχικοποιημένοι σε κάποια υφιστάμενη διεύθυνση μνήμης. Η τιμή τους είναι απροσδιόριστη και η προσπάθεια να γράψουμε στη διεύθυνση μνήμης όπου δείχνουν θα προκαλέσει Segmentation Fault.// | + | {{:java:createobjectdemoreference1.png|}} |
- | Η παρακάτω εικόνα δείχνει την ύπαρξη ενός μη αρχικοποιημένου δείκτη. | + | Αμέσως μετά τις δηλώσεις των μεταβλητών ακολουθούν οι κλήσεις των κατασκευαστών των αντίστοιχων κλάσεων. Όπως προαναφέραμε, ο κατασκευαστής όταν καλείται δεσμεύει την απαραίτητη μνήμη για το αντικείμενο, αρχικοποιεί τα πεδία του αντικειμένου και επιστρέφει μία αναφορά προς το αντικείμενο που δημιούργησε. |
- | {{ :java:reference-variables-01.png |}} | + | Η παρακάτω εικόνα δείχνει τις μεταβλητές ''originOne'', ''originTwo'', ''rectOne'', ''rectTwo'' μετά την αρχικοποίηση τους από τους αντίστοιχους κατασκευαστές. |
- | Προκειμένου να αρχικοποιηθούν οι μεταβλητές αυτές απαιτούνται δύο βήματα: | + | {{:java:createobjectdemoreference2.png|}} |
- | - Η δέσμευση της απαραίτητης μνήμης, ώστε να μπορούμε να αποθηκεύσουμε τα δεδομένα που προδιαγράφονται από τον συγκεκριμένο τύπο (κλάση). | + | |
- | - Η αρχικοποίηση των επιμέρους μεταβλητών των αντικειμένων που ορίζονται απο την εκάστοτε κλάση. | + | |
- | Η παρακάτω εικόνα δείχνει τον δείκτη μετά την δέσμευση της απαιτούμενης μνήμης και την αρχικοποίηση των δεδομένων (μεταβλητών) του αντικειμένου ''originOne''. | + | Στη συνέχεια ακολουθούν οι εξής γραμμές κώδικα: |
- | {{ :java:reference-variables-02.png ?400 |}} | + | <code java> |
+ | // set rectTwo's position | ||
+ | rectTwo.setOrigin(originOne); | ||
+ | // display rectTwo's position | ||
+ | System.out.println("[rectTwo] xPos: " + rectTwo.getOrigin().getX() + ", yPos: " + rectTwo.getOrigin().getY()); | ||
+ | |||
+ | // move rectTwo and display its new position | ||
+ | rectTwo.moveOrigin(40, -20); | ||
+ | System.out.println("[rectTwo] xPos: " + rectTwo.getOrigin().getX() + ", yPos: " + rectTwo.getOrigin().getY()); | ||
+ | |||
+ | // display rectOne's position | ||
+ | System.out.println("[rectOne] xPos: " + rectOne.getOrigin().getX()+", yPos: " + rectOne.getOrigin().getY()); | ||
+ | </code> | ||
- | Ο παρακάτω κώδικας | + | Στις γραμμές αυτές συμβαίνουν τα εξής: |
+ | - Το αντικείμενο ''rectTwo'' επιλέγει ως πεδίο origin to ''originOne''. Στη συνέχεια, μέσω του ''rectTwo'' μεταβάλλονται οι συντεταγμένες του αντικειμένου ''originOne''. | ||
+ | - Εκτυπώνονται οι αλλαγές για το ''rectTwo'' στην κονσόλα. | ||
+ | - Εκτυπώνονται οι αλλαγές για το ''rectOne'' στην κονσόλα. Παρατηρούμε ότι οι συντεταγμένες του πεδίου **origin** άλλαξαν και για το αντικείμενο ''rectOne''. | ||
- | <code java>rectOne = new Rectangle(100, 200, originOne);</code> | + | Tα παρακάτω δύο σχήματα αποτυπώνουν α) την αλλαγή του πεδίου **origin** του ''rectTwo'', ώστε να δείχνει στο αντικείμενο ''rectOne'' και β) την αλλαγή των περιεχομένων του ''originOne'' μέσω του αντικειμένου ''rectTwo''. Οι αλλαγές αυτές επηρεάζουν και το πεδίο **origin** του ''rectOne'' που δείχνει στο κοινό αντικείμενο ''origineOne''. |
- | δηλώνει την δέσμευση μνήμης για ένα αντικείμενο τύπου ''Rectangle'' όπου το σημείο της αρχής του είναι το σημείο ''originOne''. Επίσης ορίζονται οι τιμές των **width** και **height** σε 100 και 200 αντίστοιχα. O παραπάνω ορισμός σημαίνει ένα αρχικοποιημένο αντικείμενο μπορεί να έχει πολλούς δείκτες προς αυτό, όπως δείχνει το παρακάτω σχήμα. | + | Παρατηρείστε ότι πλέον μόνο η μεταβλητή ''originTwo'' δείχνει στο αντικείμενο τύπου **Point** με συντεταγμένες 15, -33. |
- | {{ :java:reference-variables-03.png ?500 | }} | + | | **(a)** | | **(b)** | |
+ | | {{:java:createobjectdemoreference3.png|}} | |{{:java:createobjectdemoreference4.png|}} | | ||
- | ===== Ο τελεστής new ===== | + | Τέλος το πρόγραμμα τελειώνει με την γραμμή κώδικα: |
+ | <code java> | ||
+ | // assign originOne value to originTwo | ||
+ | originTwo = originOne; | ||
+ | </code> | ||
+ | |||
+ | Μετά την γραμμή αυτή η μεταβλητή ''originTwo'' δείχνει στο αντικείμενο που δείχνει και η μεταβλητή ''originOne''. Πλέον δεν υπάρχει καμία μεταβλητή ή αναφορά που να δείχνει στο αντικείμενο τύπου **Point** με συντεταγμένες 15, -33. Το αντικείμενο αυτό θα διαγραφεί αυτόματα από την λειτουργία **[[#garbage_collection|Garbage Collection]]** του JVM. | ||
+ | |||
+ | {{:java:createobjectdemoreference5.png|}} | ||
+ | ===== Επεξήγηση της χρήσης του τελεστή new ===== | ||
Προκειμένου να δημιουργηθούν νέα αντικείμενα χρησιμοποιείται ο τελεστής **new**. O τελεστής **new** χρησιμοποιείται συνήθως με τον κατασκευαστή μίας κλάσης προκειμένου να κάνει τα εξής: | Προκειμένου να δημιουργηθούν νέα αντικείμενα χρησιμοποιείται ο τελεστής **new**. O τελεστής **new** χρησιμοποιείται συνήθως με τον κατασκευαστή μίας κλάσης προκειμένου να κάνει τα εξής: | ||
- Δέσμευση της απαραίτητης μνήμης και δημιουργία του αντικειμένου. Η αρχικά ορισμένη μεταβλητή δείχνει πλέον στην περιοχή μνήμης που έχει δεσμευτεί. | - Δέσμευση της απαραίτητης μνήμης και δημιουργία του αντικειμένου. Η αρχικά ορισμένη μεταβλητή δείχνει πλέον στην περιοχή μνήμης που έχει δεσμευτεί. | ||
- | - Αρχικοποίηση των εσωτερικών μεταβλητών (πεδίων) του αντικειμένου με κλήση του κατάλληλου κατασκευαστή της κλάσης. Εάν δεν έχει οριστεί κατασκευαστής τότε ο τελεστής new καλείται με χρήση του default κατασκευαστή (default constructor) που δεν έχει ορίσματα (π.χ. ''MyObject obj = new MyObject();'', όπου για την κλάση ''MyObject'' δεν έχει οριστεί κανένας κατασκευατής). | + | - Αρχικοποίηση των εσωτερικών μεταβλητών (πεδίων) του αντικειμένου με κλήση του κατάλληλου κατασκευαστή της κλάσης. Εάν δεν έχει οριστεί κατασκευαστής τότε ο τελεστής **new** καλείται με χρήση του default κατασκευαστή (default constructor) που δεν έχει ορίσματα (π.χ. ''MyObject obj = new MyObject();'', όπου για την κλάση ''MyObject'' δεν έχει οριστεί κανένας κατασκευατής). |
<WRAP tip 80% center round> | <WRAP tip 80% center round> | ||
- | Κατά την χρήση **primitive** τύπων δεδομένων (int, float, double) δεν απαιτείται η χρήση του τελεστή **new** διότι η απαραίτητη μνήμη δεσμεύεται στο stack της μεθόδου που εκτελείται. | + | Κατά την χρήση **primitive** τύπων δεδομένων σε ένα πρόγραμμα (int, float, double) δεν απαιτείται η χρήση του τελεστή **new**. Ο λόγος που συμβαίνει αυτό είναι ότι για τους συγκεκριμένους τύπους δεδομένων, η διαδικασία δέσμευσης της μνήμης είναι στατική, καθώς είναι γνωστό εκ των προτέρων το εύρος μνήμης που απαιτούν. Οι **primitive** τύποι δεδομένων αποθηκεύονται πάντοτε στο **stack** της μεθόδου μέσα στην οποία δηλώνονται. |
+ | |||
+ | Αντίθετα, για τα αντικείμενα των κλάσεων ο compiler δεν μπορεί να γνωρίζει εκ των προτέρων το μέγεθος τους, καθώς με την σειρά τους αυτά μπορεί να περιέχουν άλλα αντικείμενα, τα οποία με την σειρά τους μπορεί να περιέχουν άλλα αντικείμενα κ.ο.κ. Για τον λόγο αυτό, για τα αντικείμενα δεσμεύεται πάντοτε η απαραίτητη μνήμη δυναμικά, στην περιοχή δυναμικής δέσμευσης μνήμης που παραδοσιακά ονομάζεται **heap**. | ||
</WRAP> | </WRAP> | ||
===== Πολλαπλοί κατασκευαστές σε μία κλάση ===== | ===== Πολλαπλοί κατασκευαστές σε μία κλάση ===== | ||
- | Μία κλάση μπορεί να έχει πολλούς διαφορετικούς κατασκευαστές. Κάθε κατασκευαστής ορίζει μία διαφορετική αρχικοποίηση των εσωτερικών μεταβλητών των αντικειμένων που δημιουργούνται με βάση το "σχέδιο" της κλάσης. Το ποιός κατασκευαστής θα κληθεί εξαρτάται από τον τύπο, τη σειρά και τον αριθμό των ορισμάτων σε αναλογία με την υπερφόρτωση μεθόδων. Έτσι στη συνάρτηση **main** του παραδείγματος μας καλούνται δύο διαφορετικοί κατασκευαστές για δύο διαφορετικά αντικείμενα της ίδιας κλάσης. | + | Μία κλάση μπορεί να έχει πολλούς διαφορετικούς κατασκευαστές. Κάθε κατασκευαστής ορίζει μία διαφορετική αρχικοποίηση των εσωτερικών μεταβλητών των αντικειμένων που δημιουργούνται με βάση το "σχέδιο" της κλάσης. Το ποιoς κατασκευαστής θα κληθεί εξαρτάται από τον τύπο, τη σειρά και τον αριθμό των ορισμάτων σε αναλογία με την υπερφόρτωση μεθόδων. Ας υποθέσουμε την παρακάτω μέθοδο **main**, στην οποία καλούνται δύο διαφορετικοί κατασκευαστές για δύο διαφορετικά αντικείμενα της ίδιας κλάσης **Rectangle**. Παρατηρήστε ότι η μεταβλητή **rectOne** αρχικοποιείται από την 1ο κατασκευαστή της κλάσης και η μεταβλητή **rectTwo** από τον 2ο κατασκευαστή. |
<code java> | <code java> | ||
- | rectOne = new Rectangle(100, 200, originOne); | + | public class CreateRectangleObjects { |
- | rectTwo = new Rectangle(50, 100); | + | public static void main(String []args) { |
+ | Point originOne = new Point(10,5); | ||
+ | rectOne = new Rectangle(100, 200, originOne); | ||
+ | rectTwo = new Rectangle(50, 100, -40, 80); | ||
+ | } | ||
+ | } | ||
</code> | </code> | ||
+ | |||
===== Χρήση Αντικειμένων ===== | ===== Χρήση Αντικειμένων ===== | ||
Line 225: | Line 273: | ||
<code java> | <code java> | ||
// fields are width, height | // fields are width, height | ||
- | Rectangle rect = new Rectangle(10,20); | + | Rectangle rect = new Rectangle(10,20, -5, 22); |
System.out.println("Rectangle dimensions are " + rect.width + ", " + rect.height); | System.out.println("Rectangle dimensions are " + rect.width + ", " + rect.height); | ||
</code> | </code> | ||
<WRAP important 80% center round> | <WRAP important 80% center round> | ||
- | Απαραίτητη προϋπόθεση για να δουλέψει ο παραπάνω κώδικας είναι τα πεδία width και height να είναι προσβάσιμα, δηλαδή να ΜΗΝ έχουν προσδιοριστή πρόσβασης τύπου **private**. | + | Απαραίτητη προϋπόθεση για να δουλέψει ο παραπάνω κώδικας είναι τα πεδία width και height να είναι προσβάσιμα, δηλαδή να μην έχουν προσδιοριστή πρόσβασης τύπου **private**. |
</WRAP> | </WRAP> | ||
Line 239: | Line 287: | ||
==== Χρήση των μεθόδων ενός αντικειμένου ==== | ==== Χρήση των μεθόδων ενός αντικειμένου ==== | ||
- | Σε αναλογία με τα πεδία οι μέθοδοι ενός αντικειμένου είναι προσβάσιμες μέσω του ονόματος του αντικειμένου, μία τελεία '.' και το όνομα του πεδίου. Για παράδειγμα, | + | Σε αναλογία με τα πεδία οι μέθοδοι ενός αντικειμένου είναι προσβάσιμες μέσω του ονόματος του αντικειμένου, μία τελεία '.' και το όνομα της μεθόδου. Για παράδειγμα, |
<code java> | <code java> | ||
- | // fields are width, height | + | Rectangle rect = new Rectangle(10,20, -5, 22); |
- | Rectangle rect = new Rectangle(10,20); | + | |
System.out.println("Rectangle dimensions are " + rect.getWidth() + ", " + rect.getHeight() ); | System.out.println("Rectangle dimensions are " + rect.getWidth() + ", " + rect.getHeight() ); | ||
</code> | </code> | ||
Line 253: | Line 300: | ||
===== Garbage Collection ===== | ===== Garbage Collection ===== | ||
- | Η γλώσσα **C** που μέχρι τώρα έχετε γνωρίσει αναθέτει την ευθύνη δέσμευσης μνήμης στον προγραμματιστή μέσω των συναρτήσεων **malloc()** και **free()**. Σε αντιδιαστολή, η **JAVA** αφήνει τον προγραμματιστεί να ορίσει όσα αντικείμενα επιθυμεί και δεσμεύει την μνήμη για αυτά μέσω του τελεστή **new**. | + | Οι γλώσσες προγραμματισμού που μέχρι τώρα έχετε γνωρίσει (βλέπε **C**) αναθέτουν την ευθύνη δέσμευσης μνήμης στον προγραμματιστή μέσω των συναρτήσεων **malloc()** και **free()**. Σε αντιδιαστολή, η **JAVA** αφήνει τον προγραμματιστεί να ορίσει όσα αντικείμενα επιθυμεί και δεσμεύει την μνήμη για αυτά μέσω του τελεστή **new**. |
- | Πώς όμως αποδεσμεύεται η μνήμη που δεσμεύτηκε προηγούμενα από το πρόγραμμα μας, αλλά δεν την χρειαζόμαστε πλέον; Αν η μνήμη δεν αποδεσμεύεται και το πρόγραμμα μας τρέξει για αρκετή ώρα δεσμεύοντας διαρκώς μνήμη, τότε είναι σίγουρο ότι θα το τερματίσει το λειτουργικό σύστημα. Η απάντηση, όσον αφορά την αποδέσμευση μνήμης στη Java γίνεται μέσω του μηχανισμού **Garbage Collection** και επεξηγείται εν συντομία παρακάτω. | + | Πώς όμως αποδεσμεύεται η μνήμη που δεσμεύτηκε προηγούμενα από το πρόγραμμα μας, αλλά δεν την χρειαζόμαστε πλέον; Περιοδικά το **JVM** κοιτάει εάν υπάρχει δεσμευμένη μνήμη για αντικείμενα στα οποία δεν υφίστανται πλέον αναφορές/references που δείχνουν σε αυτά. Σε αυτές τις περιπτώσεις, ελευθερώνεται η μνήμη που έχει δεσμευτεί για τα αντικείμενα αυτής της κατηγορίας. Παράλληλα η αποδέσμευση της μνήμης και η διαγραφή των αντικειμένων πιθανόν συνεπάγεται ότι και άλλα αντικείμενα δεν διαθέτουν πια αναφορές προς αυτά κ.ο.κ. Η διαδικασία συνεχίζεται μέχρι να αποδεσμευτεί όλη η δυναμικά δεσμευμένη μνήμη. |
- | Περιοδικά το **JVM** κοιτάει εάν υπάρχει δεσμευμένη μνήμη για αντικείμενα στα οποία δεν υφίστανται πλέον μεταβλητές που δείχνουν σε αυτά, δηλαδή δεν υφίστανται αναφορές (//references//) προς αυτά. Σε αυτές τις περιπτώσεις, ελευθερώνεται η μνήμη που έχει δεσμευτεί για τα αντικείμενα αυτή της κατηγορίας. Παράλληλα η αποδέσμευση της μνήμης και η διαγραφή των αντικειμένων πιθανόν συνεπάγεται ότι και άλλα αντικείμενα δεν διαθέτουν πια αναφορές προς αυτά κ.ο.κ. Η διαδικασία συνεχίζεται μέχρι να αποδεσμευτεί όλη η δυναμικά δεσμευμένη μνήμη. | + | Ο μηχανισμός **Garbage Collection** απαντάται σε αρκετές γλώσσες υψηλού επιπέδου, απελευθερώνοντας τον προγραμματιστή από την ευθύνη αποδέσμευσης της μνήμης που δεσμεύτηκε προηγούμενα. Η ευθύνη της δεύσμευσης/αποδέσμευσης μνήμης δεν επαφίεται στον προγραμματιστή, πράγμα που κάνει λιγότερο επίπονο τον προγραμματισμό. |
- | + | ||
- | Ο μηχανισμός **Garbage Collection** απαντάται σε αρκετές γλώσσες υψηλού επιπέδου, απελευθερώνοντας τον προγραμματιστή από την ευθύνη αποδέσμευσης της μνήμης που δεσμεύτηκε προηγούμενα. Η ευθύνη της αποδέσμευσης μνήμης επαφίεται στο Garbage Collector, πράγμα που κάνει λιγότερο επίπονο τον προγραμματισμό. | + | |
- | + | ||
- | Φυσικά η δυνατότητα του **Garbage Collection** συνεπάγεται ότι ένα παράλληλο νήμα, τρέχει περιοδικά και ελευθερώνει την μνήμη, πράγμα που πιθανόν να εισάγει καθυστερήσεις σε συγκεκριμένες εφαρμογές. Σε προγράμματα που απαιτούν πολύ υψηλές επιδόσεις ή έχουν αυστηρούς περιορισμούς ως προς τον χρόνο εκτέλεσης τους, η παράλληλη εκτέλεση του Garbage Collector μπορεί να εισάγει μη αποδεκτή καθυστέρηση. | + | |
Περισσότερα για την λειτουργία του Garbage Collector και τις εναλλακτικές υλοποιήσεις μπορείτε να βρείτε [[http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html|εδώ]]. | Περισσότερα για την λειτουργία του Garbage Collector και τις εναλλακτικές υλοποιήσεις μπορείτε να βρείτε [[http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html|εδώ]]. | ||
- | |Προηγούμενο: [[:java:class_constructors | Κατασκευαστές της κλάσης ]] | [[:toc | Περιεχόμενα ]] | Επόμενο: [[:java:this_operator | O τελεστής this ]]| | + | |Προηγούμενο: [[:java:class_constructors | Κατασκευαστές της κλάσης ]] | [[:toc | Περιεχόμενα ]] | Επόμενο: [[:java:arrays | Πίνακες |
- | + | ]]| | |
- | + | ||
- | + | ||