java:objects

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revision Both sides next revision
java:objects [2016/01/22 15:10]
gthanos
java:objects [2017/03/01 15:31]
gthanos
Line 1: Line 1:
-====== Δημιουργώντας Αντικείμενα ======+====== Δημιουργία Αντικειμένων ======
  
 Μέχρι τώρα αναφέραμε στην [[ oop:​introduction | "​Εισαγωγή στον Αντικειμενοστραφή Προγραμματισμό"​ ]] ότι η κλάση είναι το βασικό σχέδιο μέσα από το οποίο δημιουργούνται επιμέρους αντικείμενα που φέρουν τα χαρακτηριστικά της κλάσης. Επίσης,​ δείξαμε πως ορίζουμε μία κλάση μέσα από παραδείγματα,​ αλλά δεν δείξαμε πως δημιουργούμε αντικείμενα από τις κλάσεις που ορίσαμε. ​ Μέχρι τώρα αναφέραμε στην [[ oop:​introduction | "​Εισαγωγή στον Αντικειμενοστραφή Προγραμματισμό"​ ]] ότι η κλάση είναι το βασικό σχέδιο μέσα από το οποίο δημιουργούνται επιμέρους αντικείμενα που φέρουν τα χαρακτηριστικά της κλάσης. Επίσης,​ δείξαμε πως ορίζουμε μία κλάση μέσα από παραδείγματα,​ αλλά δεν δείξαμε πως δημιουργούμε αντικείμενα από τις κλάσεις που ορίσαμε. ​
  
-Παρακάτω δίνεται ​ένα πρόγραμμα ​που δημιουργεί συγκεκριμένα αντικείμενα του τύπου **Point** και **Rectangle** και εκτυπώνει τα αποτελέσματα στην κονσόλα.+Παρακάτω δίνεται ​η κλάση **CreateObjectDemo** ​που δημιουργεί συγκεκριμένα αντικείμενα του τύπου **Point** και **Rectangle** και εκτυπώνει τα αποτελέσματα στην κονσόλα. ​Οι κλάσεις **Point** και **Rectangle** δίνονται επίσης παρακάτω:​
  
 <code java Point.java>​ <code java Point.java>​
Line 36: Line 36:
 public class Rectangle { public class Rectangle {
     ​     ​
-  // the Rectangle class has 3 fields+  // fields
   private int width;   private int width;
   private int height;   private int height;
   private Point origin;   private Point origin;
     ​     ​
-  // the Rectangle class has one constructor +  // constructors 
-  public Rectangle(int ​setWidth, int setHeight, Point o) { +  public Rectangle(int ​initWidth, int initHeight, Point initOrigin) { 
-    width = setWidth+    width = initWidth
-    height = setHeight+    height = initHeight
-    origin = o;+    origin = initOrigin;
   }   }
   ​   ​
-  public Rectangle(int ​setWidth, int setHeight) { +  public Rectangle(int ​initWidth, int initHeight) { 
-    width = setWidth+    width = initWidth
-    height = setHeight;+    height = initHeight;​ 
 +    origin = null;
   }   }
     ​     ​
-  // the Rectangel class has 3 methods+  // methods
   public void setWidth(int newWidth ) {   public void setWidth(int newWidth ) {
     width = newWidth;     width = newWidth;
Line 70: Line 71:
   }   }
     ​     ​
-  public void setOrigin(Point ​o) { +  public void setOrigin(Point ​newOrigin) { 
-    origin = o;+    origin = newOrigin;
   }   }
   ​   ​
Line 82: Line 83:
   }   }
        
