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
java:objects [2015/02/05 10:06]
gthanos
java:objects [2018/02/16 16:03]
gthanos
Line 1: Line 1:
-====== Δημιουργώντας Αντικείμενα ======+====== Δημιουργία Αντικειμένων ======
  
 Μέχρι τώρα αναφέραμε στην [[ 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** δίνονται επίσης παρακάτω:​
  
 <code java Point.java>​ <code java Point.java>​
 public class Point { public class Point {
-   ​private int xCoord, yCoord+    private int x; 
-   ​ +    ​private int y
-   ​public Point(int ​x, int y) { +     
-       xCoord = x; +    public Point(int ​xPos, int yPos) { 
-       yCoord = y; +      = xPos
-   ​+      = yPos
-   ​public ​void setX(int x) { +    
-       xCoord = x; +     
-   ​+    ​public ​int getX() { 
-   ​public void setY(int y) { +      ​return ​x; 
-       yCoord ​y+    
-   ​+     
-   ​public int getX() { +    ​public void setX(int xPos) { 
-       ​return ​xCoord+      ​x ​xPos
-   ​+    
-   ​public ​int getY() { +     
-       return yCoord+    ​public int getY() { 
-   ​ +      return ​y
 +    
 +     
 +    ​public ​void setY(int yPos) { 
 +      y = yPos
 +    }
 } }
 </​code>​ </​code>​
Line 30: Line 53:
 <code java Rectangle.java>​ <code java Rectangle.java>​
 public class Rectangle { public class Rectangle {
-   private int widthheight; +     
-   ​private Point origin; +  // fields 
-   ​ +  ​private int width
-   ​public Rectangle(Point p, int w, int h) { +  private int height; 
-       origin ​p+  private Point origin; 
-       width w+     
-       height ​h+  // constructors 
-   ​+  ​public Rectangle(int ​initWidth, int initHeight, Point initOrigin) { 
-   ​ +    ​width ​initWidth
-   ​public Rectangle(int ​w, int h) { +    ​height ​initHeight
-       ​width = w+    ​origin ​initOrigin
-       ​height = h+  
-   ​+   
-   ​ +  public Rectangle(int ​initWidth, int initHeight, int originX, int originY) { 
-   ​public void setOrigin(Point p) { +    width = initWidth
-      ​origin ​p+    height = initHeight
-   ​+    ​origin = new Point(originX,​originY);​ 
-   ​ +  ​
-   ​public ​void setHeight(int h) { +     
-       height = h+  // methods 
-   ​+  ​public void setWidth(int newWidth ​) { 
-   ​ +    ​width ​newWidth
-   ​public void setWidth(int w) { +  
-       width w+   
-   ​+  public int getWidth() { 
-   ​ +    ​return width
-   ​public ​Point getOrigin() { +  
-       ​return ​origin+     
-   ​+  public void setHeight(int newHeight ​) { 
-   ​ +    ​height ​newHeight
-   ​public ​int getHeight() { +  
-       return height+   
-   ​+  public ​int getHeight() { 
-   ​ +    return ​height
-   ​public ​int getWidth() { +  
-       ​return ​width+     
-   ​+  public ​void setOrigin(Point newOrigin) { 
-   ​ +    ​origin = newOrigin
-   ​public int getArea() {+  
 +   
 +  public ​Point getOrigin() { 
 +    return ​origin
 +  
 +   
 +  public int getArea() {
        ​return width * height;        ​return width * height;
-   } +  }
-    +
-   // Move rectangle origin by x,y +
-   ​public void move(int x, int y) { +
-       ​origin.setX( origin.getX() + x ); +
-       ​origin.setY( origin.getY() + y ); +
-   }+
        
 +  // Move rectangle origin by dx,dy
 +  public void moveOrigin(int dx, int dy) {
 +    origin.setX( origin.getX() + dx );
 +    origin.setY( origin.getY() + dy );
 +  }
 } }
 </​code>​ </​code>​
Line 84: 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(originOne, ​100, 200); +    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>​
-Width of rectOne: 100 +javac Point.java ​             // μεταγλώττιση της κλάσης Point 
-Height of rectOne: 200 +javac Rectange.java ​          // μεταγλώττιση της κλάσης Rectangle 
-Area of rectOne: 20000 +javac CreateObjectDemo.java ​  // μεταγλώττιση της κλάσης CreateObjectDemo
-X Position of rectTwo: 23 +
-Y Position of rectTwo: 94 +
-X Position of rectTwo: 63 +
-Y Position of rectTwo: 74+
 </​code>​ </​code>​
  
-Από τα πάραπάνω αξίζει να προσέξουμε ​τα εξής. +Για να το τρέξετε ​γράφετε
-  - Η κλάση Rectangle έχει δύο κατασκευαστές οι οποίοι καλούνται ​εναλλάξ στη συνάρτηση **main** προκειμένου να αρχικοποιήσουν τα αντικείμενα (**objects**) ''​rectOne''​ και ''​rectTwo''​. +
-  - H συνάρτηση ''​System.out.println()'' ​εκτυπώνει ένα αλφαριθμητικό (string) ακολουθούμενο από χαρακτήρα αλλαγής γραμμής.+
  
-===== Δήλωση Reference μεταβλητών και δημιουργία αντικειμένων ======+<​code>​ 
 +java CreateObjectDemo 
 +</​code>​
  
-Στο παραπάνω πρόγραμμα ​ορίζονται στη συνάρτηση ''​main'' ​τα εξής +Το παραπάνω πρόγραμμα τυπώνει τα εξής ​στην κονσόλα. 
-<​code ​java+ 
-Point originOne = new Point(23, 94); +<​code>​ 
-Rectangle ​rectOne ​= new Rectangle(originOne, ​100, 200); +[rectOne] ​ xPos: 23, yPos: 94 
-Rectangle ​rectTwo ​= new Rectangle(50100);+[rectOne] width: ​100, height: ​200 
 +[rectTwo]  xPos: 23yPos: 94                                                                                                                                                                 
 +[rectTwo] ​ xPos: 63, yPos: 74                                                                                                                                                                 
 +[rectOne] ​ xPos: 63, yPos: 74  ​
 </​code>​ </​code>​
  
-Τα παραπάνω ​μπορούν να γραφούν αναλυτικότερα ως εξής. +==== Επεξήγηση του ​παραπάνω ​κώδικα ​=====
-<code java> +
-Point originOne;​ +
-Rectangle rectOne, rectTwo; ​+
  
-originOne = new Point(23, 94); +Στο παραπάνω πρόγραμμα ορίζονται στη μέθοδο ''​main''​ τα εξής 
-rectOne = new Rectangle(originOne, ​100, 200); +<code java> 
-rectTwo = new Rectangle(50,​ 100);+    // Declare variables 
 +    Point originOne, originTwo;​ 
 +    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'',​ ''​rectOne'',​ ''​rectTwo''​. Οι μεταβλητές δυνητικά δείχνουν σε τύπους δεδομένων Point, Rectange, ​Rectangle. Προς το παρόν όμως το περιεχόμενο των μεταβλητών αυτών είναι απροσδιόριστο (undefined). Σε αναλογία με την γλώσσα C φανταστείτε ​τις μεταβλητές αυτές ως pointers που δεν είναι ​αρχικοποιημένοι σε κάποια υφιστάμενη διεύθυνση μνήμης. Η τιμή τους ​είναι απροσδιόριστη και η προσπάθεια να γράψουμε στη διεύθυνση μνήμης που δείχνουν θα προκαλάσει Segmentation Fault. Η παρακάτω εικόνα δείχνει ​την ύπαρξη ενός μη αρχικοποιημένου δείκτη.+Οι πρώτες δύο γραμμές ορίζουν τις μεταβλητές ''​originOne'',​ ''​originTwo'',​''​rectOne''​ και ​''​rectTwo''​. Οι μεταβλητές δυνητικά δείχνουν σε τύπους δεδομένων ​**Point** και **Rectangle**. Προς το παρόν όμως το περιεχόμενο των μεταβλητών αυτών είναι απροσδιόριστο (στην πραγματικότητα ο compiler ​αρχικοποιεί τις μεταβλητές ​αυτές στην τιμή **null**)
  
-{{ :​java:​reference-variables-01.png |}}+<WRAP tip 80% center round> 
 +__Σε αναλογία με την γλώσσα C__, φανταστείτε τις μεταβλητές αυτές ως pointers που δεν είναι αρχικοποιημένοι σε κάποια υφιστάμενη διεύθυνση μνήμηςΗ τιμή τους είναι απροσδιόριστη και η προσπάθεια να γράψουμε στη διεύθυνση μνήμης όπου δείχνουν θα προκαλέσει τερματισμό του προγράμματος από το λειτουργικό σύστημα. 
 +</​WRAP>​
  
-Προκειμένου ​να αρχικοποιηθούν οι μεταβλητές αυτές απαιτούνται δύο βήματα:​ +Η παρακάτω ​εικόνα δείχνει την ύπαρξη των τεσσάρων μη αρχικοποιημένων δεικτών. Όλοι ​αρχικά δείχνουν ​στην τιμή **null**.
-  - Η δέσμευση της απαραίτητης μνήμης, ώστε να μπορούμε να αποθηκεύσουμε τα δεδομένα που προδιαγράφονται απο τον συγκεκριμένο τύπο (κλάση). +
-  - Η αρχικοποίηση των επιμέρους μεταβλητών ​των ​αντικειμένων που ορίζονται απο ​την ​εκάστοτε κλάση.+
  
-Η παρακάτω εικόνα δείχνει τον δείκτη μετά την δέσμευση της απαιτούμενης μνήμης και την αρχικοποίηση των δεδομένων (μεταβλητών) του αντικειμένου ''​originOne''​.+{{:​java:​createobjectdemoreference1.png|}}
  
-{{ :​java:​reference-variables-02.png ?400 |}}+Αμέσως μετά τις δηλώσεις των μεταβλητών ακολουθούν οι κλήσεις των κατασκευαστών των αντίστοιχων κλάσεων. Όπως προαναφέραμε,​ ο κατασκευαστής όταν καλείται δεσμεύει την απαραίτητη μνήμη για το αντικείμενο, ​ αρχικοποιεί τα πεδία του αντικειμένου και επιστρέφει μία αναφορά προς το αντικείμενο που δημιούργησε.
  
-Ο παρακάτω κώδικας+Η παρακάτω ​εικόνα ​δείχνει τις μεταβλητές ''​originOne'',​ ''​originTwo'',​ ''​rectOne'',​ ''​rectTwo''​ μετά την αρχικοποίηση τους ​από τους αντίστοιχους κατασκευαστές.
  
-<​code ​java>rectOne = new Rectangle(originOne,​ 100, 200);</​code> ​+{{:java:​createobjectdemoreference2.png|}}
  
-δηλώνει ​την ​δέσμευση μνήμης για ένα αντικείμενο τύπου ''​Rectangle''​ όπου το σημείο της αρχής του είναι το σημείο ''​originOne''​. Επίσης ορίζονται οι τιμές των **width** και **height** σε 100 και 200 αντίστοιχα. O παραπάνω ορισμός σημαίνει ένα αρχικοποιημένο ​αντικείμενο ​μπορεί να έχει πολλούς δείκτες προς αυτό, όπως ​δείχνει το παρακάτω σχήμα.+Στη συνέχεια ακολουθούν οι εξής γραμμές κώδικα:
  
-{{ :java:reference-variables-03.png ?500 | }}+<​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>​
  
-===== Ο τελεστής new =====+Στις γραμμές αυτές συμβαίνουν τα εξής: 
 +    - Το αντικείμενο ''​rectTwo''​ επιλέγει ως πεδίο origin to ''​originOne''​. Στη συνέχεια,​ μέσω του ''​rectTwo''​ μεταβάλλονται οι συντεταγμένες του αντικειμένου ''​originOne''​. 
 +    - Εκτυπώνονται οι αλλαγές για το ''​rectTwo''​ στην κονσόλα. 
 +    - Εκτυπώνονται οι αλλαγές για το ''​rectOne''​ στην κονσόλα. Παρατηρούμε ότι οι συντεταγμένες του πεδίου **origin** άλλαξαν και για το αντικείμενο ''​rectOne''​. 
 + 
 +Tα παρακάτω δύο σχήματα αποτυπώνουν α) την αλλαγή του πεδίου **origin** του ''​rectTwo'',​ ώστε να δείχνει στο αντικείμενο ''​rectOne''​ και β) την αλλαγή των περιεχομένων του ''​originOne''​ μέσω του αντικειμένου ''​rectTwo''​. Οι αλλαγές αυτές επηρεάζουν και το πεδίο **origin** του ''​rectOne''​ που δείχνει στο κοινό αντικείμενο ''​origineOne''​. 
 + 
 +Παρατηρείστε ότι πλέον μόνο η μεταβλητή ''​originTwo''​ δείχνει στο αντικείμενο τύπου **Point** με συντεταγμένες 15, -33. 
 + 
 +|  **(a)** ​ | |  **(b)** ​ | 
 +| {{:​java:​createobjectdemoreference3.png|}} |  |{{:​java:​createobjectdemoreference4.png|}} | 
 + 
 +Τέλος το πρόγραμμα τελειώνει με την γραμμή κώδικα:​ 
 +<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> 
 +Κατά την χρήση **primitive** τύπων δεδομένων σε ένα πρόγραμμα (int, float, double) δεν απαιτείται η χρήση του τελεστή **new**. Ο λόγος που συμβαίνει αυτό είναι ότι για τους συγκεκριμένους τύπους δεδομένων,​ η διαδικασία δέσμευσης της μνήμης είναι στατική,​ καθώς είναι γνωστό εκ των προτέρων το εύρος μνήμης που απαιτούν. Οι **primitive** τύποι δεδομένων αποθηκεύονται πάντοτε στο **stack** της μεθόδου μέσα στην οποία δηλώνονται.
  
-<WRAP tip> +Αντίθετα,​ για τα αντικείμενα των ​κλάσεων ο compiler δεν ​μπορεί ​να γνωρίζει εκ των προτέρων το μέγεθος τουςκαθώς με την σειρά τους ​αυτά μπορεί να περιέχουν άλλα αντικείμενα, ​τα οποία με την σειρά ​τους μπορεί να περιέχουν άλλα αντικείμενα κ.ο.κ. Για τον ​λόγο αυτό, για τα αντικείμενα δεσμεύεται πάντοτε ​η απαραίτητη μνήμη δυναμικά, στην περιοχή δυναμικής δέσμευσης μνήμης ​που ​παραδοσιακά ονομάζεται ​**heap**.
-Κατά την χρήση **primitive** ​τύπων δεδομένων ​(int, floatdouble) δεν απαιτείται η χρήση του τελεστή **new** διότι η απαραίτητη μνήμη δεσμεύεται στο stack της μεθόδου που ​εκτελείται. ​+
 </​WRAP>​ </​WRAP>​
  
 ===== Πολλαπλοί κατασκευαστές σε μία κλάση ===== ===== Πολλαπλοί κατασκευαστές σε μία κλάση =====
  
-Μία κλάση μπορεί να έχει πολλούς διαφορετικούς. Κάθε κατασκευαστής ορίζει μία διαφορετική αρχικοποίηση των εσωτερικών μεταβλητών των αντικειμένων που δημιουργούντια με βάση το "​σχέδιο"​ της κλάσης. Το ποιός κατασκευαστής θα κληθεί εξαρτάται από τον τύπο, τη σειρά και τον αριθμό των ορισμάτων σε αναλογία με την υπερφόρτωση ​συναρτήσεων. ​Έτσι ​στη ​συνάρτηση ​main του παραδείγματος μας ​καλούνται δύο διαφορετικοί κατασκευαστές για δύο διαφορετικά αντικείμενα της ίδιας κλάσης.+Μία κλάση μπορεί να έχει πολλούς διαφορετικούς κατασκευαστές. Κάθε κατασκευαστής ορίζει μία διαφορετική αρχικοποίηση των εσωτερικών μεταβλητών των αντικειμένων που δημιουργούνται με βάση το "​σχέδιο"​ της κλάσης. Το ποιoς κατασκευαστής θα κληθεί εξαρτάται από τον τύπο, τη σειρά και τον αριθμό των ορισμάτων σε αναλογία με την υπερφόρτωση ​μεθόδων. Ας υποθέσουμε ​την ​παρακάτω μέθοδο **main**, στην οποία καλούνται δύο διαφορετικοί κατασκευαστές για δύο διαφορετικά αντικείμενα της ίδιας κλάσης ​**Rectangle**. Παρατηρήστε ότι η μεταβλητή **rectOne** αρχικοποιείται από την 1ο κατασκευαστή της κλάσης και η μεταβλητή **rectTwo** από τον 2ο κατασκευαστή.
  
 <code java> <code java>
-rectOne = new Rectangle(originOne, ​100, 200); +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 194: Line 272:
  
 <code java> <code java>
-                          ​// cadencespeed, gear +   // fields are widthheight 
-   Bicycle bicycle ​= new Bicycle(10, 20, 30); +   Rectangle rect = new Rectangle(10,​20, ​-5, 22); 
-   ​System.out.println("​Bicycle speed is " + bicycle.speed);+   ​System.out.println("​Rectangle dimensions are " + rect.width + ", ​" + rect.height);
 </​code>​ </​code>​
  
-<WRAP important>​ +<WRAP important ​80% center round
-Απαραίτητη προϋπόθεση για να δουλέψει ο παραπάνω κώδικας είναι το πεδίο speed να είναι προσβάσιμο, δηλαδή να μην έχει προσδιοριστή τύπου **private**.+Απαραίτητη προϋπόθεση για να δουλέψει ο παραπάνω κώδικας είναι τα πεδία width και height ​να είναι προσβάσιμα, δηλαδή να μην έχουν ​προσδιοριστή ​πρόσβασης ​τύπου **private**.
 </​WRAP>​ </​WRAP>​
  
-<WRAP tip> +<WRAP tip 80% center round
-Όπως προείπαμε μία καλή προγραμματιστική πρακτική είναι η απόκρυψη των πεδίων κάθε κλάσης και η δήλωση συναρτήσεων για την πρόσβαση στα δεδομένα της. Σε αυτή την περίπτωση η πρόσβαση στα πεδία των αντικειμένων είναι μη επιτρεπτή (ο compiler δεν μεταγλωττίζει το πρόγραμμα).+Όπως προείπαμε μία καλή προγραμματιστική πρακτική είναι η απόκρυψη των πεδίων κάθε κλάσης και η δήλωση συναρτήσεων για την πρόσβαση στα δεδομένα της. Σε αυτή την περίπτωση η απευθείας ​πρόσβαση στα πεδία των αντικειμένων είναι μη επιτρεπτή (ο compiler δεν μεταγλωττίζει το πρόγραμμα). Η πρόσβαση σε μεταβλητές που έχουν τον προσδιοριστή **private** μπορεί να γίνει μόνο μέσω βοηθητικών συναρτήσεων (set/get) που έχουν τον προσδιοριστή **public**.
 </​WRAP>​ </​WRAP>​
  
 ==== Χρήση των μεθόδων ενός αντικειμένου ==== ==== Χρήση των μεθόδων ενός αντικειμένου ====
  
-Σε αναλογία με τα πεδία οι μέθοδοι ενός αντικειμένου είναι προσβάσιμες μέσω του ονόματος του αντικειμένου,​ μία τελεία '​.'​ και το όνομα του πεδίου. Για παράδειγμα, ​+Σε αναλογία με τα πεδία οι μέθοδοι ενός αντικειμένου είναι προσβάσιμες μέσω του ονόματος του αντικειμένου,​ μία τελεία '​.'​ και το όνομα της μεθόδου. Για παράδειγμα, ​
  
 <code java> <code java>
-                          // cadence, speed, gear +   ​Rectangle rect = new Rectangle(10,​20, ​-5, 22); 
-   ​Bicycle bicycle ​= new Bicycle(10, 20, 30); +   ​System.out.println("​Rectangle dimensions are " + rect.getWidth() + ", ​" + rect.getHeight() );
-   ​System.out.println("​Bicycle speed is " + bicycle.getSpeed() );+
 </​code>​ </​code>​
  
-<WRAP important>​+<WRAP important ​80% center round>
 Ισχύουν και για τις μεθόδους όσα αναφέρονται για τους προσδιοριστές τύπου **public**, **private** των πεδίων. Ισχύουν και για τις μεθόδους όσα αναφέρονται για τους προσδιοριστές τύπου **public**, **private** των πεδίων.
 </​WRAP>​ </​WRAP>​
Line 223: Line 300:
 ===== Garbage Collection ===== ===== Garbage Collection =====
  
-Οι γλώσσες ​υψηλού επιπέδου που μέχρι τώρα έχετε γνωρίσει (**C**) αναθέτουν την ευθύνη δέσμευση μνήμης στον προγραμματιστή μέσω των συναρτήσεων **malloc()** και **free()**. Σε αντιδιαστολή,​ η **JAVA** αφήνει τον προγραμματιστεί να ορίσει όσα αντικείμενα επιθυμεί και δεσμεύει την μνήμη για αυτά μέσω του τελεστή **new**. +Οι γλώσσες προγραμματισμού που μέχρι τώρα έχετε γνωρίσει (βλέπε ​**C**) αναθέτουν την ευθύνη δέσμευσης μνήμης στον προγραμματιστή μέσω των συναρτήσεων **malloc()** και **free()**. Σε αντιδιαστολή,​ η **JAVA** αφήνει τον προγραμματιστεί να ορίσει όσα αντικείμενα επιθυμεί και δεσμεύει την μνήμη για αυτά μέσω του τελεστή **new**.
- +
-Περιοδικά το **JVM** κοιτάει εάν υπάρχουν αντικείμενα για τα οποία δεν υπάρχουν πλέον μεταβλητές που δείχνουν σε αυτά. Σε αυτές τις περιπτώσεις ελευθερώνει την μνήμη που έχει δεσμευτεί για τα αντικείμενα που εντόπισε. Ο μηχανισμός αυτός ονομάζεται **Garbage Collection** και απαντάται σε αρκετές γλώσσες υψηλού επιπέδου απελευθερώνοντας τον προγραμματιστή από την ευθύνη αποδέσμευσης της μνήμης που δεσμέυτηκε. +
- +
-Περισσότερα για την λειτουργία του Garbage Collector μπορείτε να βρείτε [[http://​www.oracle.com/​webfolder/​technetwork/​tutorials/​obe/​java/​gc01/​index.html|εδώ]]. +
- +
- +
-|Προηγούμενο:​ [[:​java:​class_methods | Μέθοδοι της Κλάσης ]] | Επόμενο:​ [[:​java:​this_operator | Oι τελεστές this και super ]]|+
  
 +Πώς όμως αποδεσμεύεται η μνήμη που δεσμεύτηκε προηγούμενα από το πρόγραμμα μας, αλλά δεν την χρειαζόμαστε πλέον; Περιοδικά το **JVM** κοιτάει εάν υπάρχει δεσμευμένη μνήμη για αντικείμενα στα οποία δεν υφίστανται πλέον αναφορές/​references που δείχνουν σε αυτά. Σε αυτές τις περιπτώσεις,​ ελευθερώνεται η μνήμη που έχει δεσμευτεί για τα αντικείμενα αυτής της κατηγορίας. Παράλληλα η αποδέσμευση της μνήμης και η διαγραφή των αντικειμένων πιθανόν συνεπάγεται ότι και άλλα αντικείμενα δεν διαθέτουν πια αναφορές προς αυτά κ.ο.κ. Η διαδικασία συνεχίζεται μέχρι να αποδεσμευτεί όλη η δυναμικά δεσμευμένη μνήμη. ​
  
 +Ο μηχανισμός **Garbage Collection** απαντάται σε αρκετές γλώσσες υψηλού επιπέδου,​ απελευθερώνοντας τον προγραμματιστή από την ευθύνη αποδέσμευσης της μνήμης που δεσμεύτηκε προηγούμενα. Η ευθύνη της δεύσμευσης/​αποδέσμευσης μνήμης δεν επαφίεται στον προγραμματιστή,​ πράγμα που κάνει λιγότερο επίπονο τον προγραμματισμό. ​
  
 +Περισσότερα για την λειτουργία του Garbage Collector και τις εναλλακτικές υλοποιήσεις μπορείτε να βρείτε [[http://​www.oracle.com/​webfolder/​technetwork/​tutorials/​obe/​java/​gc01/​index.html|εδώ]].
  
 +|Προηγούμενο:​ [[:​java:​class_constructors | Κατασκευαστές της κλάσης ]] |  [[:toc | Περιεχόμενα ]] | Επόμενο:​ [[:​java:​arrays | Πίνακες
 + ]]|
  
java/objects.txt · Last modified: 2018/02/16 16:03 by gthanos