-  // Move rectangle origin by x,y+  // Move rectangle origin by dx,dy
   public void move(int dx, int dy) {   public void move(int dx, int dy) {
     origin.setX( origin.getX() + dx );     origin.setX( origin.getX() + dx );
Line 123: Line 124:
  
 <​code>​ <​code>​
-javac Point.java +javac Point.java ​             // μεταγλώττιση της κλάσης Point 
-javac Rectange.java +javac Rectange.java ​          // μεταγλώττιση της κλάσης Rectangle 
-javac CreateObjectDemo.java+javac CreateObjectDemo.java ​  // μεταγλώττιση της κλάσης CreateObjectDemo
 </​code>​ </​code>​
  
Line 146: Line 147:
 </​code>​ </​code>​
  
-Από τα πάραπάνω αξίζει να προσέξουμε τα εξής.+Από τα παραπάνω αξίζει να προσέξουμε τα εξής.
   - Εκτελούμε την κλάση η οποία περιέχει την μέθοδο **main** η οποία εκκινεί την εκτέλεση του προγράμματος <​code>​public static void main(String[] args) { .... } </​code>​   - Εκτελούμε την κλάση η οποία περιέχει την μέθοδο **main** η οποία εκκινεί την εκτέλεση του προγράμματος <​code>​public static void main(String[] args) { .... } </​code>​
   - Η κλάση Rectangle έχει δύο κατασκευαστές οι οποίοι καλούνται εναλλάξ στη συνάρτηση **main** προκειμένου να αρχικοποιήσουν τα αντικείμενα (**objects**) ''​rectOne''​ και ''​rectTwo''​.   - Η κλάση Rectangle έχει δύο κατασκευαστές οι οποίοι καλούνται εναλλάξ στη συνάρτηση **main** προκειμένου να αρχικοποιήσουν τα αντικείμενα (**objects**) ''​rectOne''​ και ''​rectTwo''​.
 +  - Κάθε κατασκευαστής φροντίζει να αρχικοποιεί όλα τα πεδία, ακόμη και αυτά για τα οποία δεν υπάρχει αντίστοιχη παράμετρος.
   - H συνάρτηση ''​System.out.println()''​ εκτυπώνει ένα αλφαριθμητικό (string) ακολουθούμενο από χαρακτήρα αλλαγής γραμμής.   - H συνάρτηση ''​System.out.println()''​ εκτυπώνει ένα αλφαριθμητικό (string) ακολουθούμενο από χαρακτήρα αλλαγής γραμμής.
  
Line 156: Line 158:
 <code java> <code java>
 Point originOne = new Point(23, 94); Point originOne = new Point(23, 94);
-Rectangle rectOne = new Rectangle(originOne, ​100, 200);+Rectangle rectOne = new Rectangle(100,​ 200, originOne);
 Rectangle rectTwo = new Rectangle(50,​ 100); Rectangle rectTwo = new Rectangle(50,​ 100);
 </​code>​ </​code>​
Line 166: Line 168:
  
 originOne = new Point(23, 94); originOne = new Point(23, 94);
-rectOne = new Rectangle(originOne, ​100, 200);+rectOne = new Rectangle(100,​ 200, originOne);
 rectTwo = new Rectangle(50,​ 100); rectTwo = new Rectangle(50,​ 100);
 </​code>​ </​code>​
  
-Οι πρώτες δύο γραμμές ορίζουν τις μεταλητές ''​originOne'',​ ''​rectOne'',​ ''​rectTwo''​. Οι μεταβλητές δυνητικά δείχνουν σε τύπους δεδομένων Point, ​Rectange, Rectangle. Προς το παρόν όμως το περιεχόμενο των μεταβλητών αυτών είναι απροσδιόριστο (undefined). +Οι πρώτες δύο γραμμές ορίζουν τις μεταλητές ''​originOne'',​ ''​rectOne'',​ ''​rectTwo''​. Οι μεταβλητές δυνητικά δείχνουν σε τύπους δεδομένων Point, ​Rectangle, Rectangle. Προς το παρόν όμως το περιεχόμενο των μεταβλητών αυτών είναι απροσδιόριστο (στην πραγματικότητα ο compiler αρχικοποεί τις μεταβλητές αυτές στην τιμή **null**). 
  
-//__Σε αναλογία με την γλώσσα C__, φανταστείτε τις μεταβλητές αυτές ως pointers που δεν είναι αρχικοποιημένοι σε κάποια υφιστάμενη διεύθυνση μνήμης. Η τιμή τους είναι απροσδιόριστη και η προσπάθεια να γράψουμε στη διεύθυνση μνήμης που δείχνουν θα προκαλάσει Segmentation Fault.// ​+//__Σε αναλογία με την γλώσσα C__, φανταστείτε τις μεταβλητές αυτές ως pointers που δεν είναι αρχικοποιημένοι σε κάποια υφιστάμενη διεύθυνση μνήμης. Η τιμή τους είναι απροσδιόριστη και η προσπάθεια να γράψουμε στη διεύθυνση μνήμης ​όπου δείχνουν θα προκαλέσει Segmentation Fault.// ​
  
 Η παρακάτω εικόνα δείχνει την ύπαρξη ενός μη αρχικοποιημένου δείκτη. Η παρακάτω εικόνα δείχνει την ύπαρξη ενός μη αρχικοποιημένου δείκτη.
Line 179: Line 181:
  
 Προκειμένου να αρχικοποιηθούν οι μεταβλητές αυτές απαιτούνται δύο βήματα:​ Προκειμένου να αρχικοποιηθούν οι μεταβλητές αυτές απαιτούνται δύο βήματα:​
-  - Η δέσμευση της απαραίτητης μνήμης,​ ώστε να μπορούμε να αποθηκεύσουμε τα δεδομένα που προδιαγράφονται απο τον συγκεκριμένο τύπο (κλάση).+  - Η δέσμευση της απαραίτητης μνήμης,​ ώστε να μπορούμε να αποθηκεύσουμε τα δεδομένα που προδιαγράφονται από τον συγκεκριμένο τύπο (κλάση).
   - Η αρχικοποίηση των επιμέρους μεταβλητών των αντικειμένων που ορίζονται απο την εκάστοτε κλάση.   - Η αρχικοποίηση των επιμέρους μεταβλητών των αντικειμένων που ορίζονται απο την εκάστοτε κλάση.
  
Line 188: Line 190:
 Ο παρακάτω κώδικας Ο παρακάτω κώδικας
  
-<code java>​rectOne = new Rectangle(originOne, ​100, 200);</​code> ​+<code java>​rectOne = new Rectangle(100,​ 200, originOne);</​code> ​
  
 δηλώνει την δέσμευση μνήμης για ένα αντικείμενο τύπου ''​Rectangle''​ όπου το σημείο της αρχής του είναι το σημείο ''​originOne''​. Επίσης ορίζονται οι τιμές των **width** και **height** σε 100 και 200 αντίστοιχα. O παραπάνω ορισμός σημαίνει ένα αρχικοποιημένο αντικείμενο μπορεί να έχει πολλούς δείκτες προς αυτό, όπως δείχνει το παρακάτω σχήμα. δηλώνει την δέσμευση μνήμης για ένα αντικείμενο τύπου ''​Rectangle''​ όπου το σημείο της αρχής του είναι το σημείο ''​originOne''​. Επίσης ορίζονται οι τιμές των **width** και **height** σε 100 και 200 αντίστοιχα. O παραπάνω ορισμός σημαίνει ένα αρχικοποιημένο αντικείμενο μπορεί να έχει πολλούς δείκτες προς αυτό, όπως δείχνει το παρακάτω σχήμα.
Line 206: Line 208:
 ===== Πολλαπλοί κατασκευαστές σε μία κλάση ===== ===== Πολλαπλοί κατασκευαστές σε μία κλάση =====
  
-Μία κλάση μπορεί να έχει πολλούς διαφορετικούς. Κάθε κατασκευαστής ορίζει μία διαφορετική αρχικοποίηση των εσωτερικών μεταβλητών των αντικειμένων που δημιουργούντια με βάση το "​σχέδιο"​ της κλάσης. Το ποιός κατασκευαστής θα κληθεί εξαρτάται από τον τύπο, τη σειρά και τον αριθμό των ορισμάτων σε αναλογία με την υπερφόρτωση ​συναρτήσεων. Έτσι στη συνάρτηση main του παραδείγματος μας καλούνται δύο διαφορετικοί κατασκευαστές για δύο διαφορετικά αντικείμενα της ίδιας κλάσης.+Μία κλάση μπορεί να έχει πολλούς διαφορετικούς κατασκευαστές. Κάθε κατασκευαστής ορίζει μία διαφορετική αρχικοποίηση των εσωτερικών μεταβλητών των αντικειμένων που δημιουργούνται με βάση το "​σχέδιο"​ της κλάσης. Το ποιός κατασκευαστής θα κληθεί εξαρτάται από τον τύπο, τη σειρά και τον αριθμό των ορισμάτων σε αναλογία με την υπερφόρτωση ​μεθόδων. Έτσι στη συνάρτηση ​**main** του παραδείγματος μας καλούνται δύο διαφορετικοί κατασκευαστές για δύο διαφορετικά αντικείμενα της ίδιας κλάσης.
  
 <code java> <code java>
-rectOne = new Rectangle(originOne, ​100, 200);+rectOne = new Rectangle(100,​ 200, originOne);
 rectTwo = new Rectangle(50,​ 100); rectTwo = new Rectangle(50,​ 100);
 </​code>​ </​code>​
Line 222: Line 224:
  
 <code java> <code java>
-                          ​// cadencespeed, gear +   // fields are widthheight 
-   Bicycle bicycle ​= new Bicycle(10, 20, 30); +   Rectangle rect = new Rectangle(10,20); 
-   ​System.out.println("​Bicycle speed is " + bicycle.speed);+   ​System.out.println("​Rectangle dimensions are " + rect.width + ", ​" + rect.height);
 </​code>​ </​code>​
  
 <WRAP important 80% center round> <WRAP important 80% center round>
-Απαραίτητη προϋπόθεση για να δουλέψει ο παραπάνω κώδικας είναι το πεδίο speed να είναι προσβάσιμο, δηλαδή να μην ​έχει προσδιοριστή τύπου **private**.+Απαραίτητη προϋπόθεση για να δουλέψει ο παραπάνω κώδικας είναι τα πεδία width και height ​να είναι προσβάσιμα, δηλαδή να ΜΗΝ ​έχουν ​προσδιοριστή ​πρόσβασης ​τύπου **private**.
 </​WRAP>​ </​WRAP>​
  
 <WRAP tip 80% center round> <WRAP tip 80% center round>
-Όπως προείπαμε μία καλή προγραμματιστική πρακτική είναι η απόκρυψη των πεδίων κάθε κλάσης και η δήλωση συναρτήσεων για την πρόσβαση στα δεδομένα της. Σε αυτή την περίπτωση η απευθείας πρόσβαση στα πεδία των αντικειμένων είναι μη επιτρεπτή (ο compiler δεν μεταγλωττίζει το πρόγραμμα). Η πρόσβαση σε μεταβλητές που έχουν τον προσδιοριστή **private** μπορεί να γίνει μόνο μέσω βοηθητικών συναρτήσεων (set/get) που έχουν το προσδιοριστή **public**.+Όπως προείπαμε μία καλή προγραμματιστική πρακτική είναι η απόκρυψη των πεδίων κάθε κλάσης και η δήλωση συναρτήσεων για την πρόσβαση στα δεδομένα της. Σε αυτή την περίπτωση η απευθείας πρόσβαση στα πεδία των αντικειμένων είναι μη επιτρεπτή (ο compiler δεν μεταγλωττίζει το πρόγραμμα). Η πρόσβαση σε μεταβλητές που έχουν τον προσδιοριστή **private** μπορεί να γίνει μόνο μέσω βοηθητικών συναρτήσεων (set/get) που έχουν τον προσδιοριστή **public**.
 </​WRAP>​ </​WRAP>​
  
Line 240: Line 242:
  
 <code java> <code java>
-                          ​// cadencespeed, gear +   // fields are widthheight 
-   Bicycle bicycle ​= new Bicycle(10, 20, 30); +   Rectangle rect = new Rectangle(10,20); 
-   ​System.out.println("​Bicycle speed is " + bicycle.getSpeed() );+   ​System.out.println("​Rectangle dimensions are " + rect.getWidth() + ", ​" + rect.getHeight() );
 </​code>​ </​code>​
  
Line 251: Line 253:
 ===== Garbage Collection ===== ===== Garbage Collection =====
  
-Οι γλώσσες υψηλού επιπέδου ​που μέχρι τώρα έχετε γνωρίσει ​(**C**) ​αναθέτουν ​την ευθύνη δέσμευση μνήμης στον προγραμματιστή μέσω των συναρτήσεων **malloc()** και **free()**. Σε αντιδιαστολή,​ η **JAVA** αφήνει τον προγραμματιστεί να ορίσει όσα αντικείμενα επιθυμεί και δεσμεύει την μνήμη για αυτά μέσω του τελεστή **new**.+Η γλώσσα **C** που μέχρι τώρα έχετε γνωρίσει αναθέτει την ευθύνη δέσμευσης μνήμης στον προγραμματιστή μέσω των συναρτήσεων **malloc()** και **free()**. Σε αντιδιαστολή,​ η **JAVA** αφήνει τον προγραμματιστεί να ορίσει όσα αντικείμενα επιθυμεί και δεσμεύει την μνήμη για αυτά μέσω του τελεστή **new**.
  
-Πως όμως αποδεσμεύεται η μνήμη που δεσμεύτηκε προηγούμενα από το πρόγραμμα μας, αλλά δεν την χρειαζόμαστε πλέον; Αν η μνήμη δεν αποδεσμεύεται και το πρόγραμμα μας τρέξει για αρκετή ώρα δεσμεύοντας μνήμη, τότε είναι σίγουρο ότι θα το τερματίσει το λειτουργικό σύστημα. Η απάντηση,​ όσον αφορά την αποδέσμευση μνήμης στη Java δίνεται παρακάτω.+Πώς όμως αποδεσμεύεται η μνήμη που δεσμεύτηκε προηγούμενα από το πρόγραμμα μας, αλλά δεν την χρειαζόμαστε πλέον; Αν η μνήμη δεν αποδεσμεύεται και το πρόγραμμα μας τρέξει για αρκετή ώρα δεσμεύοντας διαρκώς μνήμη, τότε είναι σίγουρο ότι θα το τερματίσει το λειτουργικό σύστημα. Η απάντηση,​ όσον αφορά την αποδέσμευση μνήμης στη Java γίνεται ​μέσω του μηχανισμού **Garbage Collection** και επεξηγείται εν συντομία ​παρακάτω.
  
-Περιοδικά το **JVM** κοιτάει εάν υπάρχει δεσμευμένη μνήμη για αντικείμενα στα οποία δεν υφίστανται πλέον μεταβλητές που δείχνουν σε αυτά. Σε αυτές τις περιπτώσεις,​ ελευθερώνεται η μνήμη που έχει δεσμευτεί για τα αντικείμενα ​που εντόπισε ​το JVMΟ μηχανισμός αυτός ονομάζεται **Garbage Collection** ​και απαντάται ​σε αρκετές γλώσσες υψηλού ​επιπέδου ​απελευθερώνοντας τον προγραμματιστή από την ευθύνη αποδέσμευσης ​της μνήμης που ​δεσμεύτηκε προηγούμενα.+Περιοδικά το **JVM** κοιτάει εάν υπάρχει δεσμευμένη μνήμη για αντικείμενα στα οποία δεν υφίστανται πλέον μεταβλητές που δείχνουν σε αυτά, δηλαδή δεν υφίστανται αναφορές (//​references//​) προς ​αυτά. Σε αυτές τις περιπτώσεις,​ ελευθερώνεται η μνήμη που έχει δεσμευτεί για τα αντικείμενα ​αυτή της κατηγορίαςΠαράλληλα η αποδέσμευση της μνήμης και η διαγραφή των αντικειμένων πιθανόν ​συνεπάγεται ότι και άλλα αντικείμενα δεν διαθέτουν πια αναφορές προς ​αυτά κ.ο.κ. Η διαδικασία συνεχίζεται μέχρι ​να αποδεσμευτεί όλη η δυναμικά ​δεσμευμένη μνήμη
  
-Η ευθύνη της αποδέσμευσης μνήμης επαφίεται στο Garbage Collector, πράγμα που κάνει ​πιο εύκολη τη ζωή ​του προγραμματιστήΑπό την άλλη, σε προγράμματα που απαιτούν πολύ υψηλές επιδόσεις ή έχουν αυστηρούς περιορισμούς ως προς τον χρόνο εκτέλεσης τους, ​ο αλγόριθμος που χρησιμοποιεί ​ο Garbage Collector μπορεί να εισάγει μη αποδεκτή καθυστέρηση.+Ο μηχανισμός **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_methods ​Μέθοδοι ​της ​Κλάσης ]] | Επόμενο:​ [[:​java:​this_operator | O τελεστής this ]]|+|Προηγούμενο:​ [[:java:class_constructors ​Κατασκευαστές της ​κλάσης ​]] |  [[:toc | Περιεχόμενα ​]] | Επόμενο:​ [[:​java:​this_operator | O τελεστής this ]]|
  
  
java/objects.txt · Last modified: 2018/02/16 16:03 by gthanos