Προγραμματισμός II

Διομήδης Σπινέλλης
Τμήμα Διοικητικής Επιστήμης και Τεχνολογίας
Οικονομικό Πανεπιστήμιο Αθηνών
dds@aueb.gr

Εισαγωγή στο μάθημα

Καλώς ήρθατε

Προγραμματισμός II

Αυτοαξιολόγηση

Πόσο άνετα προγραμματίζετε στη Java;

Στόχοι του μαθήματος

Στόχος του μαθήματος είναι όσοι το παρακολουθήσουν να είναι σε θέση να:

Τρόπος διδασκαλίας

Οι σημειώσεις

Βαθμολογία

Ο τελικός βαθμός κάθε φοιτήτριας ή φοιτητή θα βασίζεται σε 3 κριτήρια: Προσοχή:

Βαθμολογία χωρίς ομαδική εργασία

Σε περίπτωση μη συμμετοχής στην ομαδική εργασία ο βαθμός υπολογίζεται κατά 40% από τις εξετάσεις και 30% από τις ατομικές ασκήσεις, ώστε να να είναι δίκαιο για τα άτομα που κάνουν την ομαδική εργασία. Επιπλέον, στην περίπτωση αυτή ο μέγιστος δυνατός βαθμός είναι το 5. Ενδεικτικά, ο τύπος υπολογισμού είναι κάτι σαν:

MIN(ROUND(
  IF(@Exam>=5,
    IF(ISNA(@group),
      MAX(@exam*0.3 + IFNA(@Exercise, 0)*0.3, 5),
      @Exam*0.2+IFNA(@Participation, 0)*0.1+IFNA(@Bonus, 0)+IFNA(@Exercise, 0)*0.3+IFNA(@Group, 0)*0.5),MAX(INT(@Exam),0))
  *2,0)/2,10)

Αξιολόγηση συμμετοχής

HMAC QR participation token

Στατιστικά στοιχεία

Επιδόσεις στις εξετάσεις στο τέλος του εξαμήνου.
ΈτοςΕξετάσειςΑσκήσειςΒαθμόςΕπιτυχία
20157.69.18.194%
20167.29886%
20178.08.88.390%
20187.79.18.593%
20217.79.17.580%
20226.98.37.578%
20236.98.87.682%
20257.58.77.883%

Οι ασκήσεις

Χρήση του συστήματος των ασκήσεων jarpeb

Για να χρησιμοποιήσετε το σύστημα πρέπει:

Παράδοση της βαθμολογίας

Καθυστερημένη παράδοση

Χρήση ΠΤΝ

Για τη χρήση παραγωγικής τεχνητής νοημοσύνης (π.χ. ChatGPT, Bard, GitHub Copilot) ισχύουν τα εξής.

Διαθέσιμα συγγράμματα

Πρόσθετα δωρεάν συγγράμματα

Επίσης διαθέσιμα στις φοιτήτριες και στους φοιτητές του ΟΠΑ μέσω του HEAL-Link:

Βιβλιογραφία για προγραμματισμό

Βιβλιογραφία για τη Java

Επισκόπηση θεωρίας

Επισκόπηση των ασκήσεων

  1. εξοικείωση με τις ασκήσεις
  2. ορίσματα, εκφράσεις, βρόχοι και αποφάσεις
  3. δημιουργία αντικειμένων και πρόσβαση στις μεθόδους τους
  4. δημιουργία μιας κλάσης
  5. κληρονομικότητα
  6. παραγωγή και έλεγχος εξαιρέσεων
  7. προγραμματισμός με συμβολοσειρές
  8. μετασχηματισμός αρχείου κειμένου
  9. μια απλή γραφική εφαρμογή
  10. επεξεργασία XML
  11. επικοινωνία πελάτη-εξυπηρετητή
  12. χρήση νημάτων και παραμετρικών τύπων
  13. προγραμματισμός σε ζεύγη
  14. αναδρομικές συναρτήσεις
  15. μορφοποίηση
  16. διεπαφές

Δουλειά για το επόμενο μάθημα

Γλώσσες και περιβάλλοντα ανάπτυξης

Ιστορική ανασκόπηση

Διαδικασιακές γλώσσες

Σε μια αλγοριθμική (imperative) (ή προστακτική ή επιτακτική ή διαδικαστική (procedural)) γλώσσα το πρόγραμμα εκφράζει άμεσα τα βήματα που επιθυμούμε να εκτελέσει ο υπολογιστής.

Τιμές, τύποι και μεταβλητές

Εκφράσεις και τελεστές

Μηχανισμοί αφαίρεσης

Μηχανισμοί ελέγχου της ροής

Αντικειμενοστρεφείς γλώσσες

  • Χαρακτηριστικές γλώσσες: Smalltalk, Squeak, C++, Java, C#, Python, Ruby, JavaScript, TypeScript, Swift

    Συναρτησιακός προγραμματισμός

    Χαρακτηριστικά συναρτησιακού προγραμματισμού

    Γλώσσες ολοκλήρωσης

    Θέματα για μελέτη

    1. Τι κάνει μια γλώσσα κατάλληλη για την υλοποίηση επιχειρηματικών εφαρμογών;
    2. Με ποιον τύπο δεδομένων θα παραστήσετε στη Java χρηματικά ποσά; Δώστε παραδείγματα.

    Άσκηση: εξοικείωση με τις ασκήσεις

    Άσκηση 1

    Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

    Βιβλιογραφία

    Τεχνολογίες μεταγλώττισης και εκτέλεσης

    Το χάσμα υλικού και λογισμικού

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

    Υλοποίηση γλωσσών προγραμματισμού

    Μια γλώσσα προγραμματισμού μπορεί - ανάλογα με τη γλώσσα - να υλοποιηθεί με τους παρακάτω τρόπους: καθώς και με συνδυασμούς τους.

    Αρχιτεκτονική του μεταγλωττιστή

    Η διεργασία της μεταγλώττισης μπορεί να διαχωριστεί στις παρακάτω ξεχωριστές λειτουργίες οι οποίες εκτελούνται σε διαδοχικές φάσεις:

    Λεκτική ανάλυση

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

    Λεκτικές μονάδες

    Χρήση λεκτικών μονάδων

    Ο συντακτικός αναλυτής

    Ο συντακτικός αναλυτής:

    Παράδειγμα

        i = 0;
        while ( i < 10) {
            System.out.println(i);
            i = i + 1;
        }
    

    (Το δέντρο μπορεί να κατασκευαστεί και ζωντανά από 17 άτομα.)

    Συντακτικό δένδρο

    Parse graph

    Παραγωγή κώδικα

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

    Βελτιστοποίηση του ενδιάμεσου κώδικα

    Η βελτιστοποίηση του κώδικα μετασχηματίζει τον κώδικα σε μια μορφή που παράγει τα ίδια αποτελέσματα με τον αρχικά αλλά βελτιωμένα κάποια κριτήρια απόδοσης. Τέτοια κριτήρια μπορεί να είναι:

    Πλεονεκτήματα βελτιστοποίησης

    Η βελτιστοποίηση μπορεί να απαλλάξει τον προγραμματιστή από αντιπαραγωγικές αλλαγές του κώδικα που έχουν ως στόχο να ικανοποιήσουν τα κριτήρια αυτά και να του επιτρέψει να συγκεντρωθεί σε άλλα ποιοτικά στοιχεία του παραγόμενου κώδικα όπως την ορθότητα, την ασφάλεια, τη διαθεσιμότητα, τη συντηρησιμότητα, και τη μεταφερσιμότητα. Συχνά βελτιστοποιήσεις που γίνονται από τον προγραμματιστή έρχονται σε αντίθεση με τα παραπάνω ποιοτικά στοιχεία.

    Παράδειγμα βελτιστοποίησης

    Απαλοιφή κοινών υποεκφράσεων (common subexpression elimination)
    Εκφράσεις με κοινά στοιχεία υπολογίζονται μόνο μια φορά. Η ακολουθία:
    x = b / c;
    y = 42 + b / c;
    
    μετασχηματίζεται στην ακολουθία:
    x = b / c;
    y = 42 + x;
    

    Παράδειγμα βελτιστοποίησης

    Μετακίνηση κώδικα βρόχων (loop code motion)
    Εκφράσεις που δεν αλλάζουν μέσα σε ένα βρόχο μετακινούνται έξω από αυτόν. Η ακολουθία:
    {
        int a, b, z;
    
        a = 8; b = 4;
        for (i = 0; i < 10; i++) {
            z = a / b;
            System.out.println(z);
        }
    }
    
    μετασχηματίζεται στην ακολουθία:
    {
        int a, b, z;
    
        a = 8; b = 4;
        z = a / b;
        for (i = 0; i < 10; i++) {
            System.out.println(z);
        }
    }
    

    Παράδειγμα βελτιστοποίησης

    Απαλοιφή άχρηστου κώδικα (dead code removal)
    Κώδικας που δεν εκτελείται ποτέ απαλείφεται. Η ακολουθία:
    {
        int a, q;
    
        q = 48;
        return (q);
        a = q / 2;
    }
    
    μετασχηματίζεται στην ακολουθία:
    {
        int a, q;
    
        q = 48;
        return (q);
    }
    

    Παράδειγμα βελτιστοποίησης

    Απαλοιφή κλήσεων σε συναρτήσεις (function inlining)
    Κλήσεις σε συναρτήσεις μετασχηματίζονται σε απευθείας χρήση του αντίστοιχου κώδικα. Η ακολουθία:
    static int
    square(int a) {
        return (a * a);
    }
    
    public static void main(String args[]) {
        System.out.println(square(12));
    }
    
    μετασχηματίζεται στην ακολουθία:
    public static void main(String args[]) {
        System.out.println(12 * 12);
    }
    

    Παράδειγμα βελτιστοποίησης

    Απαλοιφή αναδρομής από το τέλος συνάρτησης (tail recursion elimination)
    Αναδρομή στο τέλος μιας συνάρτησης μετασχηματίζεται σε βρόχο. Η ακολουθία:
    foo() {
        System.out.println("foo");
        foo();
    }
    
    μετασχηματίζεται στην ακολουθία:
    foo() {
        for (;;)
            System.out.println("foo");
    }
    

    Βελτιστοποίηση του τελικού κώδικα

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

    Παράδειγμα βελτιστοποίησης τελικού κώδικα

    Η ακολουθία:
        mov $12, %rax
        mov %rax, %rbx
        mov $20, %rax
    
    μετασχηματίζεται στην ακολουθία:
        mov $12, %rbx
        mov $20, %rax
    
    Επίσης η διάταξη των εντολών μπορεί να βελτιωθεί για να γίνεται καλύτερη χρήση πολλαπλών υπολογιστικών στοιχείων που διαθέτει ο επεξεργαστής. Για παράδειγμα σε ορισμένους επεξεργαστές η εναλλαγή εντολών κινητής υποδιαστολής με εντολές ακεραίων επιτρέπει στις δύο λειτουργικές μονάδες να δουλεύουν παράλληλα.

    Σύνδεση

    Κατά τη σύνδεση τα ανεξάρτητα μεταγλωττισμένα τμήματα του προγράμματος συνδέονται μεταξύ τους και με τις βιβλιοθήκες της γλώσσας για να δημιουργηθεί το τελικό εκτελέσιμο πρόγραμμα. Συχνά οι βιβλιοθήκες που χρησιμοποιούνται είναι κοινές ανάμεσα σε προγράμματα και φορτώνονται δυναμικά κατά το στάδιο εκτέλεσης του προγράμματος (Unix shared libraries, Windows DLLs). Κατά τη φάση της σύνδεσης γίνεται έλεγχος πως όλες οι συναρτήσεις και μεταβλητές που χρησιμοποιούνται έχουν οριστεί και, για ορισμένες γλώσσες όπως η C++, πως οι τύποι των συμβόλων που έχουν οριστεί σε διαφορετικά αρχεία είναι συμβατοί μεταξύ τους. Ορισμένες γλώσσες όπως η Java υλοποιούν μεγάλο μέρος της σύνδεσης κατά τη φόρτωση του προγράμματος στη μνήμη για εκτέλεση.

    Ιδεατές μηχανές

    Μια ιδεατή μηχανή (virtual machine) εμφανίζει στο λογισμικό που τρέχει πάνω σε αυτήν μια διαφορετική διεπαφή από αυτή στην οποία βασίζεται η μηχανή για την υλοποίησή της. Συχνά οι ιδεατές μηχανές υλοποιούνται σε ιεραρχία.

    Πλεονεκτήματα και προβλήματα ιδεατών μηχανών

    Διαχείριση μνήμης

    Κατά τη διάρκεια ζωής του προγράμματος υπάρχουν απαιτήσεις για τη φύλαξη δεδομένων με διαφορετική διάρκεια ζωής. Συγκεκριμένα, πρέπει να υπάρχει υποστήριξη για δεδομένα που διατηρούνται:

    Παράδειγμα διάταξης μνήμης

    Στοίβα (stack)
    ...

    ...
    Σωρός (heap)
    (Δυναμική μνήμη)
    ...
    Στατικά δεδομένα (static data)
    ...
    Μεταγλωττισμένος κώδικας (code (text))

    Τρόποι διαχείρισης μνήμης

    Όταν ο όγκος της κύριας μνήμης του υπολογιστή δεν επαρκεί μπορεί να χρησιμοποιηθεί:

    Τέλος, για οικονομία στο χώρο που απαιτεί ο κώδικας των προγραμμάτων σε δευτερεύουσα αποθήκευση, χρησιμοποιούνται συχνά μοιρασμένες βιβλιοθήκες (shared libraries) (π.χ. .DLL, .so).

    Άσκηση: ορίσματα, εκφράσεις, βρόχοι και αποφάσεις

    Άσκηση 2

    Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

    Βιβλιογραφία

    Προγραμματισμός με αντικείμενα

    Αντικείμενα

    Κλάσεις

    Δημιουργία νέων αντικειμένων

    Καθορισμός μνήμης αντικειμένων με new

    Καθορισμός μνήμης αντικειμένων με αναφορά

    Κλήση μεθόδων

    Πρόσβαση σε ιδιότητες

    Ορατότητα

    Παράδειγμα: Point

    class Point {
      // Public fields
      public int x, y;
      private boolean visible;
      private int serialNumber;
      // Private method
      private void setpos(int sx, int sy) {
        x = sx;
        y = sy;
      }
      // Public methd
      public void moveToCenter() {
        setpos(0, 0);
      }
    
    }
    

    Παράδειγμα: TestPoint

    class TestPoint {
      public static void main(String args[])
      {
        Point a;
    
        a = new Point();
        a.moveToCenter();
        // Use public field
        a.x = 10;
      }
    }
    

    Μέθοδοι κατασκευαστές

    Κλήση κατασκευαστών

    Ιδιότητες και μέθοδοι κλάσης

    Δήλωση μεταβλητών με var

    Παράδειγμα: εύρεση ημέρας

    
    import java.util.Calendar;
    import java.util.GregorianCalendar;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    
    class FindDay {
      /** Return the name of the given numeric week day */
      public static String weekDayName(int weekNumber) {
        return switch (weekNumber) {
          case Calendar.MONDAY -> "Δευτέρα";
          case Calendar.TUESDAY -> "Τρίτη";
          case Calendar.WEDNESDAY -> "Τετάρτη";
          case Calendar.THURSDAY -> "Πέμπτη";
          case Calendar.FRIDAY -> "Παρασκευή";
          case Calendar.SATURDAY -> "Σάββατο";
          case Calendar.SUNDAY -> "Κυριακή";
          default -> throw new IllegalStateException("Unexpected value: " + weekNumber);
        };
      }
    
      public static void main(String args[]) throws Exception {
      // ...
    }
    

    Παράδειγμα: εύρεση ημέρας (main)

    
      public static void main(String[] args) throws Exception {
          // Are appropriate arguments given?
          if (args.length != 3) {
            System.err.println("usage: FindDay year month day");
            System.exit(1);
          }
    
          // Parse year, month, day
          int year = Integer.parseInt(args[0]);
          int month = Integer.parseInt(args[1]) - 1;
          int monthDay = Integer.parseInt(args[2]);
    
          // Set the calendar and calculate the day name
          var d = new GregorianCalendar(year, month, monthDay);
          String dn = weekDayName(d.get(Calendar.DAY_OF_WEEK));
    
          // Print the day name
          System.out.println(dn);
        }
    

    Μέθοδοι όλων των αντικειμένων

    Άσκηση: δημιουργία αντικειμένων και πρόσβαση στις μεθόδους τους

    Άσκηση 3

    Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

    Βιβλιογραφία

    Δημιουργία κλάσεων

    Ορισμός κλάσεων

    Ορισμός πεδίων υπόστασης

    Ορισμός μεθόδων υπόστασης

    Πρόσβαση στα μέλη της κλάσης

    Πρόσβαση στα μέλη της κλάσης: παράδειγμα

    Μέθοδοι κατασκευής

    Μέθοδοι κατασκευής: παράδειγμα

    class Point {
        /* Fields */
    
        /** Point x coordinate */
        private int x;
        /** Point y coordinate */
        private int y;
    
        /* Methods */
        /** Default constructor */
        Point() { x = y = 0; }
        /** Constructor with coordinates */
        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    

    Έλεγχος πρόσβασης

    Κάθε μέθοδος ή πεδίο μπορεί να έχει ως προσδιοριστή
    public
    Το μέλος είναι ορατό σε όλες τις άλλες κλάσεις
    private
    Το μέλος είναι ορατό μόνο στις μεθόδους της δικής μας κλάσης
    (τίποτα)
    Το μέλος είναι ορατό στις κλάσεις του πακέτου μας
    Μια καλοσχεδιασμένη κλάση έχει:

    Ορισμός ιδιοτήτων και μεθόδων κλάσης

    Παράδειγμα ιδιοτήτων και μεθόδων κλάσης

    Μπλοκ αρχικοποίησης

    Σε ανώνυμα μπλοκ { } στο σώμα της κλάσης μπορεί να τοποθετηθεί:

    Εσωτερικές κλάσεις

    Μια κλάση μπορεί να οριστεί εσωτερικά:

    Παράδειγμα εσωτερικής κλάσης

    class Rectangle {
        private static class Point {
            private int x, y;
    
            /** Point constructor */
            Point(int ix, int iy) {
                x = ix;
                y = iy;
            }
        }
    
        private Point topLeft, bottomRight;
    
        /** Rectangle constructor */
        Rectangle(int x, int y, int height, int width) {
            topLeft = new Point(x, y);
            bottomRight = new Point(x + width, y + height);
        }
    }
    

    Παράδειγμα ανώνυμης κλάσης

    class InnerCall {
        public static void main(String args[]) {
            System.out.println(new Object());
            System.out.println(new Object() {
                @Override
                public String toString() {
                    return "I am a woke object";
                }
            });
        }
    }
    

    Απαριθμήσεις

    Παράδειγμα

    enum Ingredients {
      TOMATO,
      ONION,
      TZATZIKI,
      POTATO,
      MUSTARD,
      SOUVLAKI,
      GYROS
    };
    

    Χρήση απαριθμήσεων

    Απαρίθμηση ως κλάση

    Η αντίστοιχη κλάση χωρίς τη χρήση απαρίθμησης θα είχε την παρακάτω μορφή.
    
    public class Ingredients {
        // Static array to hold all ingredient constants
        private static final Ingredients[] VALUES = new Ingredients[7];
    
        // Constants with names and ordinal values
        public static final Ingredients TOMATO = new Ingredients("TOMATO", 0);
        public static final Ingredients ONION = new Ingredients("ONION", 1);
        public static final Ingredients TZATZIKI = new Ingredients("TZATZIKI", 2);
        public static final Ingredients POTATO = new Ingredients("POTATO", 3);
        public static final Ingredients MUSTARD = new Ingredients("MUSTARD", 4);
        public static final Ingredients SOUVLAKI = new Ingredients("SOUVLAKI", 5);
        public static final Ingredients GYROS = new Ingredients("GYROS", 6);
    
        private final String name;
        private final int ordinal;
    
        private Ingredients(String name, int ordinal) {
            this.name = name;
            this.ordinal = ordinal;
            VALUES[ordinal] = this;  // Add to the static array
        }
    
        // Getters
        public int ordinal() {
            return ordinal;
        }
    
        public String getName() {
            return name;
        }
    
        public static Ingredients[] values() {
            return VALUES.clone();  // Return a copy of the array
        }
    
        public static Ingredients valueOf(String name) {
            for (Ingredients ingredient : VALUES) {
                if (ingredient.name.equals(name)) {
                    return ingredient;
                }
            }
            throw new IllegalArgumentException("No enum constant " + name);
        }
    
        @Override
        public String toString() {
            return name;
        }
    }
    

    Πολυμορφισμός με ταίριαγμα προτύπων

    Με εντολές switch μπορούμε να γράψουμε κώδικα για συγκεκριμένους τύπους με βάση το ταίριασμα προτύπων (pattern matching).
    
    class PaternMatch {
    
        class RetailCustomer {}
        class BusinessCustomer {}
    
        /** Return the document a given object shall receive */
        private static String documentName(Object o) {
            return switch (o) {
                case RetailCustomer rc -> "receipt";
                case BusinessCustomer bc -> "invoice";
                default -> "unknown document";
            };
        }
    
        public static void main(String[] args) {
            var retailCustomer = new RetailCustomer();
            var businessCustomer = new BusinessCustomer();
            System.out.println("Retail customer gets "
                    + documentName( retailCustomer));
            System.out.println("Business customer gets "
                    + documentName(businessCustomer));
        }
    }
    

    Εγγραφές

    Παράδειγμα

    
    public class RecordDemo {
        record Point(int x, int y) {}
    
        public static void main(String[] args) {
            var a = new Point(5, 12); // Pythagorean triple
            System.out.println("Point " + a + " has magnitude "
                    + Math.sqrt(a.x() * a.x() + a.y() * a.y()));
        }
    }
    

    Εγγραφή ως κλάση

    Η αντίστοιχη κλάση χωρίς τη χρήση εγγραφής θα είχε την παρακάτω μορφή.
    
    public class Point {
        private final int x;
        private final int y;
    
        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    
        // Getters
        public int getX() {
            return x;
        }
    
        public int getY() {
            return y;
        }
    
        // Object methods
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Point point = (Point) o;
            return x == point.x && y == point.y;
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    
        @Override
        public String toString() {
            return "Point{" + "x=" + x + ", y=" + y + '}';
        }
    }
    

    Ταίριαγμα προτύπων σε εγγραφές

    Σε εγγραφές μπορούμε να ταιριάξουμε και τα ορίσματά τους.
    
    class PaternMatch {
    
        record Point2D(double x, double y) {}
        record Point3D(double x, double y, double z) {}
    
        /** Output the magnitude of the specified object */
        private static void printMagnitude(Object o) {
            System.out.println("Magnitude of " + o + " is " +
                switch (o) {
                    case Point2D(double x, double y) -> Math.sqrt(x * x + y * y);
                    case Point3D(double x, double y, double z) ->
                        Math.sqrt(x * x + y * y + z * z);
                    default -> throw new IllegalArgumentException("Unexpected type: "
                            + o.getClass().getName());
                }
            );
        }
    
        public static void main(String[] args) {
            printMagnitude(new Point2D(3, 4)); // Pythagorean triple
            printMagnitude(new Point3D(1, 4, 8)); // Pythagorean quadruple
        }
    }
    

    Το σχεδιαστικό πρότυπο singleton

    Παράδειγμα singleton

    Άσκηση: δημιουργία μιας κλάσης

    Άσκηση 4

    Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

    Βιβλιογραφία

    Κληρονομικότητα

    Εισαγωγή

    Διάγραμμα κληρονομικότητας

    Κληρονομικότητα σε κλάσεις

    Υπερφόρτωση

    Παράδειγμα: σχήματα

    
    class Shape {
        private int x, y;       // Position
        public void setPosition(int px, int py) {
            x = px;
            y = py;
        }
    
        @Override public String toString() {
            return "Shape(" + x + ", " + y + ")";
        }
    }
    
    class Circle extends Shape {
        private int radius;
        public void setRadius(int r) {
            radius = r;
        }
    
        @Override public String toString() {
            return super.toString() + ": Circle(" + radius + ")";
        }
    }
    
    class Rectangle extends Shape {
        private int height, width;
    
        public void setDimensions(int h, int w) {
            height = h;
            width = w;
        }
    
        @Override public String toString() {
            return super.toString() + ": Rectangle(" + height + " x " + width + ")";
        }
    }
    
    class Test1 {
        static public void main(String args[])
        {
            Circle c = new Circle();
            Rectangle r = new Rectangle();
    
            r.setPosition(1, 2);
            r.setDimensions(50, 50);
            c.setPosition(3, 4);
            c.setRadius(10);
            System.out.println(r);
            System.out.println(c);
        }
    }
    

    Σχήματα: διάγραμμα

    Ο προσδιοριστής protected

    Δυναμική διεκπεραίωση

    Παράδειγμα δυναμικής διεκπεραίωσης

    static public void main(String args[])
    {
        Rectangle r = new Rectangle();
        Shape s;
    
        r.setPosition(1, 2);
        r.setDimensions(50, 50);
        s = r;
        s.setPosition(10, 20);
        System.out.println(r);
        System.out.println(s);
        r = (Rectangle)s;
    }
    

    Λειτουργία δυναμικής διεκπεραίωσης

    Πλεονεκτήματα της δυναμικής διεκπεραίωσης

    Σφραγισμένες κλάσεις

    Με τους προσδιοριστές sealed και permits μπορούμε να ορίσουμε ποιες κλάσεις επιτρέπεται να επεκτείνουν τη μητρική κλάση.
    
    public sealed class Shape permits Circle, Rectangle {
    }
    
    class Circle extends Shape {
    }
    
    class Rectangle extends Shape {
    }
    

    Αφηρημένες κλάσεις

    Σχεδιάζοντας με αφηρημένες κλάσεις

    Παράδειγμα: σχήματα

    Σχήματα: ο κώδικας

    
    abstract class Shape {
        private double x, y;        // Position
        protected double getX() { return x; }
        protected double getY() { return y; }
        public void setposition(double px, double py) {
            x = px;
            y = py;
        }
        public abstract double area();
        @Override public String toString() {
            return "Shape(x=" + x + ", y=" + y + ", area=" + area() + ")";
        }
    }
    
    class Circle extends Shape {
        private double radius;
        public void setradius(double r) {
            radius = r;
        }
        @Override public double area() {
            return Math.PI * radius * radius;
        }
        @Override public String toString() {
            return super.toString() + ": Circle(" + radius + ")";
        }
    }
    
    class Rectangle extends Shape {
        private double height, width;
        public void setdimensions(double h, double w) {
            height = h;
            width = w;
        }
        @Override public double area() {
            return height * width;
        }
        @Override public String toString() {
            return super.toString() + ": Rectangle(" + height + " x " + width + ")";
        }
    }
    
    class Test2 {
        static public void main(String args[])
        {
            Circle c = new Circle();
            Rectangle r = new Rectangle();
            Shape s[] = new Shape[2];
    
            s[0] = r;
            r.setposition(1, 2);
            r.setdimensions(50, 50);
    
            s[1] = c;
            c.setposition(3, 4);
            c.setradius(10);
            for (int i = 0; i < s.length; i++)
                System.out.println(s[i]);
        }
    }
    
    Το παραπάνω πρόγραμμα θα τυπώσει:
    Shape(x=1.0, y=2.0, area=2500.0): Rectangle(50.0 x 50.0)
    Shape(x=3.0, y=4.0, area=628.3185307179587): Circle(10.0)
    

    Τελικές μεταβλητές

    Τελικά ορίσματα

    Τελικά πεδία

    Πόσα σχόλια είναι αρκετά;

    Unneeded comments

    Σχόλια για τα σχόλια

    Έλεγχοι

    Τι να αποφεύγετε

    Οδηγίες και παράδειγμα μορφοποίησης κώδικα

    /*
     * Όνομα της κλάσης
     *
     * Copyright έτος όνομα/οργανισμός.
     */
    
    package gr.aueb.dmst.Package;
    
    import java.blah.blough.bligh;
    
    /**
     * Σύνοψη της κλάσης σε μια γραμμή.
     * Αναλυτική περιγραφή της κλάσης.
     *
     * @version     1.82 18 Mar 1999
     * @author      Όνομα Επώνυμο
     */
    
    public class SpecialHtmlParser extends FileHtmlParser {
    
        /*
         * Εδώ γράφεται το σχόλιο υλοποίησης της κλάσης.
         */
    
        /** Σύνοψη του πεδίου κλάσης classVar1 */
        public static int classVar1;
    
        /** Σύνοψη του πεδίου κλάσης classVar2 */
        protected static int classVar2;
    
        /** Σύνοψη του πεδίου κλάσης classVar3 */
        static int classVar3;
    
        /** Σύνοψη του πεδίου κλάσης classVar3 */
        private static Object classVar3;
    
        /**
         * Σύνοψη του πεδίου υπόστασης instanceVar1
         * Εκτενής επεξήγηση του πεδίου instanceVar1 σε πολλαπλές
         * γραμμές
         */
        public int instanceVar1;
    
        /** Σύνοψη του πεδίου υπόστασης instanceVar2 */
        protected int instanceVar2;
    
        /** Σύνοψη του πεδίου υπόστασης instanceVar3 */
        static int instanceVar3;
    
        /** Σύνοψη του πεδίου υπόστασης instanceVar4 */
        private Object instanceVar4;
    
        /** Construct a parser for the specified HTML dialect. */
        SpecialHtmlParser(string dialect, int maxNesting) {
            // Κώδικας
        }
    
        /** Construct a default HTML parser. */
        SpecialHtmlParser(string dialect, int maxNesting) {}
    
        /**
         * Σύνοψη της μεθόδου.
         * Εκτενής επεξήγηση της μεθόδου σε πολλαπλές
         * γραμμές.
         */
        public void doSomething() {
    
        int nLines = 0;                // HTML lines in the file
        int nChars = 0                // Number of characters in the file
        int i;
        double averageDensity = 1.;        // Average density of comments in the file
        Car transport;                // Transport to use
    
            for (;;)
                a++;
    
            for (int j = 0; j < 10; j++) {
                a++;
                b++;
            }
    
            while (a < 10) {
                a++;
                b += 12;
            }
    
            while (a < 10) {
                a++;
                for (int i = 0; i < 10; i++)
                    b += 12;
            }
    
            do {
                a++;
                b += 12;
            } while (a < 10);
    
            switch (c) {
            case 'a':
                system.out.println("Alpha");
                break;
            case 'b':
                system.out.println("Bravo");
                break;
            case 'c':
                system.out.println("Charlie");
                break;
            default:
                system.out.println("???");
                break;
            }
    
            if (a == 3) {
                system.out.println("Threee");
                k = 52;
            }
    
            if (a == 3) {
                system.out.println("Three");
                k = 52;
            } else {
                system.out.println("Not three");
                k = 55;
            }
    
            if (a == 3)
                system.out.println("Three");
            else
                system.out.println("Not three");
    
            if (s.equals("a")
                system.out.println("Alpha");
            else if (s.equals("b")
                system.out.println("Bravo");
            else if (s.equals("c")
                system.out.println("Charlie");
            else
                system.out.println("???");
    
            try {
                i = 12;
                o.myMethod();
            } catch (ExceptionClass e) {
                statements;
            } finally {
                statements;
            }
    
        if (a && !b) {
            a = 2 * (3 + 8) % 15;
            k = a.myMethod(q, b, c);
        }
        return k;
    
       /**
        * Returns an Image object that can then be painted on the screen.
        * The url argument must specify an absolute {@link URL}. The name
        * argument is a specifier that is relative to the url argument.
        * <p>
        * This method always returns immediately, whether or not the
        * image exists. When this applet attempts to draw the image on
        * the screen, the data will be loaded. The graphics primitives
        * that draw the image will incrementally paint on the screen.
        *
        * @param  url  an absolute URL giving the base location of the image
        *         name the location of the image, relative to the url argument
        * @return      the image at the specified URL
        * @see         Image
        */
        public Image getImage(URL url, String name) {
            try {
                return getImage(new URL(url, name));
            } catch (MalformedURLException e) {
                return null;
            }
        }
    
         /*
          * A non-javadoc comment with a special keyword
          * (recommended keywords in parenthesis)
          *
          * (XXX, FIXME, TODO): The comment
          */
    
    Σημείωση: οι στηλοθέτες (tab) πρέπει να αντιστοιχούν σε 8 κενά, έστω και αν πάντα η στοίχιση γίνεται σε 4 κενά. Στο διορθωτή vim οι σωστές ρυθμίσεις είναι:
    set shiftwidth=4
    set smarttab
    

    Βιβλιογραφία

    Πρόσθετες πληροφορίες

    Ασκήσεις

    Άσκηση 15

    Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

    Γενικεύσεις και νήματα

    Παραμετρικοί τύποι

    Παράδειγμα: ζευγάρι

    
    class Pair <E1, E2> {
        private final E1 element1;
        private final E2 element2;
        public Pair(final E1 e1, final E2 e2) {
            element1 = e1;
            element2 = e2;
        }
        public E1 getFirst() {
            return element1;
        }
        public E2 getSecond() {
            return element2;
        }
        @Override
        public String toString() {
            return "(" + element1.toString() + ", " + element2.toString() + ")";
        }
    }
    
    class Sock {}
    class Man {}
    class Woman {}
    
    class Test {
        public static void main(String args[]) {
            Pair <Sock, Sock> pairOfSocks;
            Pair <Man, Woman> churchMarriedCouple;
            Pair <Man, Man> civilPartners;
        }
    }
    

    Παραμετρικοί τύποι στη Java

    Παραμετρικοί τύποι μπαλαντέρ

    Παράδειγμα γενίκευσης

    
    class LinkedList <E> {
        /** Node's value */
        private E value;
        /** Next node */
        private LinkedList <E> next;
    
        /** Construct a list with a single element v */
        LinkedList(final E v) {
            value = v;
            next = null;
        }
    
        /** Return a list with element n added to it */
        public LinkedList <E> add(final E v) {
            var n = new LinkedList <E>(v);
            n.next = this;
            return n;
        }
    
        /** Return a string representation of the list */
        @Override
        public String toString() {
            final String me = value.toString();
    
            /* Recursive implementation */
            if (next == null)
                return me;
            else
                return me + " -> " + next;
        }
    
        /** Test harness */
        static public void main(String args[]) {
            var ilst = new LinkedList <Integer>(0);
    
            ilst = ilst.add(1);
            ilst = ilst.add(18);
            ilst = ilst.add(45);
    
            for (int i = 0; i < 5; i++)
                ilst = ilst.add(i * 10);
            System.out.println(ilst);
        }
    }
    

    Παράδειγμα υπερφόρτωσης μεθόδων

    
    double
    square(final double x)
    {
      return x * x;
    }
    
    Complex
    square(final Complex x)
    {
      return new Complex(
        square(x.real) + square(x.imaginary),
        2 * x.real + x.imaginary);
    }
    

    Ανακεφαλαίωση πολυμορφισμού

    Έχουμε στο σημείο αυτό εξετάσει όλα τα είδη πολυμορφισμού (polymorphism):

    Χρήση πολυμορφισμού

    Σε συνηθισμένες εφαρμογές σχεδιάζουμε συχνά με κληρονομικότητα διεπαφών, ενώ συναντάμε:

    Διάγραμμα πολυμορφισμού

    polymorpism types

    Νήματα

    Νήματα: προβλήματα

    Όταν υλοποιούμε κώδικα με νήματα δημιουργούνται συχνά προβλήματα συγχρονισμού που πρέπει να αντιμετωπίσουμε. Τα στοιχεία αυτά δεν καλύπτονται στο συγκεκριμένο μάθημα.
  • Αδιέξοδο

    ="Παράδειγμα"

    Νήματα: εναλλακτικές

    Αντί για νήματα μπορούμε συχνά να χρησιμοποιήσουμε

    Ορισμός νήματος στη Java

    Χρήση νήματος στη Java

    Παράδειγμα χρήσης νημάτων

    
    public class CocktailGuest implements Runnable {
        /** What the guest will say */
        private final String mumble;
        /** How many seconds will he/she pause before speaking */
        private final int pause;
        /** How long the guest will stay */
        private final int stay;
        /** How long the guest has stayed */
        private int hereFor;
    
        /** Constructor */
        public CocktailGuest(String mumble, int pause, int stay) {
            this.mumble = mumble;
            this.pause = pause;
            this.stay = stay;
            hereFor = 0;
        }
    
        /** Execution method */
        @Override
        public void run() {
            try {
                while (hereFor < stay) {
                    Thread.sleep(pause * 1000);
                    hereFor += pause;
                    System.out.println(mumble);
                }
            } catch (InterruptedException e) {
                System.out.println("Something has come up; got to go.");
                return;
            } finally {
                System.out.println("Good bye.");
            }
        }
    
        public static void main(String args[]) {
            final int NGUEST = 5;
            var guest = new CocktailGuest[NGUEST];
            var thread = new Thread[NGUEST];
    
            int i = 0;
            guest[i++] = new CocktailGuest("Can I have another drink?", 8, 30);
            guest[i++] = new CocktailGuest("Nice food!", 7, 120);
            guest[i++] = new CocktailGuest("Ha ha ha...", 3, 100);
            guest[i++] = new CocktailGuest("Hi, I am Maria.", 5, 60);
            guest[i++] = new CocktailGuest("Hello, I am Petros.", 15, 60);
    
            // Create the threads
            for (i = 0; i < NGUEST; i++)
                thread[i] = new Thread(guest[i]);
            // Start the threads
            for (i = 0; i < NGUEST; i++)
                thread[i].start();
        }
    }
    

    Άσκηση: χρήση παραμετρικών τύπων και νήματα

    Άσκηση 12

    Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

    Βιβλιογραφία

    Δημιουργία γραφικών εφαρμογών

    Στοιχεία της εφαρμογής

    Οι εφαρμογές μπορούν διαχωριστούν ανάλογα με την μέθοδο διεπαφής με τον χρήστη σε

    Συστατικά εισαγωγής δεδομένων

    Συστατικά εμφάνισης δεδομένων

    Επίδειξη συστατικών

    Κατεβάστε και τρέξτε το πρόγραμμα SwingSet2.jar.

    Προγραμματιστική διεπαφή συστατικών

    Παράθυρο (javax.swing.JFrame, Κλάση)

    Παράδειγμα: ένα κενό παράθυρο

    Το παρακάτω παράδειγμα δημιουργεί ένα κενό παράθυρο, θέτει ως τίτλο το αλφαριθμητικό "Hello, World!" και το εμφανίζει.

    import javax.swing.JFrame;
    
    public class Window {
        public static void main(String[] args) {
            JFrame jf = new JFrame("Hello, World!");
            
            jf.setBounds(0, 0, 800, 600);
            // Remember, the method show() is deprecated
            jf.setVisible(true);
        }
    }
    

    Προσαρμογή στο τοπικό περιβάλλον

    Μπορούμε να δώσουμε στην εφαρμογή την αίσθηση εφαρμογής φτιαγμένης ειδικά για το λειτουργικό περιβάλλον στο οποίο εκτελείται με τον παρακάτω κώδικα.
    try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
        e.printStackTrace();
    }
    

    Προγραμματιστική διεπαφή συμβάντων

    Κουμπιά (javax.swing.JButton)

    Διαχειριστές διάταξης

    Οι διαχειριστές διάταξης (layout managers) είναι αόρατα συστατικά που καθορίζουν δυναμικά την τοποθέτηση των ορατών συστατικών (πχ κουμπιά, πίνακες) στην εφαρμογή. Οι κύριοι διαχειριστές διάταξης είναι:

    Προγραμματιστική διεπαφή διάταξης FlowLayout

    FlowLayout (java.awt.FlowLayout)

    Παράδειγμα διάταξης FlowLayout

    java.awt.FlowLayout
    import javax.swing.JFrame;
    import javax.swing.JButton;
    
    import java.awt.FlowLayout;
    
    public class FlowLayoutDemo {
        public static void main(String[] args) {
            JFrame jf = new JFrame("Hello, World!");
            
            jf.setBounds(0, 0, 800, 600);
            
            jf.setLayout(new FlowLayout());
            jf.add(new JButton("button 1"));
            jf.add(new JButton("button 2"));
            jf.add(new JButton("button 3"));
            
            // Remember, the method show() is deprecated
            jf.setVisible(true);
        }
    }
    

    Αποτέλεσμα διάταξης FlowLayout

    Προγραμματιστική διεπαφή διάταξης BorderLayout

    BorderLayout (java.awt.BorderLayout)

    Παράδειγμα διάταξης BorderLayout

    java.awt.BorderLayout
    import javax.swing.JFrame;
    import javax.swing.JButton;
    
    import java.awt.BorderLayout;
    
    public class BorderLayoutDemo {
        public static void main(String[] args) {
            JFrame jf = new JFrame("Hello, World!");
            
            jf.setBounds(0, 0, 800, 600);
            
            jf.setLayout(new BorderLayout());
            jf.add(new JButton("north"), BorderLayout.NORTH);
            jf.add(new JButton("south"), BorderLayout.SOUTH);
            jf.add(new JButton("center"), BorderLayout.CENTER);
            jf.add(new JButton("west"), BorderLayout.WEST);
            jf.add(new JButton("east"), BorderLayout.EAST);
            
            // Remember, the method show() is deprecated
            jf.setVisible(true);
        }
    }
    

    Αποτέλεσμα διάταξης BorderLayout

    Προγραμματιστική διεπαφή διάταξης GridLayout

    GridLayout (java.awt.GridLayout)

    Παράδειγμα διάταξης GridLayout

    java.awt.GridLayout
    import javax.swing.JFrame;
    import javax.swing.JButton;
    
    import java.awt.GridLayout;
    
    public class GridLayoutDemo {
        public static void main(String[] args) {
            JFrame jf = new JFrame("Hello, World!");
            
            jf.setBounds(0, 0, 800, 600);
            
            jf.setLayout(new GridLayout(3, 2));
            jf.add(new JButton("(1, 1)"));
            jf.add(new JButton("(1, 2)"));
            jf.add(new JButton("(2, 1)"));
            jf.add(new JButton("(2, 2)"));
            jf.add(new JButton("(3, 1)"));
            jf.add(new JButton("(3, 2)"));
            
            // Remember, the method show() is deprecated
            jf.setVisible(true);
        }
    }
    

    Αποτέλεσμα διάταξης GridLayout

    Προγραμματισμός με συμβάντα

    Η διαδραστικότητα στις εφαρμογές καθορίζεται από προκαθορισμένα συμβάντα. Η νοοτροπία τους είναι πολύ απλή:
    1. Επιλέγεται ένα γεγονός στο οποίο θέλουμε να επέμβουμε (πάτημα ένος πλήκτρου κτλ)
    2. Υλοποιόντας την κατάλληλη διεπαφή, γράφουμε το κομμάτι κώδικα που θέλουμε να εκτελεστεί για το συγκεκριμένο γεγονός
    3. Συσχετίζουμε το κομμάτι αυτό κώδικα με τη λίστα γεγονότων του συστατικού
    Τα γεγονότα είναι προκαθορισμένα και αφορούν είσοδο από το πληκτρολόγιο ή το ποντίκι, μετακινήσεις ή διαφοροποίηση του μεγέθους παραθύρων κτλ. Συνήθως οι κλάσεις που τα υλοποιούν βρίσκονται στο πακέτο java.awt.event.*.

    Παράδειγμα προγραμματισμού με συμβάντα

    import javax.swing.JFrame;
    import javax.swing.JButton;
    import javax.swing.JOptionPane;
    
    import java.awt.BorderLayout;
    
    import java.awt.event.ActionListener;
    import java.awt.event.ActionEvent;
    
    public class EventDemo {
        class AlertAction implements ActionListener {
            private JFrame parent;
    
            AlertAction(JFrame parent) {
                this.parent = parent;
            }
    
            @Override public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(parent, "information", "Button Pressed!!", JOptionPane.INFORMATION_MESSAGE);
            }
        }
    
        public EventDemo() {
            JFrame jf = new JFrame("Hello, World!");
            JButton jb = new JButton("Click Me!");
    
            jf.setBounds(0, 0, 800, 600);
    
            jf.setLayout(new BorderLayout());
            jf.add(jb, BorderLayout.CENTER);
    
            jb.addActionListener(new AlertAction(jf));
    
            // Remember, the method show() is deprecated
            jf.setVisible(true);
        }
    
        public static void main(String[] args) {
            new EventDemo();
        }
    }
    

    Αποτέλεσμα προγραμματισμού με συμβάντα

    Συντεταγμένες γραφικών

    Συντεταγμένες γραφικών (διάγραμμα)

    Κλάση προγραμματιστικής διεπαφής χαμηλού επιπέδου

    java.awt.Graphics

    Μέθοδοι χαμηλού επιπέδου

    Παράδειγμα: Σχεδίαση κειμένου

    Όλες οι συναρτήσεις χαμηλού επιπέδου υλοποιούνται στην κλάση java.awt.Graphics. Η κλάση java.awt.Font διαθέτει κατασκευαστή που δέχεται 3 παραμέτρους:

    Κώδικας: Σχεδίαση κειμένου

    import javax.swing.JFrame;
    import javax.swing.JComponent;
    
    import java.awt.BorderLayout;
    import java.awt.Graphics;
    import java.awt.Font;
    
    public class TextDemo {
        class GraphicPane extends JComponent {
            public GraphicPane() {
                super();
            }
        
            @Override public void paint(Graphics g) {
                g.setFont(new Font(Font.SANS_SERIF, Font.ITALIC, 14));
                g.drawString("Hello, World!", 30, 30);
            }
        }
        
        public TextDemo() {
            JFrame jf = new JFrame("Hello, World!");
            GraphicPane gp = new GraphicPane();
            
            jf.setBounds(0,0, 800, 600);
            jf.setLayout(new BorderLayout());        
            jf.add(gp, BorderLayout.CENTER);
            
            // Remember, the method show() is deprecated
            jf.setVisible(true);
        }
    
        public static void main(String[] args) {
            new TextDemo();
        }
    }
    

    Αποτέλεσμα: Σχεδίαση κειμένου

    Παράδειγμα: Χειρισμός χρωμάτων

    Ο χειρισμός των χρωμάτων γίνεται μέσω της κλάσης java.awt.Color.
    import javax.swing.JFrame;
    import javax.swing.JComponent;
    
    import java.awt.BorderLayout;
    import java.awt.Graphics;
    import java.awt.Font;
    import java.awt.Color;
    
    public class ColorDemo {
        class GraphicPane extends JComponent {
            public GraphicPane() {
                super();
            }
        
            @Override public void paint(Graphics g) {
                g.setFont(new Font(Font.SANS_SERIF, Font.ITALIC, 14));
                g.setColor(Color.ORANGE);
                g.drawString("Hello, World! (orange)", 30, 30);
                g.setColor(new Color(250, 100, 120));
                g.drawString("Hello, World! (red ... almost)", 80, 80);
    
            }
        }
        
        public ColorDemo() {
            JFrame jf = new JFrame("Hello, World!");
            GraphicPane gp = new GraphicPane();
            
            jf.setBounds(0,0, 800, 600);
            jf.setLayout(new BorderLayout());        
            jf.add(gp, BorderLayout.CENTER);
            
            // Remember, the method show() is deprecated
            jf.setVisible(true);
        }
    
        public static void main(String[] args) {
            new ColorDemo();
        }
    }
    

    Αποτέλεσμα: Χειρισμός χρωμάτων

    Παράδειγμα: Σχεδίαση σχημάτων

    Κώδικας: Σχεδίαση σχημάτων

    import javax.swing.JFrame;
    import javax.swing.JComponent;
    
    import java.awt.BorderLayout;
    import java.awt.Graphics;
    import java.awt.Font;
    import java.awt.Color;
    
    public class ShapeDemo {
        class GraphicPane extends JComponent {
            public GraphicPane() {
                super();
            }
    
            @Override public void paint(Graphics g) {
                //// line
                g.setColor(Color.BLACK);
                // drawLine(int x1, int y1, int x2, int y2)
                g.drawLine(0, 0, 100, 100);
    
                //// ovals
                g.setColor(new Color(250, 100, 120));
                // drawOval(int x, int y, int width, int height)
                g.drawOval(30, 30, 100, 200);
                // same, but it fills the oval with the current color
                g.fillOval(300, 30, 100, 200);
    
                //// Rectangle
                g.setColor(Color.BLUE);
                // drawRect(int x, int y, int width, int height)
                g.drawRect(30, 300, 100, 200);
                // fillRect(int x, int y, int width, int height)
                g.fillRect(300, 300, 100, 200);
            }
        }
    
        public ShapeDemo() {
            JFrame jf = new JFrame("Hello, World!");
            GraphicPane gp = new GraphicPane();
    
            jf.setBounds(0,0, 800, 600);
            jf.setLayout(new BorderLayout());
            jf.add(gp, BorderLayout.CENTER);
    
            // Remember, the method show() is deprecated
            jf.setVisible(true);
        }
    
        public static void main(String[] args) {
            new ShapeDemo();
        }
    }
    

    Αποτέλεσμα: Σχεδίαση σχημάτων

    Παράδειγμα: Αρχεία εικόνων

    Η βιβλιοθήκες που παρέχονται μαζί με το περιβάλλον ανάπτυξης της Java, υποστηρίζουν την επεξεργασία εικόνων μέσω των πακέτων java.awt.image.* και javax.imageio.*.
    import javax.swing.JFrame;
    import javax.swing.JComponent;
    
    import javax.imageio.ImageIO;
    
    import java.io.File;
    import java.io.IOException;
    
    import java.awt.BorderLayout;
    import java.awt.Graphics;
    
    import java.awt.image.BufferedImage;
    
    public class ImageDemo {
        class GraphicPane extends JComponent {
            private BufferedImage bi;
            private JFrame parent;
    
            public GraphicPane(JFrame parent) {
                this.parent = parent;
                try {
                    // reads a file
                    this.bi = ImageIO.read(new File("planes.jpg"));
                } catch (IOException ioe) {
                    System.err.println("Could not load image");
                }
            }
    
            @Override public void paint(Graphics g) {
                // drawImage(Image img, int x, int y, ImageObserver observer)
                g.drawImage(bi, 0, 0, parent);
            }
        }
    
        public ImageDemo() {
            JFrame jf = new JFrame("Hello, World!");
            GraphicPane gp = new GraphicPane(jf);
    
            jf.setBounds(0,0, 800, 600);
            jf.setLayout(new BorderLayout());
            jf.add(gp, BorderLayout.CENTER);
    
            jf.setVisible(true);
        }
    
        public static void main(String[] args) {
            new ImageDemo();
        }
    }
    

    Αποτέλεσμα: Αρχεία εικόνων

    Άσκηση: Μία απλή γραφική εφαρμογή

    Άσκηση 9

    Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

    Βιβλιογραφία

    Ευχαριστίες

    Ευχαριστίες στο Βασίλη Καρακόιδα για την καθοριστική συνεισφορά του στη συγγραφή της ενότητας αυτής των σημειώσεων.

    Δομές δεδομένων

    Συμβολοσειρές

    Συμβολοσειρές: παράδειγμα

    class Book {
        public String toString() { return "Book"; }
        static public void main(String args[]) {
            var b = new Book();
            String k = "*" + b + "*";
            System.out.println(k);
            System.out.println(b);
        }
    }
    

    Συμβολοσειρές πολλαπλών γραμμών

    Μπορούμε να παραστήσουμε συμβολοσειρές πολλαπλών γραμμών με τριπλά εισαγωγικά.
    
    String html = """
        <html>
            <body>
                <h1>Welcome to my page</h1>
                <p>This is a paragraph.</p>
            </body>
        </html>
        """;
    

    String: μέθοδοι κατασκευής

    String()
    Κατασκευάζει μια άδεια συμβολοσειρά.
    String(char[] value)
    Κατασκευάζει μια συμβολοσειρά από τον πίνακα value.
    String(char[] value, int offset, int count)
    Κατασκευάζει μια συμβολοσειρά από count στοιχεία του πίνακα value αρχίζοντας από τη θέση offset.
    String(String original)
    Κατασκευάζει ένα αντίγραφο συμβολοσειράς
    String(StringBuffer buffer)
    Κατασκευάζει μια συμβολοσειρά από ένα αντικείμενο StringBuffer

    String: μέθοδοι επεξεργασίας

    Οι θέσεις σε μια συμβολοσειρά αριθμούνται από το 0.
    h e l l o
    0 1 2 3 4
    Η μη ύπαρξη θέσης συμβολίζεται με το -1.
    String substring(int beginIndex)
    Επιστρέφει το τμήμα που αρχίζει στη θέση beginIndex
    String substring(int beginIndex, int endIndex)
    Επιστρέφει το τμήμα που αρχίζει στη θέση beginIndex και τελειώνει στη θέση endIndex - 1
    char charAt(int index)
    Επιστρέφει το χαρακτήρα στη θέση index
    String concat(String string2)
    Επιστρέφει τη συμβολοσειρά ενωμένη με το string2

    String: μέθοδοι ερωτήσεων

    int length()
    Μήκος
    boolean equals(String string2)
    Σύγκριση
    boolean StartsWith(String string2)
    Σύγκριση αρχής
    boolean endsWith(String string2)
    Σύγκριση τέλους
    int compareTo(String string2)
    Λεξικογραφική σύγκριση (απλή)
    int indexOf(String string2)
    Επιστρέφει τη θέση της συμβολοσειράς string2

    String: μέθοδοι μετατροπής

    static String valueOf(int i)
    Μετατρέπει το όρισμα i σε συμβολοσειρά
    static String valueOf(double d)
    Μετατρέπει το όρισμα d σε συμβολοσειρά
    static String valueOf(boolean b)
    Μετατρέπει το όρισμα b σε συμβολοσειρά
    static String valueOf(long l)
    Μετατρέπει το όρισμα l σε συμβολοσειρά
    static String valueOf(float f)
    Μετατρέπει το όρισμα f σε συμβολοσειρά
    static String valueOf(char c)
    Μετατρέπει το όρισμα c σε συμβολοσειρά

    StringBuffer και StringBuilder

    StringBuffer append(String string2)
    Προσθήκη της συμβολοσειράς string2 στο τέλος
    StringBuffer insert(int offset, String string2)
    Προσθήκη της συμβολοσειράς string2 στη θέση offset
    StringBuffer delete(int start, int end)
    Διαγραφή των χαρακτήρων από τη θέση start μέχρι την end - 1
    StringBuffer replace(int start, int end, String string2)
    Αντικατάσταση των χαρακτήρων από τη θέση start μέχρι την end - 1 με τη συμβολοσειρά string2

    Εσωτερική χρήση της StringBuilder

    Η κλάση StringBuilder παρέχει τις ίδιες δυνατότητες με την StringBuffer, χωρίς όμως να παρέχει ασφάλεια σε πολυνηματική επεξεργασία.

    Η κλάση StringBuilder χρησιμοποιείται και από το μεταγλωττιστή για την υλοποίηση ένωσης συμβολοσειρών. Η ακολουθία

    x = "a" + 4 + "c"
    
    μεταγλωττίζεται εσωτερικά σε
    x = new StringBuilder().append("a").append(4).append("c").toString()
    

    Πλαίσια συλλογών

    Πλεονεκτήματα

    Τα πλεονεκτήματα της υποστήριξης και του προγραμματισμού με βάση ένα πλαίσιο συλλογών είναι:

    Το πλαίσιο συλλογών της Java

    Το πλαίσιο συλλογών της βιβλιοθήκης της Java περιλαμβάνει:

    Διεπαφές συλλογών

    Υλοποιήσεις συλλογών

    Διαθέσιμες υλοποιήσεις στη Java

    Για τις διεπαφές των συλλογών υπάρχουν οι παρακάτω υλοποιήσεις:

    Set:
    HashSet, TreeSet, LinkedHashSet
    SortedSet:
    TreeSet
    List:
    ArrayList, LinkedList
    Map:
    HashMap, TreeMap, LinkedHashMap
    SortedMap:
    TreeMap

    Πίνακας διεπαφών και υλοποιήσεων

      Υλοποιήσεις
    ΠΚΠίνακας ΙΔΣΛ ΣΛ και ΠΚ
    Διεπαφές SetHashSet   TreeSet   LinkedHashSet
    SortedSet    TreeSet    
    List   ArrayList   LinkedList  
    Map HashMap   TreeMap   LinkedHashMap
    SortedMap     TreeMap    
    (Οι υλοποιήσεις που συνδιάζουν συνδεδεμένη λίστα και πίνακα κατακερματισμού επιτρέπουν την πρόσβαση των στοιχείων με τη σειρά που έγινε η εισαγωγή τους.)

    Διάγραμμα UML

    Η δομή των διεπαφών και κλάσεων που έχουμε εξετάσει μπορεί να παρασταθεί σε μορφή UML ως εξής.
    UML diagram of Java's Collection and Maps
    Σημείωση: στην πράξη η υλοποίηση της Java χρησιμοποιεί και άλλες ενδιάμεσες κλάσεις, όπως AbstractCollection, AbstractSequentialList, AbstractSet.

    Collection: επεξεργασία

    Η γενικευμένη διεπαφή

    Collection <E>
    
    ορίζει μεταξύ άλλων τις παρακάτω μεθόδους (κατά περίπτωση επιστρέφουν αληθές αν η συλλογή μεταβλήθηκε):

    void clear()
    Αφαιρεί όλα τα αντικείμενα από τη συλλογή
    boolean add(E o)
    Προσθήκη στοιχείου
    boolean addAll(Collection <? extends E> c)
    Προσθήκη συλλογής
    boolean remove(Object o)
    Αφαίρεση στοιχείου
    boolean removeAll(Collection <?> c)
    Αφαίρεση συλλογής

    Collection: ερωτήσεις

    boolean contains(Object o)
    Επιστρέφει αληθές αν το στοιχείο περιέχεται
    boolean containsAll(Collection <?> c)
    Επιστρέφει αληθές αν τα στοιχεία της συλλογής περιέχονται
    Iterator <E> iterator()
    Επιστρέφει έναν επαναλήπτη για διάσχιση της συλλογής
    boolean isEmpty()
    Επιστρέφει αληθές αν η συλλογή είναι άδεια
    int size()
    Επιστρέφει τον αριθμό των στοιχείων στη συλλογή

    Παράδειγμα της διεπαφής Collection

    import java.util.Collection;
    import java.util.LinkedList;
    
    public class CollectionTest <E> {
        static <E> void testContain(Collection <E> c, E o) {
            System.out.print("The collection " + c);
            if (c.contains(o))
                System.out.print(" contains");
            else
                System.out.print(" does not contain");
    
            System.out.println(" the object " + o);
        }
    
        public static void main(String args[]) {
            var list = new LinkedList <String>();
    
            list.add("Petros");
            list.add("Maria");
    
            testContain(list, "Maria");
            testContain(list, "John");
            testContain(list, "Petros");
            System.out.println("Number of elements = " + list.size());
        }
    }
    

    Η διεπαφή Iterator

    Η διεπαφή
    Iterator <E>
    
    υποστηρίζει τη διάσχιση και μεταβολή συλλογών. Ορίζει τις παρακάτω μεθόδους:
    boolean hasNext()
    Επιστρέφει αληθές αν υπάρχει επόμενο στοιχείο
    Object next()
    Επιστρέφει το επόμενο στοιχείο
    void remove()
    Διαγράφει το τελευταίο στοιχείο που επιστρέφτηκε

    Η διεπαφή ListIterator

    Η διεπαφή ListIterator επεκτείνει την Iterator με τις παρακάτω μεθόδους:
    boolean hasPrevious()
    Επιστρέφει αληθές αν υπάρχει προηγούμενο στοιχείο
    Object previous()
    Επιστρέφει το προηγούμενο στοιχείο
    void add(Object o)
    Προσθέτει ένα στοιχείο
    void set(Object o)
    Αντικαθιστά το τελευταίο στοιχείο που επιστρέφτηκε

    Παράδειγμα της διεπαφής Iterator

    import java.util.*;
    
    public class IteratorTest {
    
        static void fill(Collection <String> c) {
            c.add("Kerkyra");
            c.add("Zakynthos");
            c.add("Kythira");
            c.add("Santorini");
            c.add("Dilos");
            c.add("Samos");
            c.add("Rodos");
            c.add("Kastelorizo");
        }
    
        static void printAll(Collection <?> c) {
            for (var i = c.iterator(); i.hasNext(); )
                System.out.print(i.next() + " ");
        }
    
        public static void main(String args[]) {
            var hash = new HashSet<String> ();
            var list = new LinkedList<String> ();
    
            fill(hash);
            fill(list);
    
            System.out.println("Hash contains:");
            printAll(hash);
            System.out.println("\nList contains:");
            printAll(list);
        }
    }
    

    Διάσχιση δομών με την εντολή foreach

    Παραδείγματα foreach

    Παράδειγμα διάσχισης συλλογής:
    static void printAll(Collection <?> c) {
        for (Object o : c)
            System.out.print(o + " ");
    }
    
    Παράδειγμα διάσχισης πίνακα:
    class Echo {
        public static void main(String args[]) {
            for (var s : args)
                System.out.print(s + " ");
            System.out.println();
        }
    }
    

    Παράδειγμα: διάσχιση της ακολουθίας Fibonacci

    import java.util.Iterator;
    import java.math.BigInteger;
    
    /**
     * An Iterable interface over the Fibonacci sequence.
     * @author Diomidis Spinellis
     */
    class FibonacciSequence implements Iterable<BigInteger> {
    
        /** The iterator over the Fibonacci sequence. */
        private class  FibonacciIterator implements Iterator<BigInteger> {
            /** Integer n-2 of the series. */
            private BigInteger n0 = null;
            /** Integer n-1 of the series. */
            private BigInteger n1 = null;
    
            /**
             * Return true.
             * The FibonacciSequence sequence is infinite.
             */
            public boolean hasNext() { return true; }
    
            /** Return the next FibonacciSequence integer. */
            public BigInteger next() {
                if (n0 == null) {
                    n0 = BigInteger.ZERO;
                    return n0;
                } else if (n1 == null) {
                    n1 = BigInteger.ONE;
                    return n1;
                } else {
                    BigInteger r = n0.add(n1);
                    n0 = n1;
                    n1 = r;
                    return r;
                }
            }
    
            /**
             * Remove an element.
             * Nothing to see here; move on.
             */
            public void remove() {
                throw new UnsupportedOperationException();
            }
        }
    
        /** Return an iterator for the FibonacciSequence series. */
        public Iterator<BigInteger> iterator() {
            return new FibonacciIterator();
        }
    
        /** A simple test harness. */
        public static void main(String argv[]) {
            var fib = new FibonacciSequence();
    
            for (BigInteger i : fib)
                System.out.println(i);
        }
    }
    
    Βλέπε και το βίντεο για την εμφάνιση της ακολουθίας στη φύση (http://www.youtube.com/watch?v=kkGeOWYOFoA).

    Η διεπαφή Map

    Η διεπαφή
    Map <K, V>
    
    ορίζει μια απεικόνιση από ένα κλειδί (key) K σε μια τιμή (value) V. Η διεπαφή ορίζει μεταξύ άλλων τις παρακάτω μεθόδους:
    void clear()
    Αφαιρεί όλα τα αντικείμενα από τη συλλογή
    Object put(Object key, Object value)
    Προσθήκη στοιχείου (επιστρέφει την προηγούμενη τιμή ή null)
    void putAll(Map <? extends K, ? extends V> m)
    Προσθήκη στοιχείων
    boolean remove(Object key)
    Αφαίρεση στοιχείου (επιστρέφει την προηγούμενη τιμή ή null)

    Ερωτήσεις διεπαφής Map

    V get(Object key)
    Επιστρέφει την τιμή του στοιχείου με το κλειδί key
    boolean containsKey(Object key)
    Επιστρέφει αληθές αν το στοιχείο με το κλειδί key περιέχεται
    boolean containsValue(Object value)
    Επιστρέφει αληθές αν το στοιχείο με την τιμή value περιέχεται (αργή)
    Set<K> keySet()
    Επιστρέφει το σύνολο των κλειδιών
    Collection<V> values()
    Επιστρέφει μια συλλογή με τις αποθηκευμένες τιμές
    boolean isEmpty()
    Επιστρέφει αληθές αν η συλλογή είναι άδεια
    int size()
    Επιστρέφει τον αριθμό των στοιχείων στη συλλογή

    Παράδειγμα: νομισματικές ισοτιμίες

    import java.util.TreeMap;
    
    public class FXConvert {
    
        private static TreeMap<String, Double> FXRate = new TreeMap<String, Double>();
    
        static double FXconvert(String from, String to, double value) {
            double euro = value / FXRate.get(from);
            return euro * FXRate.get(to);
        }
    
        public static void main(String args[]) {
    
            // Euro rates
            FXRate.put("USD", 1.27);
            FXRate.put("JPY", 126.0);
            FXRate.put("GBP", 0.68);
            FXRate.put("CHF", 1.57);
            FXRate.put("CAD", 1.53);
            FXRate.put("SEK", 9.03);
    
            System.out.println("5 SEK = " + FXconvert("SEK", "JPY", 5) + " JPY");
            System.out.println("100 GBP = " + FXconvert("GBP", "CHF", 100) + " CHF");
        }
    }
    

    Η κλάση Stack

    Η κλάση
    Stack <E>
    
    υλοποιεί τη δομή δεδομένων που ονομάζεται στοίβα (stack) με το χαρακτηριστικό τύπο πρόσβασης τελευταίο μέσα πρώτο έξω (last in first out) (LIFO). H κλάση Stack υλοποιεί τη διεπαφή Collection και ορίζει τις παρακάτω μεθόδους:
    boolean empty()
    Αληθές αν η στοίβα είναι άδεια
    E push(E item)
    Προσθέτει το αντικείμενο item στην κορυφή της στοίβας
    E pop()
    Αφαιρεί και επιστρέφει το αντικείμενο από την κορυφή της στοίβας
    E peek()
    Επιστρέφει το αντικείμενο από την κορυφή της στοίβας

    οι πύργοι του Ανόι

    Μπορείτε να δοκιμάστε το παιγνίδι εδώ (https://www.mindgames.com/game/Tower+of+Hanoi).

    Παράδειγμα: οι πύργοι του Ανόι

    import java.util.Stack;
    import java.util.Iterator;
    import java.util.Collection;
    
    public class Hanoi {
        static Stack<Integer> A, B, C;
    
        /** Display the contents of a collection with a given name */
        static <E> void showCollection(String name, Collection <E> c) {
            System.out.print(name + ": ");
            for (E e : c)
                System.out.print(e + " ");
            System.out.println();
        }
    
        /** Display the hanoi towers */
        static void showConfiguration() {
            showCollection("A", A);
            showCollection("B", B);
            showCollection("C", C);
            System.out.println();
        }
    
        /** Move n blocks from to using tmp */
        static <E> void move(int n, Stack<E> from, Stack<E> to, Stack<E> tmp) {
            if (n == 1) {
                to.push(from.pop());
                showConfiguration();
            } else {
                move(n - 1, from, tmp, to);
                to.push(from.pop());
                showConfiguration();
                move(n - 1, tmp, to, from);
            }
        }
    
        public static void main(String args[]) {
            final int N = 64;
            A = new Stack<Integer>();
            B = new Stack<Integer>();
            C = new Stack<Integer>();
    
            for (int i = N; i > 0; i--)
                A.push(i);
            showConfiguration();
            move(N, A, C, B);
        }
    }
    

    Άσκηση: προγραμματισμός με συμβολοσειρές και συλλογές

    Άσκηση 7

    Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

    Βιβλιογραφία

    Χειρισμός αρχείων

    Επισκόπηση

    Δευτερεύουσα μνήμη

    Τα προγράμματα συχνά πρέπει να μεταφέρουν τα δεδομένα τους σε δευτερεύουσα μνήμη (μονάδα SSD, μαγνητικό δίσκο, CD/DVD, μνήμη USB, κάρτα μνήμης, ταινία). Οι λόγοι που το επιβάλλουν αυτό είναι οι παρακάτω:

    Η διαδικασία μεταφοράς των δεδομένων μεταξύ του προγράμματος και εξωτερικών συσκευών καλείται είσοδος/έξοδος (input/output) ή Ε/Ε (I/O).

    Παράσταση δεδομένων

    Τα δεδομένα σε ένα αρχείο μπορούμε να τα παραστήσουμε σε δύο μορφές.

    Παραδείγματα παράστασης

    ΤύποςΤιμήΔυαδική παράστασηΠαράσταση κειμένου
    int4200000000 00000000 00000000 0010101000110100 00110010
    short4200000000 0010101000110100 00110010
    chara00000000 0110000101100001
    charα00000011 1011000111001110 10110001
    Το κείμενο παριστάνεται με την κωδικοποίηση UTF-8.

    Παράσταση αριθμών κινητής υποδιαστολής

    ΤύποςΤιμήΔυαδική παράστασηΠαράσταση κειμένου
    double-0.12510111111 11000000 00000000 00000000
    00000000 00000000 00000000 00000000
    00101101
    00110000
    00101110
    00110001
    00110010
    00110101
    double 12.566370614359173 10-7 00111110 10110101 00010101 00110111
    00001111 10011001 11110110 11001011
    00110001
    00110010
    00101110
    00110101
    00110110
    00110110
    00110011
    00110111
    00110000
    00110110
    00110001
    00110100
    00110011
    00110101
    00111001
    00110001
    00110111
    00110011
    01100101
    00101101
    00110111
    (Ο τελευταίος αριθμός παριστάνει τη φυσική σταθερά μ0, τη διαπερατότητα του κενού, 4π 10-7. Το κείμενο παριστάνεται με την κωδικοποίηση UTF-8 και οι αριθμοί κινητής υποδιαστολής σύμφωνα με το πρότυπο IEEE 754-1985.)

    Ομαδοποίηση δεδομένων

    Η ομαδοποίηση στοιχείων μπορεί να γίνει:

    Παράδειγμα: ομαδοποίηση πεδίων σταθερού μήκους

    ΓΓΠΣ/ΑΑΔΕ: Αναλυτική γραμμή πωλήσεων (πελατών)
    ΠΙΝΑΚΑΣ 3. Αναλυτική γραμμή πωλήσεων (στοιχεία πελατών)
    (RECORD τύπου 2)
    ΠΕΡΙΓΡΑΦΗ
    ΠΕΔΙΟΥ
    ΘΕΣΕΙΣ
    ΧΑΡΑΚΤΗΡΙΣΤΙΚΑ ΠΕΔΙΟΥ
    Σημειώσεις
    ΣΤΑΘΕΡΗ
    ΤΙΜΗ
    ΑΠΟ
    ΕΩΣ
    ΜΗΚΟΣ
    ΤΥΠΟΣ
    1
    Τύπος Record (κωδικός)
    1
    1
    1
    Numeric
    KENO
    2
    2
    Α/Α
    2
    6
    5
    Numeric
    KENO
    KENO
    3
    ΑΦΜ πελάτη
    7
    15
    9
    Character
    KENO
    KENO
    4
    Επωνυμία πελάτη
    16
    42
    27
    Character
    KENO
    KENO
    5
    Επαγγελμα πελάτη
    43
    57
    15
    Character
    KENO
    KENO
    61
    Μη υπόχρεοι υποβολής(αγρότες, περιστασιακά απασχολούμενοι κλπ)
    58
    58
    1
    Character
    0 (μηδέν)= υπόχρεος
    1 (ένα) = μη υπόχρεος
    KENO
    7
    Δ/νση / Πόλη πελάτη
    59
    68
    10
    Character
    KENO
    KENO
    8
    Δ/νση / Οδός πελάτη
    69
    84
    16
    Character
    KENO
    KENO
    9
    Δ/νση / Αριθμ πελάτη
    85
    87
    3
    Character
    KENO
    KENO
    10
    Ταχ. Κώδικας πελάτη
    88
    92
    5
    Numeric
    KENO
    KENO
    113
    Αριθμός τιμολογίων (πλήθος)
    93
    99
    7
    Numeric
    KENO
    KENO
    12
    Καθαρή αξία τιμολογίων
    100
    115
    16
    Numeric
    KENO
    KENO
    13
    FILLER
    116
    150
    35
    Character
    KENO
    spaces

    Παράδειγμα: ομαδοποίηση πεδίων με διαχωριστικό

    Αρχείο /etc/passwd στο λειτουργικό σύστημα Unix

    root:*:0:0:Charlie Root:/root:/bin/csh
    dds:*:1000:1000:Diomidis Spinellis:/home/dds:/usr/local/bin/bash
    nutmon:*:1056:1056:NUT UPS monitor unprivileged user:/nonexistent:/usr/sbin/nologin
    sgrig:*:1001:1001:Stavros Grigorakakis:/home/sgrig:/usr/local/bin/bash
    archie:*:1002:1002:Achilleas Anagnostopoulos:/home/archie:/usr/local/bin/bash
    path:*:1003:1003:Stephanos Androutselis:/home/path:/usr/local/bin/bash
    

    Τιμοκατάλογος της Microsoft (CSV)

    Product Description,1st AP Non-Platform,1st AP Platform,2nd AP Non-Platform,2nd AP Platform,3rd AP Non-Platform,3rd AP Platform,Non-Platform,Platform,,,,,,,
    OFFICE FAMILY,,,,,,,,,,
    Office Enterprise Listed Lic/SA Pack MVL,76J-01468,76J-01637, 190.31 , 161.77 , 190.31 , 161.77 , 190.31 , 161.77 ,,
    Office Enterprise Listed SA MVL,76J-01552,76J-01640, 98.96 , 94.02 , 98.96 , 94.02 , 98.96 , 94.02 ,,
    Office Enterprise Listed SA Step Up MVL from Office Pro,76J-01510,76J-00002, 34.51 , 29.33 , 34.51 , 29.33 , 34.51 , 29.33 ,,,,,,,
    Office Professional Plus Listed Lic/SA Pack MVL,269-05924,269-12441, 155.81 , 132.45 , 155.81 , 132.45 , 155.81 , 132.45 ,,,,,,,
    Office Professional Plus Listed SA MVL,269-05925,269-12444, 81.02 , 76.97 , 81.02 , 76.97 , 81.02 , 76.97 ,,,,,,,
    WINDOWS FAMILY,,,,,,,,,,,,,,,
    Windows Vista Business Listed Upg/SA Pack MVL w/VisEnterprise,66J-00588,66J-00579, 48.01 , 40.81 , 48.01 , 40.81 , 48.01 , 40.81 ,,,,,,,
    Windows Vista Business Listed SA MVL w/VisEnterprise,66J-00844,66J-00582, 31.76 , 30.17 , 31.76 , 30.17 , 31.76 , 30.17 ,,,,,,,
    

    Ανάγνωση δυαδικών δεδομένων

    Αυτόματη αποδέσμευση πόρων

    Παράδειγμα: ανάγνωση byte

    import java.io.*;
    
    /**
     * Count and display the number of bytes in the specified file
     * @author Diomidis Spinellis
     */
    class ByteCount {
        public static void main(String args[]) {
    	if (args.length != 1) {
    	    System.err.println("Usage: ByteCount file");
    	    System.exit(1);
    	}
    
    	// Try with resources; will auto-close in
    	try (var in = new BufferedInputStream(new FileInputStream(args[0]))) {
    
                // Count bytes
                int count = 0;
    	    int b;
    	    while ((b = in.read()) != -1)
    		count++;
    
                System.out.println(count);
    	} catch (FileNotFoundException e) {
    	    System.err.println("Unable to open file " + args[0] + ": " + e.getMessage());
    	    System.exit(1);
    	} catch (IOException e) {
    	    System.err.println("Error reading byte: " + e.getMessage());
    	    System.exit(1);
    	}
    
        }
    }
    

    Εγγραφή δυαδικών δεδομένων

    Παράδειγμα: εγγραφή εικόνας

    import java.io.*;
    
    /**
     * Create a 256*256 24-bit color PNM RGB file containing all combinations
     * of R and G.
     * @author Diomidis Spinellis
     */
    class ColorWrite {
    
        /** Write the specified ASCII string to out as bytes */
        static void writeStringAsBytes(OutputStream out, String s) throws IOException {
            for (int i = 0; i < s.length(); i++)
                    out.write((byte)s.charAt(i));
        }
    
        public static void main(String args[]) {
    	final String fileName = args[0];
    
    	// Open file; try with resources
    	try (var out =
                    new BufferedOutputStream(new FileOutputStream(fileName))) {
                // NetPBM PPM 24-bit color file header
                // https://netpbm.sourceforge.net/doc/ppm.html
                writeStringAsBytes(out, "P6 256 256 255 ");
    	    for (int r = 0; r < 256; r++)
    		for (int g = 0; g < 256; g++) {
    		    out.write(r);
    		    out.write(g);
    		    out.write(0);
    		}
    	} catch (FileNotFoundException e) {
    	    System.err.println("Unable to open file " + fileName
    		+ ": " + e.getMessage());
    	    System.exit(1);
    	} catch (IOException e) {
    	    System.err.println("Error writing byte: " + e.getMessage());
    	    System.exit(1);
    	}
        }
    }
    

    Παράδειγμα: αρχείο PNG

    PNG file format

    Ανάγνωση χαρακτήρων

    Παρένθεση: κωδικοποίηση ελληνικών χαρακτήρων

    Στη Java μπορούμε να επεξεργαστούμε αρχεία με ελληνικούς χαρακτήρες με βάση τα παρακάτω ονόματα κωδικοποίησης της κλάσης Charset.

    Διαθέσιμες κωδικοποιήσεις

    Το παρακάτω πρόγραμμα τυπώνει όλες τις διαθέσιμες κωδικοποιήσεις.
    import java.nio.charset.Charset;
    import java.util.SortedMap;
    
    /**
     * List the available character set encodins.
     * @author Diomidis Spinellis
     */
    class ListCharset {
        public static void main(String args[]) {
            SortedMap<String,Charset> ac = Charset.availableCharsets();
    
            for (String k : ac.keySet())
                System.out.println(k);
        }
    }
    

    Παράδειγμα: κατηγοριοποίηση χαρακτήρων

    import java.io.*;
    import java.util.*;
    import java.lang.Character.UnicodeBlock;
    
    /**
     * Count and display for the specified input file
     * the number of characters contained in various Unicode blocks .
     * @author Diomidis Spinellis
     */
    class CharCount {
        public static void main(String args[]) {
    	if (args.length != 2) {
    	    System.err.println("Usage: CharCount file encoding");
    	    System.exit(1);
    	}
    
    	// Open file; try-with-resources
    	try (var in = new BufferedReader(new InputStreamReader(
                            new FileInputStream(args[0]), args[1]))) {
    
                // Count characters in blocks
                var count = new HashMap<Character.UnicodeBlock, Integer>();
    	    int c;
    	    while ((c = in.read()) != -1) {
    		var u = Character.UnicodeBlock.of(c);
    		    Integer oldN = count.get(u);
    		    if (oldN == null)
    			count.put(u, 1);
    		    else
    			count.put(u, oldN + 1);
    	    }
    
                // Display results
                for (var s : count.entrySet())
                    System.out.println(s.getKey() + ": " + s.getValue());
    	} catch (FileNotFoundException e) {
    	    System.err.println("Unable to open file " + args[0] + ": " + e.getMessage());
    	    System.exit(1);
    	} catch (UnsupportedEncodingException e) {
    	    System.err.println("Unsupported encoding " + args[1] + ": " + e.getMessage());
    	} catch (IOException e) {
    	    System.err.println("Error reading character: " + e.getMessage());
    	    System.exit(1);
    	}
    
        }
    }
    

    Εγγραφή χαρακτήρων

    E/E συμβολοσειρών, πινάκων· σωληνώσεις

    Είσοδο και έξοδο μπορούμε να πραγματοποιήσουμε επιπλέον μέσω:

    Σειριακοποίηση αντικειμένων

    Δόκιμες λύσεις φύλαξης αντικειμένων

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

    Ανακεφαλαίωση σειριακής πρόσβασης

    Ανάγνωση Εγγραφή
    byte FileInputStream FileOutputStream
    buffered byte BufferedInputStream BufferedOutputStream
    int/double/… DataInputStream DataOutputStream
    Object ObjectInputStream ObjectOutputStream
    char InputStreamReader OutputStreamWriter
    line(char) BufferedReader BufferedWriter
    PrintWriter

    Αρχεία τυχαίας πρόσβασης

    Η διεπαφή NIO

    H Java προσφέρει την διεπαφή προγραμματισμού (API) ΝΙΟ (New I/O) για πρόσβαση σε αρχεία όταν έχουμε ιδιαίτερα υψηλές απαιτήσεις απόδοσης. Σε σχέση με τη διεπαφή IO αυτή προσφέρει:

    Πρόσβαση στο σύστημα αρχείων

    Η κλάση File παρέχει πρόσβαση στη δομή με μεθόδους όπως τις παρακάτω:
    exists
    Ελέγχει την ύπαρξη ενός αρχείου.
    delete
    Διαγράφει ένα αρχείο.
    lastModified
    Επιστρέφει το χρόνο της τελευταίας αλλαγής στο αρχείο.
    renameTo
    Μετονομάζει ένα αρχείο
    length
    Επιστρέφει το μήκος ενός αρχείου
    list
    Επιστρέφει τα αρχεία που βρίσκονται σε ένα φάκελο.
    mkdir
    Δημιουργεί ένα νέο φάκελο
    getFreeSpace
    Επιστρέφει τον ελεύθερο χώρο στο δίσκο.

    Άσκηση: επεξεργασία αρχείου κειμένου

    Άσκηση 8

    Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

    Βιβλιογραφία

    Παράρτημα: Παράσταση ελληνικών χαρακτήρων

    ΧαρακτήραςUnicodeISO 8859-7CP 1253CP 737CP 851Mac GreekCP 423CP 869ISO IR-19ISO IR-27ISO IR-88ISO IR-18ISO IR-150ISO IR-55
    Ά0386b6a2ea86cd7186      
    Έ0388b8b8eb8dce728d      
    Ή0389b9b9ec8fd7738f      
    Ί038ababaed90d87590      
    Ϊ03aadada  ab 91      
    Ό038cbcbcee92d97692      
    Ύ038ebebeef95da7795      
    Ϋ03abdbdb  bd 96      
    Ώ038fbfbff098df7898      
    Α0391c1c180a4b041a461 41614141
    Β0392c2c281a5b542a562 42624242
    Γ0393c3c382a6a143a6672343674344
    Δ0394c4c483a7a244a7644044644445
    Ε0395c5c584a8b645a865 45654546
    Ζ0396c6c685a9b746a97a 467a4649
    Η0397c7c786aab847aa68 4768474a
    Θ0398c8c887aca348ac755c4875484b
    Ι0399c9c988adb949ad69 4969494c
    Κ039acaca89b5ba51b56b 4b6b4a4d
    Λ039bcbcb8ab6a452b66c5e4c6c4b4e
    Μ039ccccc8bb8bb53b76d 4d6d4c4f
    Ν039dcdcd8cb7c154b86e 4e6e4d50
    Ξ039ecece8dbda555bd6a214f6a4e51
    Ο039fcfcf8ebec356be6f 506f4f52
    Π03a0d0d08fc6a657c6703f51705053
    Ρ03a1d1d190c7c458c772 52725155
    Σ03a3d3d391cfaa59cf735f53735356
    Τ03a4d4d492d0c662d074 54745458
    Υ03a5d5d593d1cb63d179 55795559
    Φ03a6d6d694d2bc64d2665d5666565a
    Χ03a7d7d795d3cc65d378 5878575b
    Ψ03a8d8d896d4be66d4633a5963585c
    Ω03a9d9d997d5bf67d5765b5a76595d
    ά03acdcdce19bc0b19b      
    έ03addddde29ddbb29d      
    ή03aededee39edcb39e      
    ί03afdfdfe59fddb59f      
    ϊ03cafafae4a0fbb4a0      
    ΐ0390c0c0 a1fd a1      
    ό03ccfcfce6a2deb6a2      
    ύ03cdfdfde7a3e0b7a3      
    ϋ03cbfbfbe8fbfcb8fb      
    ΰ03b0e0e0 fcfe fc      
    ώ03cefefee9fdf1b9fd      
    α03b1e1e198d6e18ad6  61416161
    β03b2e2e299d7e28bd7  62426262
    γ03b3e3e39ad8e78cd8  63476364
    δ03b4e4e49bdde48ddd  64446465
    ε03b5e5e59cdee58ede  65456566
    ζ03b6e6e69de0fa8fe0  665a6669
    η03b7e7e79ee1e89ae1  6748676a
    θ03b8e8e89fe2f59be2  6855686b
    ι03b9e9e9a0e3e99ce3  6949696c
    κ03baeaeaa1e4eb9de4  6b4b6a6d
    λ03bbebeba2e5ec9ee5  6c4c6b6e
    μ03bcececa3e6ed9fe6  6d4d6c6f
    ν03bdededa4e7eeaae7  6e4e6d70
    ξ03beeeeea5e8eaabe8  6f4a6e71
    ο03bfefefa6e9eface9  704f6f72
    π03c0f0f0a7eaf0adea  71507073
    ρ03c1f1f1a8ebf2aeeb  72527175
    ς03c2f2f2aaedf7afed  77577277
    σ03c3f3f3a9ecf3baec  73537376
    τ03c4f4f4abeef4bbee  74547478
    υ03c5f5f5acf2f9bcf2  75597579
    φ03c6f6f6adf3e6bdf3  7646767a
    χ03c7f7f7aef4f8bef4  7858777b
    ψ03c8f8f8aff6e3bff6  7943787c
    ω03c9f9f9e0faf6dbfa  7a56797d

    Παράρτημα: το πρότυπο ASCII

    Ο παρακάτω πίνακας παρουσιάζει τις τιμές των χαρακτήρων, σύμφωνα με το πρότυπο ASCII (American Standard Code for Information Interchange). Οι πρώτες 32 θέσεις δεσμεύονται για χαρακτήρες διαφυγής (escape character).
    ΧαρακτήραςΔεκαδικήΔεκαεξαδικήΟκταδικήΔυαδική
    nul0000000000 0000
    soh1010010000 0001
    stx2020020000 0010
    etx3030030000 0011
    eot4040040000 0100
    enq5050050000 0101
    ack6060060000 0110
    bel7070070000 0111
    bs8080100000 1000
    ht9090110000 1001
    lf100a0120000 1010
    vt110b0130000 1011
    ff120c0140000 1100
    cr130d0150000 1101
    so140e0160000 1110
    si150f0170000 1111
    dle16100200001 0000
    dc117110210001 0001
    dc218120220001 0010
    dc319130230001 0011
    dc420140240001 0100
    nak21150250001 0101
    syn22160260001 0110
    etb23170270001 0111
    can24180300001 1000
    em25190310001 1001
    sub261a0320001 1010
    esc271b0330001 1011
    fs281c0340001 1100
    gs291d0350001 1101
    rs301e0360001 1110
    us311f0370001 1111
    sp32200400010 0000
    !33210410010 0001
    "34220420010 0010
    #35230430010 0011
    $36240440010 0100
    %37250450010 0101
    &38260460010 0110
    '39270470010 0111
    (40280500010 1000
    )41290510010 1001
    *422a0520010 1010
    +432b0530010 1011
    ,442c0540010 1100
    -452d0550010 1101
    .462e0560010 1110
    /472f0570010 1111
    048300600011 0000
    149310610011 0001
    250320620011 0010
    351330630011 0011
    452340640011 0100
    553350650011 0101
    654360660011 0110
    755370670011 0111
    856380700011 1000
    957390710011 1001
    :583a0720011 1010
    ;593b0730011 1011
    <603c0740011 1100
    =613d0750011 1101
    >623e0760011 1110
    ?633f0770011 1111
    @64401000100 0000
    A65411010100 0001
    B66421020100 0010
    C67431030100 0011
    D68441040100 0100
    E69451050100 0101
    F70461060100 0110
    G71471070100 0111
    H72481100100 1000
    I73491110100 1001
    J744a1120100 1010
    K754b1130100 1011
    L764c1140100 1100
    M774d1150100 1101
    N784e1160100 1110
    O794f1170100 1111
    P80501200101 0000
    Q81511210101 0001
    R82521220101 0010
    S83531230101 0011
    T84541240101 0100
    U85551250101 0101
    V86561260101 0110
    W87571270101 0111
    X88581300101 1000
    Y89591310101 1001
    Z905a1320101 1010
    [915b1330101 1011
    \925c1340101 1100
    ]935d1350101 1101
    ^945e1360101 1110
    _955f1370101 1111
    `96601400110 0000
    a97611410110 0001
    b98621420110 0010
    c99631430110 0011
    d100641440110 0100
    e101651450110 0101
    f102661460110 0110
    g103671470110 0111
    h104681500110 1000
    i105691510110 1001
    j1066a1520110 1010
    k1076b1530110 1011
    l1086c1540110 1100
    m1096d1550110 1101
    n1106e1560110 1110
    o1116f1570110 1111
    p112701600111 0000
    q113711610111 0001
    r114721620111 0010
    s115731630111 0011
    t116741640111 0100
    u117751650111 0101
    v118761660111 0110
    w119771670111 0111
    x120781700111 1000
    y121791710111 1001
    z1227a1720111 1010
    {1237b1730111 1011
    |1247c1740111 1100
    }1257d1750111 1101
    ~1267e1760111 1110
    del1277f1770111 1111

    Παράσταση δεδομένων με XML, JSON και κανονικές εκφράσεις

    Σύνταξη κανονικών εκφράσεων

    Σύμβολα με ειδικό νόημα

    Πρόσθετα σύμβολα με ειδικό νόημα

    Χαρακτήρες διαφυγής

    Πρόσθετοι χαρακτήρες διαφυγής

    Χρήση κανονικών εκφράσεων

    Παράδειγμα: Εύρεση κανονικών εκφράσεων σε αρχείο

    
    /*
     * Globally match regular expression and print
     * Modelled after the Unix command with the same name
     * D. Spinellis, January 2004-2024
     */
    
    import java.util.regex.*;
    import java.io.*;
    
    class Grep {
        public static void main(String args[]) {
            if (args.length != 2) {
                System.err.println("Usage: Grep pattern file");
                System.exit(1);
            }
    
            try (var in = new BufferedReader(new InputStreamReader(
                            new FileInputStream(args[1])))) {
                Pattern compiledRe = Pattern.compile(args[0]);
                String s;
                while ((s = in.readLine()) != null) {
                    Matcher m = compiledRe.matcher(s);
                    if (m.find())
                        System.out.println(s);
                }
            } catch (FileNotFoundException e) {
                System.err.println("Unable to open file " + args[1] + ": " + e.getMessage());
                System.exit(2);
            } catch (PatternSyntaxException e) {
                System.err.println("Invalid RE syntax: " + e.getDescription());
                System.exit(3);
            } catch (IOException e) {
                System.err.println("Error reading line: " + e.getMessage());
                System.exit(4);
            }
        }
    }
    

    Αποτέλεσμα αναζήτησης κανονικών εκφράσεων

    java Grep "abo" /usr/dict/words
    ...
    sabotage
    seaboard
    taboo
    thereabouts
    turnabout
    vagabond
    whereabout
    ...
    
    java Grep "^abo" /usr/dict/words
    aboard
    abode
    abolish
    abolition
    abominable
    abominate
    aboriginal
    
    java Grep bent /usr/dict/words
    absorbent
    bent
    benthic
    debenture
    incumbent
    recumbent
    
    java Grep "bent$" /usr/dict/words
    absorbent
    bent
    incumbent
    recumbent
    
    java Grep "[^AEIOUYaeiouy]{5,}" /usr/dict/words
    angstrom
    Armstrong
    birthplace
    bremsstrahlung
    corkscrew
    Dijkstra
    downstream
    hardscrabble
    jockstrap
    Knightsbridge
    lengthly
    Nietzsche
    nightclub
    offspring
    postscript
    Rothschild
    ...
    
    java Grep "(.)(.)(.)\3\2\1" /usr/dict/words
    braggart
    Brenner
    collocation
    diffident
    dissident
    glossolalia
    grammar
    grammarian
    installation
    staccato
    suffuse
    

    Διαίρεση συμβολοσειρών με πρότυπο

    Διαίρεση συμβολοσειρών με κανονική έκφραση

    Όταν τα τμήματα μιας συμβολοσειράς χωρίζονται από ίδια στοιχεία διαχωρισμού (π.χ. :, κενό, tab) τότε μπορούμε να τα διαχωρίσουμε με τη μέθοδο του αντικειμένου Pattern.
    
    import java.io.*;
    import java.util.regex.*;
    
    public class SplitWords {
        public static void main(String[] args) {
            if (args.length != 1) {
                System.err.println("Usage: SplitWords file");
                System.exit(1);
            }
    
            // Split on non-word characters
            Pattern splitPattern = Pattern.compile("[^a-zA-Z]+");
    
            try (var in = new BufferedReader(new InputStreamReader(
                            new FileInputStream(args[0])))) {
                String line;
                while ((line = in.readLine()) != null) {
                    String[] words = splitPattern.split(line);
                    for (String word : words) {
                        System.out.println(word);
                    }
                }
            } catch (FileNotFoundException e) {
                System.err.println("Unable to open file " + args[0] + ": " + e.getMessage());
                System.exit(2);
            } catch (IOException e) {
                System.err.println("Error reading line: " + e.getMessage());
                System.exit(3);
            }
        }
    }
    

    Παράδειγμα: επεξεργασία αρχείων καταγραφής πρόσβασης σε ιστοσελίδες

    
    /*
     * Collect and print Web statistics
     * D. Spinellis, 2004-2024
     */
    
    import java.util.*;
    import java.util.regex.*;
    import java.io.*;
    
    class WebStats {
    
        /**
         * Increment the integer value of map's member by 1
         * The member is obtained by using the matcher to extract
         * the specified group from the string s
         */
        static void increment(Map<String, Integer> map, String s, Matcher m, int group) {
    	String member = s.substring(m.start(group), m.end(group));
    	Integer i = map.get(member);
            map.put(member, i == null ? 1 : i + 1);
        }
    
        /** List the contents of the given map */
        static void list(String title, Map<String, Integer> map) {
    	System.out.println("\n" + title);
    	for (Map.Entry e : map.entrySet())
    	    System.out.println(e.getValue() + " " + e.getKey());
        }
    
        /** List the contents of the given map ordered by their values.
         * (You are not expected to undestand this).
         */
        static void sortedList(String title, Map<String, Integer> map) {
    	System.out.println("\n" + title);
    	var valueOrder = new TreeSet<Map.Entry<String, Integer>>(new
    	    Comparator<Map.Entry<String, Integer>>() {
    		public int compare(Map.Entry<String, Integer> a,
    			Map.Entry<String, Integer> b) {
    		    return (-a.getValue().compareTo(b.getValue()));
    		}
    	    }
    	);
    	valueOrder.addAll(map.entrySet());
    	for (Map.Entry e : valueOrder)
    	    System.out.println(e.getValue() + " " + e.getKey());
        }
    
    
    
        public static void main(String args[]) {
    	if (args.length != 1) {
    	    System.err.println("Usage: WebStats file");
    	    System.exit(1);
    	}
    
    	Pattern cre = null;	// Compiled RE
    	try {
    	    // A standard log line is a line like:
    	    // 192.168.136.16 - - [26/Jan/2004:19:45:48 +0200] "GET /c136.html HTTP/1.1" 200 1674 "http://office/c120.html" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5) Gecko/20031007"
    	    String patternString = """
                    ([-\\w.]+)\\s+      # 1. Host
                    ([-\\w]+)\\s+       # 2. Logname
                    ([-\\w]+)\\s+       # 3. User
                    \\[(\\d+)/          # 4. Date
                    (\\w+)/             # 5. Month
                    (\\d+):             # 6. Year
                    (\\d+):             # 7. Hour
                    (\\d+)              # 8. Minute
                    ([^]]+?)\\]\\s+     # 9. Rest of time
                    \"([-\\w]+)\\s*     # 10. Request verb
                    ([^\\s]*)           # 11. Request URL
                    ([^\"]*?)\"\\s+     # 12. Request protocol etc.
                    (\\d+)\\s+          # 13. Status
                    ([-\\d]+)\\s+       # 14. Bytes
                    \"([^\"]*)\"\\s+    # 15. Referrer URL
                    \"([^\"]*)\"        # 16. Client
    	    """;
    	    cre = Pattern.compile(patternString, Pattern.COMMENTS);
    	} catch (PatternSyntaxException e) {
    	    System.err.println("Invalid RE syntax: " + e.getDescription());
    	    System.exit(1);
    	}
    
    	BufferedReader in = null;
    	try {
    	    in = new BufferedReader(new InputStreamReader(new FileInputStream(args[0])));
    	} catch (FileNotFoundException e) {
    	    System.err.println("Unable to open file " + args[1] + ": " + e.getMessage());
    	    System.exit(1);
    	}
    
    	var host = new HashMap<String, Integer>();
    	var hour = new HashMap<String, Integer>();
    	var request = new HashMap<String, Integer>();
    	var referrer = new HashMap<String, Integer>();
    	try {
    	    String s;
    	    while ((s = in.readLine()) != null) {
    		Matcher m = cre.matcher(s);
    		if (!m.matches())
    		    System.out.println("Invalid line: " + s);
    		else {
    		    increment(host, s, m, 1);
    		    increment(hour, s, m, 7);
    		    increment(request, s, m, 11);
    		    increment(referrer, s, m, 15);
    		}
    	    }
    	} catch (Exception e) {
    	    System.err.println("Error reading line: " + e.getMessage());
    	    System.exit(1);
    	}
    	sortedList("Host Access Counts", host);
    	sortedList("Hourly Access Counts", hour);
    	sortedList("Request URL Access Counts", request);
    	sortedList("Referrer URL Access Counts", referrer);
        }
    }
    

    Υλοποίηση αναγνώρισης κανονικών εκφράσεων

    Μηχανή μετάπτωσης καταστάσεων για αναγνώριση της κανονικής έκφρασης (ΔΕΤ!+)|(ΔΕΟΣ) State machine example (Υλοποιείται από 9 άτομα.)

    Επιλογή ανάμεσα σε JSON και XML

    O μορφότυπος JSON

    Σύνταξη JSON

    
    {
        "name": "John",
        "age": 30,
        "isStudent": false,
        "courses": ["Math", "Science"],
        "address": {
            "city": "Athens",
            "country": "Greece"
        }
    }
    

    Βασικοί τύποι δεδομένων σε JSON

    Ενσωμάτωση JSON στη Java

    Ανάγνωση και δημιουργία δεδομένων JSON

    
    package gr.aueb.dmst.dds.example;
    
    import com.google.gson.Gson;
    
    record Person(String name, int age) {}
    
    public class JsonIO {
        public static void main(String[] args) {
            Gson gson = new Gson();
    
    	// Read a JSON object
            String json = "{\"name\":\"Anna\", \"age\":25}";
            Person person = gson.fromJson(json, Person.class);
            System.out.println("Read Person: " + person);
    
    	// Serialize a Java object into JSON
            String serializedJson = gson.toJson(person);
            System.out.println("Serialized JSON: " + serializedJson);
        }
    }
    

    Βέλτιστες πρακτικές

    Βάσεις της XML

    Έγγραφα XML

    Παραδείγματα XML

    Παράδειγμα: ένα στοιχείο με κείμενο

    
    <city>Larisa</city>
    

    Παράδειγμα: στοιχείο με περιεχόμενο άλλα στοιχεία

    
     <?xml version="1.0" encoding="US-ASCII" ?>
     <city_info>
        <name>Larisa</name>
        <area_code>241</area_code>
        <latitude>39.38</latitude>
        <longitude>-22.25</longitude>
        <country>Greece</country>
     </city_info>
    

    Παράδειγμα: κενό στοιχείο

    
    <alumnus />
    
    Ηλεκτρονικό τιμολόγιο (https://docs.oasis-open.org/ubl/os-UBL-2.1/xml/UBL-Invoice-2.1-Example.xml)

    Προσδιορισμοί

    Παράδειγμα:
    <city country="el" id="HER">
    <name>Hrakleio</name>
    </city>
    

    Οντότητες και σχόλια

    Οι παρακάτω οντότητες (entities) μπορούν να οριστούν περιφραστικά:
    ΟντότηταΣύνταξη XML
    <&lt;
    &&amp;
    >&gt;
    "&quot;
    '&apos;

    Σχόλια μέσα σε ένα έγγραφο XML γράφονται ως
    <!-- περιεχόμενο -->

    Διάκριση μεταξύ οντοτήτων, στοιχείων και προσδιορισμών

    Παράδειγμα: ΚΑΔ XML

    Τα παρακάτω αρχείο χρησιμοποιείται από τους φορολογούμενους για να δηλώσουν στη ΑΑΔΕ τον κωδικό αριθμό δραστηριότητάς (ΚΑΔ) τους.
    <?xml version="1.0" encoding="UTF-8"?>
    <ekad xmlns="http://www.gsis.gr/ekad"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      afm="046523469">
        <branch aa="0">
            <kad typeOfKad="1">
                <value>71121908</value>
            </kad>
        </branch>
    </ekad>
    

    Ορισμός σχήματος εγγράφων με τη χρήση XSD

    Σχήμα για απλά στοιχεία

    Στοιχεία XML που περιέχουν απλά δεδομένα όπως το παρακάτω
    <?xml version="1.0" ?>
    <studentID>802345</studentID>
    
    μπορούν να δηλωθούν με το στοιχείο element και τον προσδιορισμό του τύπου.
    <?xml version="1.0" ?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="studentID" type="xsd:integer" />
    </xsd:schema>
    

    Διαθέσιμοι τύποι

    Μερικοί διαθέσιμοι τύποι είναι οι παρακάτω:

    Περιορισμοί σε απλά στοιχεία

    Αν θέλουμε να περιορίσουμε το περιεχόμενο του στοιχείου, μπορούμε να χρησιμοποιήσουμε τα στοιχεία simpleType και restriction μαζί με διάφορους περιορισμούς (restrictions) (στο παράδειγμα pattern).
    <?xml version="1.0" ?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="studentID" >
            <xsd:simpleType>
                <xsd:restriction base="xsd:integer">
                    <xsd:pattern value="80\d{4}" />
                </xsd:restriction>
            </xsd:simpleType>
        </xsd:element>
    </xsd:schema>
    

    Είδη περιορισμών

    Μερικοί υποστηριζόμενοι περιορισμοί είναι οι παρακάτω: Όλοι παίρνουν μια παράμετρο value, που ορίζει την τιμή τους.

    Παραδείγματα περιορισμών

    Παράδειγμα σχήματος για βαθμό:
    <?xml version="1.0" ?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <xsd:element name="grade" >
                    <xsd:simpleType>
                      <xsd:restriction base="xsd:float">
                        <xsd:pattern value="\d+\.[05]"/>
                        <xsd:minInclusive value="0"/>
                        <xsd:maxInclusive value="10"/>
                      </xsd:restriction>
                    </xsd:simpleType>
            </xsd:element>
    </xsd:schema>
    
    Παράδειγμα περιορισμού για επιλογή μιας πόλης:
    <xsd:simpleType>
      <xsd:restriction base="xsd:string">
        <xsd:enumeration value="Athens"/>
        <xsd:enumeration value="Thessaloniki"/>
        <xsd:enumeration value="Argostoli"/>
        <xsd:enumeration value="Volos"/>
        <!-- ... -->
      </xsd:restriction>
    </xsd:simpleType>
    

    Σύνθετοι τύποι

    Ορισμοί προσδιορισμών

    Απλό περιεχόμενο

    Παράδειγμα απλού περιεχομένου

    Παράδειγμα σχήματος:
    
    <?xml version="1.0" ?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="country">
      <xsd:complexType>
        <xsd:simpleContent >
            <xsd:extension base="xsd:string" >
                <xsd:attribute name="code" type="xsd:string" use="required" />
            </xsd:extension>
        </xsd:simpleContent >
      </xsd:complexType>
    </xsd:element>
    </xsd:schema>
    
    Παράδειγμα εγγράφου:
    
    <?xml version="1.0" ?>
    <country code="el">Greece</country>
    

    Ομάδες

    Σε ένα στοιχείο complexType μπορούμε να ορίσουμε και τα παρακάτω στοιχεία

    Παράδειγμα ομάδων

    Παράδειγμα σχήματος:
    
    <?xml version="1.0" ?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="javaProgram">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="package" type="xsd:string" />
                    <xsd:element name="import" type="xsd:string" maxOccurs="unbounded" />
                    <xsd:element name="class">
                        <xsd:complexType>
                            <xsd:sequence>
                                <xsd:element name="name" type="xsd:string" />
                                <xsd:choice maxOccurs="unbounded">
                                    <xsd:element name="field" type="xsd:string" />
                                    <xsd:element name="ctor" type="xsd:string" />
                                    <xsd:element name="method" type="xsd:string" />
                                </xsd:choice>
                            </xsd:sequence>
                            <xsd:attribute name="extends" type="xsd:string" use="optional" />
                        </xsd:complexType>
                    </xsd:element>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>
    
    Παράδειγμα εγγράφου:
    
    <?xml version="1.0" ?>
    <javaProgram>
            <package>gr.aueb.dds.bio</package>
            <import>java.util.Date</import>
            <import>java.math.BigDecimal</import>
            <class extends="Object">
                    <name>Point</name>
                    <field>int x</field>
                    <field>int y</field>
                    <ctor>Point(int x, int y)</ctor>
                    <field>static int numPoints</field>
            </class>
    </javaProgram>
    

    Αριθμητικοί περιορισμοί

    Παράδειγμα: Μια τάξη μπορεί να έχει 10-150 φοιτητές.
    <?xml version="1.0" ?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="class" >
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="student" type="xsd:string"
                     minOccurs="10" maxOccurs="150" />
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>
    

    Ανακεφαλαίωση

    Η επιτρεπόμενη δομή ενός εγγράφου XSD εμφανίζεται στο παρακάτω σχήμα.
    the content models in an XML Schema
    (Αναδημοσιεύεται με την άδεια του συγγραφέα Rahul Srivastava).

    Παράδειγμα: ΚΑΔ XSD

    Τα παρακάτω σχήμα ορίζει τη μορφή του αρχείου που χρησιμοποιείται από τους φορολογούμενους για να δηλώσουν στη ΑΑΔΕ τον κωδικό αριθμό δραστηριότητάς (ΚΑΔ) τους.
    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns="http://www.gsis.gr/ekad" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.gsis.gr/ekad" elementFormDefault="qualified" attributeFormDefault="unqualified">
      <xs:element name="ekad">
        <xs:annotation>
          <xs:documentation>root element</xs:documentation>
        </xs:annotation>
        <xs:complexType>
          <xs:sequence>
            <xs:element name="branch" nillable="false" maxOccurs="unbounded">
              <xs:annotation>
                <xs:documentation>Εγκατάσταση</xs:documentation>
              </xs:annotation>
              <xs:complexType>
                <xs:sequence>
                  <xs:element name="kad" maxOccurs="unbounded">
                    <xs:complexType>
                      <xs:sequence>
                        <xs:element name="value" nillable="false">
                          <xs:annotation>
                            <xs:documentation>Η τιμή του ΚΑΔ</xs:documentation>
                          </xs:annotation>
                          <xs:simpleType>
                            <xs:restriction base="xs:integer">
                              <xs:totalDigits value="15"/>
                            </xs:restriction>
                          </xs:simpleType>
                        </xs:element>
                      </xs:sequence>
                      <xs:attribute name="typeOfKad" use="required">
                        <xs:annotation>
                          <xs:documentation>Είδος ΚΑΔ (δραστηριότητας). 1=Κύρια, 2=Δευτερεύουσα, 3=Λοιπή, 4=Βοηθητική</xs:documentation>
                        </xs:annotation>
                        <xs:simpleType>
                          <xs:restriction base="xs:int">
                            <xs:enumeration value="1"/>
                            <xs:enumeration value="2"/>
                            <xs:enumeration value="3"/>
                            <xs:enumeration value="4"/>
                          </xs:restriction>
                        </xs:simpleType>
                      </xs:attribute>
                    </xs:complexType>
                  </xs:element>
                </xs:sequence>
                <xs:attribute name="aa" use="required">
                  <xs:annotation>
                    <xs:documentation>ΑΑ εγκατάστασης. Η έδρα δηλώνεται σαν υποκατάστημα με ΑΑ=0. Εάν υπάρχει μητρική εταιρεία στο εξωτερικό, ο ΚΑΔ της δηλώνεται ως υποκατάστημα με ΑΑ=9999</xs:documentation>
                  </xs:annotation>
                  <xs:simpleType>
                    <xs:restriction base="xs:int">
                      <xs:minInclusive value="0"/>
                    </xs:restriction>
                  </xs:simpleType>
                </xs:attribute>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
          <xs:attribute name="afm" use="required">
            <xs:annotation>
              <xs:documentation>ΑΦΜ υπόχρεου</xs:documentation>
            </xs:annotation>
            <xs:simpleType>
              <xs:restriction base="xs:string">
                <xs:minLength value="9"/>
                <xs:maxLength value="9"/>
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
        </xs:complexType>
      </xs:element>
    </xs:schema>
    

    Μετασχηματισμοί με τη χρήση XSLT

    Στοιχεία της XSLT

    Παράδειγμα μετασχηματισμού: σχήμα

    <?xml version="1.0" ?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="project">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="shortname" type="xsd:string" />
                    <xsd:element name="projtitle" type="xsd:string" />
                    <xsd:element name="startdate" type="xsd:date" minOccurs="0" />
                    <xsd:element name="enddate" type="xsd:date" />
                    <xsd:element name="web_site" type="xsd:string" minOccurs="0" />
                    <xsd:element name="our_budget" type="xsd:integer" minOccurs="0" />
                    <xsd:element name="total_budget" type="xsd:integer" minOccurs="0" />
                    <xsd:element name="funding_agency" type="xsd:string" minOccurs="0" />
                    <xsd:element name="funding_programme" type="xsd:string" minOccurs="0" />
                    <xsd:element name="project_code" type="xsd:string" minOccurs="0" />
                    <xsd:element name="partner" minOccurs="0" maxOccurs="unbounded">
                        <xsd:complexType>
                            <xsd:sequence>
                                <xsd:element name="shortname" type="xsd:string" />
                                <xsd:element name="country" type="xsd:string" />
                                <xsd:element name="web_site" type="xsd:string" minOccurs="0" />
                            </xsd:sequence>
                        </xsd:complexType>
                    </xsd:element>
                    <xsd:element name="logo" type="xsd:string" minOccurs="0" />
                    <xsd:element name="description" type="xsd:string" />
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>
    

    Παράδειγμα μετασχηματισμού: έγγραφο

    <?xml version="1.0"?>
    <project>
            <shortname>mExpress</shortname>
            <projtitle>mobile in-EXhibition PRovision of Electronic Support Services</projtitle>
            <startdate>2002-03-05</startdate>
            <enddate>2004-04-01</enddate>
            <web_site>http://mexpress.intranet.gr/</web_site>
            <our_budget>328</our_budget>
            <total_budget>3493</total_budget>
            <funding_agency>European Commission</funding_agency>
            <funding_programme>IST</funding_programme>
            <project_code>IST-2001-33432</project_code>
            <partner>
                    <shortname>Intracom</shortname>
                    <country>EL</country>
                    <web_site>http://www.intracom.gr</web_site>
            </partner>
            <partner>
                    <shortname>Ericsson</shortname>
                    <country>DK</country>
                    <web_site>http://www.ericsson.com/</web_site>
            </partner>
            <partner>
                    <shortname>ELISA</shortname>
                    <country>FIN</country>
                    <web_site>http://www.elisa.com</web_site>
            </partner>
            <partner>
                    <shortname>POULIADIS</shortname>
                    <country>EL</country>
                    <web_site>http://www.pouliadis.gr</web_site>
            </partner>
            <partner>
                    <shortname>SSF</shortname>
                    <country>FIN</country>
                    <web_site>http://www.ssf.fi/</web_site>
            </partner>
            <partner>
                    <shortname>HUT</shortname>
                    <country>FIN</country>
                    <web_site>http://www.hut.fi</web_site>
            </partner>
            <partner>
                    <shortname>FFC</shortname>
                    <country>FIN</country>
            </partner>
            <partner>
                    <shortname>ROTA</shortname>
                    <country>EL</country>
                    <web_site>http://www.rota.gr</web_site>
            </partner>
            <logo>../images/p_mexpress.gif</logo>
            <description>
    mEXPRESS aims to exploit the technological opportunities arising from
    evolution in the areas of wireless networks and positioning mechanisms in
    order to support and facilitate the professional exhibition industry in
    a context-aware manner. It will contribute to the economic development of
    the Community by providing means for efficient operation and interaction
    in information-rich environments such as exhibitions, and significantly
    enhancing promotional activities and business communications. The mEXPRESS
    project will provide an integrated mediation platform (mEXPRESS Service
    Provider) oriented to exhibition shows and events.
            </description>
    </project>
    

    Παράδειγμα μετασχηματισμού: XSLT

    <?xml version="1.0"?>
    <!-- Apply using
    xml tr project.xslt mexpress.xml
    -->
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:template match="project">
                    <h1>
                    <xsl:value-of select="shortname" />
                    -
                    <xsl:value-of select="projtitle" />
                    </h1>
                    <!-- Show Logo -->
                    <xsl:element name="img">
                            <xsl:attribute name="src"><xsl:value-of select="logo" /></xsl:attribute>
                    </xsl:element>
                    <br /> <br />
                    <!-- Project Summary information -->
                    <xsl:if test="count(project_code) != 0">
                            Project Code:
                            <xsl:value-of select="project_code" />
                            <xsl:if test="@international = 'yes'">
                                    (International)
                            </xsl:if>
                            <br/>
                    </xsl:if>
                    <xsl:if test="count(funding_programme) != 0">
                            Funding programme: <xsl:value-of select="funding_programme" />
                            <br />
                    </xsl:if>
                    <xsl:if test="count(funding_agency) != 0">
                            Funding Agency: <xsl:value-of select="funding_agency" />
                            <br />
                    </xsl:if>
                    <xsl:if test="@type != ''">
                            Project type:
                            <xsl:choose>
                                    <xsl:when test="@type = 'rtd'">RTD</xsl:when>
                                    <xsl:when test="@type = 'consulting'">Consulting</xsl:when>
                                    <xsl:when test="@type = 'training'">Training</xsl:when>
                                    <xsl:when test="@type = 'dissemination'">Dissemination</xsl:when>
                            </xsl:choose>
                            <br />
                    </xsl:if>
                    <xsl:if test="count(web_site) != 0">
                            Web site:
                            <xsl:element name="a">
                                    <xsl:attribute name="href"><xsl:value-of select="web_site"/></xsl:attribute>
                                    <xsl:value-of select="web_site" />
                            </xsl:element>
                            <br />
                            <br />
                    </xsl:if>
                    <xsl:if test="count(our_budget) != 0">
                            ELTRUN budget: <xsl:value-of select="our_budget" /> EUR
                            <br />
                    </xsl:if>
                    <xsl:if test="count(total_budget) != 0">
                            Total budget: <xsl:value-of select="total_budget" /> EUR
                            <br />
                    </xsl:if>
                    <br />
            </xsl:template>
    </xsl:stylesheet>
    

    Παράδειγμα μετασχηματισμού: αποτέλεσμα

    mExpress - mobile in-EXhibition PRovision of Electronic Support Services



    Project Code: IST-2001-33432 (International)
    Funding programme: IST
    Funding Agency: European Commission
    Project type: RTD
    Web site: http://mexpress.intranet.gr/ (http://mexpress.intranet.gr/)

    ELTRUN budget: 328 EUR
    Total budget: 3493 EUR

    Το μοντέλο αντικειμένων εγγράφων

    Μέθοδοι της NodeList

    Η υλοποίηση του μοντέλου αντικειμένων εγγράφων στη Java

    Κλήσεις μέσω της διεπαφής Document

    Παράδειγμα: υπολογισμός μέσου όρου

    import javax.xml.parsers.*;
    import java.io.*;
    import org.w3c.dom.*;
    
    class Average {
        public static void main(String args[]) {
    
            if (args.length != 2) {
                System.err.println("Usage: Average element file");
                System.exit(1);
            }
    
            Document doc = null;
            try {
                // Create the DocumentBuilderFactory
                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                // Create the document builder
                DocumentBuilder db = dbf.newDocumentBuilder();
                // Create DOM document from the file
                doc = db.parse(new File(args[1]));
            } catch (Exception e) {
                System.err.println("Parsing failed: " + e);
                System.exit(1);
            }
    
            NodeList nodes = doc.getElementsByTagName(args[0]);
            double sum = 0.0;
            for (int i = 0; i < nodes.getLength(); i++) {
                String grade = nodes.item(i).getFirstChild().getNodeValue();
                sum += (Integer.valueOf(grade)).doubleValue();
            }
            System.out.println(sum / nodes.getLength());
        }
    }
    

    Αποτέλεσμα υπολογισμού

    Η εκτέλεση στο αρχείο
    <result_list>
        <result>
            <id>809678</id>
            <grade>9</grade>
        </result>
        <result>
            <id>809630</id>
            <grade>8</grade>
        </result>
        <result>
            <id>809679</id>
            <grade>10</grade>
        </result>
        <result>
            <id>809673</id>
            <grade>6</grade>
        </result>
    </result_list>
    
    γίνεται ως εξής.
    java Average grade grade.xml
    8.25
    

    Άσκηση: Περιγραφή δεδομένων με XML και κανονικές εκφράσεις

    Άσκηση 10

    Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

    Βιβλιογραφία

    Παράρτημα: Ορισμός τύπου εγγράφων με τη χρήση DTD

    Υποστηρίζονται οι παρακάτω ορισμοί:
    Απλοί χαρακτήρες (parsed character data)
    <!ELEMENT name (#PCDATA)>
    
    Ένα στοιχείο
    <!ELEMENT student (person_data)>
    
    Ακολουθία στοιχείων
    <!ELEMENT person_data (name, surname)>
    
    Κανένα ή ένα στοιχείο
    <!ELEMENT person_name (given_name, initial?, last_name)>
    
    Μηδέν ή περισσότερα στοιχεία
    <!ELEMENT owned_cars (car*)>
    
    Ένα ή περισσότερα στοιχεία
    <!ELEMENT course_lecturer (person_data+)>
    
    Επιλογή στοιχείων
    <!ELEMENT engine (two_stroke | four_stroke | wankel | rotary)>
    
    Χρήση παρενθέσεων
    <!ELEMENT person_details (name, surname, (vat_number | id_number))>
    
    Κενό περιεχόμενο
    <!ELEMENT alumnus EMPTY>
    
    Τυχαίο περιεχόμενο
    <!ELEMENT text ANY>
    

    Παράδειγμα - DTD

    <!--
     -
     - Document Type Description for the projects
     -
     - $Id: project.dtd,v 1.2 2004/01/24 20:20:04 bkarak Exp $
     -
    -->
    <!ELEMENT project (
        shortname, 
        projtitle, 
        startdate?, 
        enddate, 
        web_site?, 
        our_budget?, 
        total_budget?, 
        funding_agency?, 
        funding_programme?, 
        project_code?, 
        partner*, 
        logo?, 
        description
    )>
    
    <!ELEMENT projtitle (#PCDATA)>
    <!ELEMENT our_budget (#PCDATA)>
    <!ELEMENT total_budget (#PCDATA)>
    <!ELEMENT funding_agency (#PCDATA)>
    <!ELEMENT funding_programme (#PCDATA)>
    <!ELEMENT project_code (#PCDATA)>
    <!ELEMENT web_site (#PCDATA)>
    <!ELEMENT startdate (#PCDATA)>
    <!ELEMENT enddate (#PCDATA)>
    <!ELEMENT shortname (#PCDATA)>
    <!ELEMENT logo (#PCDATA)>
    <!ELEMENT description (#PCDATA)>
    
    <!ELEMENT partner (shortname, country, web_site?)>
    <!ELEMENT shortname (#PCDATA)>
    <!ELEMENT country (#PCDATA)>
    

    Παράδειγμα - αντίστοιχη XML

    <?xml version="1.0"?>
    <project>
        <shortname>mExpress</shortname>
        <projtitle>mobile in-EXhibition PRovision of Electronic Support Services</projtitle>
        <startdate>20020305</startdate>
        <enddate>20040401</enddate>
        <web_site>http://mexpress.intranet.gr/</web_site>
        <our_budget>328 EUR</our_budget>
        <total_budget>3,493 EUR</total_budget>
        <funding_agency>European Commission</funding_agency>
        <funding_programme>IST</funding_programme>
        <project_code>IST-2001-33432</project_code>
        <partner>
            <shortname>Intracom</shortname>
            <country>EL</country>
            <web_site>http://www.intracom.gr</web_site>
        </partner>
        <partner>
            <shortname>Ericsson</shortname>
            <country>DK</country>
            <web_site>http://www.ericsson.com/</web_site>
        </partner>
        <partner>
            <shortname>ELISA</shortname>
            <country>FIN</country>
            <web_site>http://www.elisa.com</web_site>
        </partner>
        <partner>
            <shortname>POULIADIS</shortname>
            <country>EL</country>
            <web_site>http://www.pouliadis.gr</web_site>
        </partner>
        <partner>
            <shortname>SSF</shortname>
            <country>FIN</country>
            <web_site>http://www.ssf.fi/</web_site>
        </partner>
        <partner>
            <shortname>HUT</shortname>
            <country>FIN</country>
            <web_site>http://www.hut.fi</web_site>
        </partner>
        <partner>
            <shortname>FFC</shortname>
            <country>FIN</country>
        </partner>
        <partner>
            <shortname>ROTA</shortname>
            <country>EL</country>
            <web_site>http://www.rota.gr</web_site>
        </partner>
        <logo>../images/p_mexpress.gif</logo>
        <description>
    mEXPRESS aims to exploit the technological opportunities arising from
    evolution in the areas of wireless networks and positioning mechanisms in
    order to support and facilitate the professional exhibition industry in
    a context-aware manner. It will contribute to the economic development of
    the Community by providing means for efficient operation and interaction
    in information-rich environments such as exhibitions, and significantly
    enhancing promotional activities and business communications. The mEXPRESS
    project will provide an integrated mediation platform (mEXPRESS Service
    Provider) oriented to exhibition shows and events.
        </description>
    </project>
    

    Παράρτημα: Ορισμός τύπων προσδιορισμών με τη χρήση DTD

    Οι προδιορισμοί που επιτρέπονται σε ένα στοιχείο ορίζονται με στοιχεία της μορφής
    <!ATTLIST όνομα_στοιχείου
        όνομα_προσδιορισμού τύπος_προσδιορισμού περιορισμός
        ...
    >
    
    Υποστηρίζονται μεταξύ άλλων οι παρακάτω τύποι προσδιορισμού
    Χαρακτήρες
    CDATA
    Απαρίθμηση
    (επιλογή1 | επιλογή2 | ...)
    Κλειδί
    ID
    Αναφορά σε κλειδί
    IDREF
    Αναφορά σε κλειδιά
    IDREFS
    Οι πιο χρήσιμοι περιορισμοί προσδιορισμών είναι:
    #IMPLIED
    Προαιρετικός προσδιορισμός
    #REQUIRED
    Υποχρεωτικός προσδιορισμός

    Παράδειγμα - DTD

    <!ATTLIST project
        id ID #REQUIRED
        contact CDATA #IMPLIED
        scientific_coordinator CDATA #IMPLIED
        project_manager CDATA #IMPLIED
        group CDATA #REQUIRED
        international (yes | no) #REQUIRED
        type (consulting | rtd | training | dissemination) #REQUIRED
    >
    

    Παράδειγμα - XML

    <?xml version="1.0"?>
    <project
        id="p_mexpress"
        group="g_sense g_wrc"
        scientific_coordinator="m_dds"
        contact="m_pateli"
        international="yes"
        type="rtd"
        project_manager="m_pateli"
    >
    <!-- ... -->
    </project>
    

    Εκτενές παράδειγμα

    Γιορτινή κάρτα

    Ολοκληρωμένο παράδειγμα

    Διάγραμμα των κλάσεων

    XMas card class diagram

    HolidayCard

    
    /*-
     * Copyright 2005-2018 Diomidis Spinellis
     *
     *   Licensed under the Apache License, Version 2.0 (the "License");
     *   you may not use this file except in compliance with the License.
     *   You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *   Unless required by applicable law or agreed to in writing, software
     *   distributed under the License is distributed on an "AS IS" BASIS,
     *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *   See the License for the specific language governing permissions and
     *   limitations under the License.
     */
    
    package gr.aueb.card;
    
    import java.awt.Rectangle;
    
    /**
     * The Holiday Card program main class.
     *
     * @author Giorgos Gousios, Diomidis Spinellis
     * @depend - - - gr.aueb.card.DrawPanel
     * @depend - <instantiate> - gr.aueb.card.MidiPlayer
     * @depend - - - gr.aueb.card.Tree
     * @depend - - - gr.aueb.card.PointSnowFlake
     * @depend - - - gr.aueb.card.SlashSnowFlake
     */
    public class HolidayCard {
    
        /** Number of trees */
        private static final int NUM_TREES = 30;
        /** Number of snowflakes */
        private static final int NUM_SNOWFLAKES = 1500;
        /** Minimum tree width. */
        private static final int TREE_WIDTH = 30;
        /** Minimum tree height. */
        private static final int TREE_HEIGHT = 100;
        /** Additional variation to tree height and width */
        private static final int TREE_WOBBLE = 100;
        /** Song to play. */
        private static String musicFile = "/Jingle_Bells_full_Ab.mid";
    
        public static void main(String[] args) {
    
            // Create a window and the canvas to draw onto.
            DrawPanel d = DrawPanel.getInstance();
    
            // Create randomly-positioned trees.
            for (int i = 0; i < NUM_TREES; i++) {
                Rectangle treeBox = new Rectangle(
    		(int)(Math.random() * DrawPanel.WIDTH),
                    (int)(Math.random() * DrawPanel.HEIGHT),
                    TREE_WIDTH + (int)(Math.random() * TREE_WOBBLE),
                    TREE_HEIGHT + (int)(Math.random() * TREE_WOBBLE));
    
                Tree t = new Tree(d.getCanvas(), treeBox);
                d.addDrawObject(t);
            }
    
    	// Start playing music
    	MidiPlayer m = new MidiPlayer(musicFile);
    
            // Create the snowflakes.
            for (int i = 0; i < NUM_SNOWFLAKES; i++) {
    	    switch (i % 6) {
    	    case 0, 1:
                    d.addDrawObject(new PointSnowFlake(d.getCanvas(), '.', 15));
    		break;
    	    case 2:
                    d.addDrawObject(new PointSnowFlake(d.getCanvas(), 'o', 10));
    		break;
    	    case 3:
                    d.addDrawObject(new PointSnowFlake(d.getCanvas(), '*', 5));
    		break;
    	    case 4, 5:
                    d.addDrawObject(new SlashSnowFlake(d.getCanvas()));
    		break;
    	    }
    	    try {
    		// Allow existing snowflakes to fall a bit, before adding more
    		Thread.sleep(100);
    	    } catch (InterruptedException e) {
    	    }
            }
        }
    }
    

    DrawPanel

    
    /*-
     * Copyright 2005-2018 Diomidis Spinellis
     *
     *   Licensed under the Apache License, Version 2.0 (the "License");
     *   you may not use this file except in compliance with the License.
     *   You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *   Unless required by applicable law or agreed to in writing, software
     *   distributed under the License is distributed on an "AS IS" BASIS,
     *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *   See the License for the specific language governing permissions and
     *   limitations under the License.
     */
    
    package gr.aueb.card;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.util.Vector;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    /**
     * The program's main window.
     * Extends JFrame to display the window where the
     * trees and snow are drawn. Implements the {@link java.lang.Runnable Runnable}
     * interface so as to create a thread that repeatedly calls the
     * {@link gr.aueb.card.Drawable#draw() draw}method.
     *
     * @author Giorgos Gousios, Diomidis Spinellis
     * @opt nodefillcolor lightblue
     * @assoc 1 drawablePanel 1 DrawablePanel
     */
    public class DrawPanel extends JFrame implements Runnable {
    
        /** The window's width. */
        public static final int WIDTH = 1024;
        /** The window's height. */
        public static final int HEIGHT = 768;
    
        /** The window's background color (blue). */
        public static final Color BACKGROUND_COLOR = new Color(0, 153, 204);
    
        /* A table that holds the objects to be drawn */
        private Vector<Drawable> drawObjects = null;
    
        /* The drawing thread (not serializable) */
        private transient Thread thread;
    
        /* The canvas to draw onto */
        private DrawablePanel drawablePanel = null;
    
        /** Serial number of persistant  data.
         * Required, because JFrame implements serializable.
         */
        static final long serialVersionUID = 1L;
    
        /**
         * Constructor to initialize an object with the minimal required state.
         * The constructor is private, as the full initialization is done
         * in the getInstance method.
         */
        private DrawPanel() {
            super("Holiday Card");
        }
    
        /**
         * Field initialization based on a constructed instance
         */
        private void initialize() {
            drawObjects = new Vector<Drawable>();
            initializeGraphics();
            initializeThread();
        }
    
        /**
         * Initialize, display the window, and start the animation.
         * The code here is separate from the constructor in order to
         * avoid the resulting "this escape".
         */
        public static DrawPanel getInstance() {
            DrawPanel instance = new DrawPanel();
            instance.initialize();
            return instance;
        }
    
        /** Initialize the main window. */
        private void initializeGraphics() {
            // Make our window look nice
            JFrame.setDefaultLookAndFeelDecorated(true);
    
            // Create our drawing canvas
            drawablePanel = new DrawablePanel(this);
            drawablePanel.setBackground(BACKGROUND_COLOR);
            drawablePanel.setPreferredSize(new Dimension(WIDTH, HEIGHT));
            setContentPane(drawablePanel);
    
            // Handle termination
            setDefaultCloseOperation(
                    javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
    
            // Exit when the window is closed
            addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
    
            // Our size
            setSize(WIDTH, HEIGHT);
    
            // Force the parent window to expand the canvas to all available space
            pack();
    
            //Display the window
            setVisible(true);
        }
    
        /** Start the execution of the drawing thread. */
        private void initializeThread() {
            if (thread == null) {
                thread = new Thread(this);
                thread.setPriority(Thread.MIN_PRIORITY);
                thread.start();
            }
        }
    
        /** Add a component to be drawn. */
        public void addDrawObject(Drawable drawObject) {
            drawObjects.add(drawObject);
        }
    
        /** Return a copy of the component list to be drawn */
        public Vector<Drawable> getDrawables() {
            return new Vector<Drawable>(drawObjects);
        }
    
        /**
         * The method to be executed by the running thread. Executes the
         * {@link DrawablePanel#repaint()}method periodically.
         */
        public void run() {
            Thread me = Thread.currentThread();
    
            // Allow termination by setting thread to null
            while (thread == me) {
                // tell drawablePanel to repaint its contents
                drawablePanel.repaint();
                try {
                    Thread.sleep(250);
                } catch (InterruptedException e) {
                }
            }
            thread = null;
        }
    
        /**
         * Get the canvas's drawing panel
         *
         * @return javax.swing.JPanel
         */
        public JPanel getCanvas(){
            return drawablePanel;
        }
    }
    

    Drawable

    
    /*-
     * Copyright 2005-2018 Diomidis Spinellis
     *
     *   Licensed under the Apache License, Version 2.0 (the "License");
     *   you may not use this file except in compliance with the License.
     *   You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *   Unless required by applicable law or agreed to in writing, software
     *   distributed under the License is distributed on an "AS IS" BASIS,
     *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *   See the License for the specific language governing permissions and
     *   limitations under the License.
     */
    
    package gr.aueb.card;
    
    import javax.swing.JPanel;
    
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    
    /**
     * An abstract representation of a self-drawable object.
     *
     * @author Giorgos Gousios, Diomidis Spinellis
     */
    public abstract class Drawable {
    
        /**
         * The canvas to draw the object onto
         */
        protected Graphics2D canvas;
    
        /**
         * The canvas's bounds
         */
        protected Rectangle bounds;
    
        /**
         * Create drawable item
         *
         * @param panel The panel to draw the object onto
         */
        public Drawable(JPanel panel) {
            bounds = panel.getBounds();
            canvas = (Graphics2D)panel.getGraphics();
        }
    
        /**
         * Draws the object onto the canvas
         *
         */
        public abstract void draw(Graphics g);
    }
    

    DrawablePanel

    
    /*-
     * Copyright 2005-2018 Diomidis Spinellis
     *
     *   Licensed under the Apache License, Version 2.0 (the "License");
     *   you may not use this file except in compliance with the License.
     *   You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *   Unless required by applicable law or agreed to in writing, software
     *   distributed under the License is distributed on an "AS IS" BASIS,
     *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *   See the License for the specific language governing permissions and
     *   limitations under the License.
     */
    
    package gr.aueb.card;
    
    import java.awt.Color;
    import java.awt.Graphics;
    import java.util.Vector;
    
    import javax.swing.JPanel;
    
    
    /**
     * The Holiday Card program main class.
     *
     * @author Georgios Zouganelis
     * Draw components from this object to reduce flickering.
     */
    public class DrawablePanel extends JPanel {
    
        /** The DrawPanel this DrawablePanel is attached to **/
        private DrawPanel controller = null;
    
        /** Serial number of persistent  data.
         * Required, because JPanel implements serializable.
         */
        private static final long serialVersionUID = 1L;
    
        /**
         * Constructor to initialize the DrawablePanel with it's controller
         *
         */
        public DrawablePanel(DrawPanel panel) {
            controller = panel;
        }
    
        /**
         * Perform all drawing operations
         * By overriding the JPanel method and initiating all the drawing
         * from this place we take advantage of JPanel's double-buffering
         * capability.
         */
        @Override
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            setBackground(DrawPanel.BACKGROUND_COLOR);
    
            // Ask our controller for a copy of items to draw
            Vector<Drawable> toPaint = controller.getDrawables();
            for (Drawable d : toPaint)
                d.draw(g);
        }
    }
    

    Tree

    
    /*-
     * Copyright 2005-2018 Diomidis Spinellis
     *
     *   Licensed under the Apache License, Version 2.0 (the "License");
     *   you may not use this file except in compliance with the License.
     *   You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *   Unless required by applicable law or agreed to in writing, software
     *   distributed under the License is distributed on an "AS IS" BASIS,
     *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *   See the License for the specific language governing permissions and
     *   limitations under the License.
     */
    
    package gr.aueb.card;
    
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Polygon;
    import java.awt.Rectangle;
    import javax.swing.JPanel;
    
    /**
     * A self-drawable tree. Uses a box to specify the tree's bounds (the dimensions
     * constructor parameter). The trunk is placed in the middle of the bottom side
     * of the box, having a width equal to the 8% of the total width of the tree and
     * a height equal to the 20% of the total height of the bounding box. The main
     * body is represented as an isosceles triangle with a height of 80% of the
     * height of the bounding box.
     *
     * @author Giorgos Gousios, Diomidis Spinellis
     * @opt nodefillcolor green
     */
    public class Tree extends Drawable {
    
        /** Tree trunk width as % of the bounding rectangle width */
        private final double TRUNK_WIDTH_FACTOR = 0.08;
        /** Tree trunk height as % of the bounding rectangle height */
        private final double TRUNK_HEIGHT_FACTOR = 0.2;
        /** Tree body height as % of the bounding rectangle height */
        private final double BODY_HEIGHT_FACTOR = 0.8;
        /** Trunk's color (RGB) */
        private final Color BROWN = new Color(204, 102, 0);
        /** Body's color (RGB) */
        private final Color GREEN = new Color(0, 254, 0);
        /** Tree balls' color (RGB) */
        private final Color RED = new Color(250, 0, 0);
    
        /** The tree's bounding rectangle */
        private Rectangle dimensions;
    
        /**
         * Creates a tree from the specified bounding box
         *
         * @param panel The panel to draw the object onto
         * @param dimensions The bounding box dimensions.
         */
        public Tree(JPanel panel, Rectangle dimensions) {
        super(panel);
    	this.dimensions = dimensions;
        }
    
        /**
         * Draws the tree.
         *
         * @param g The Graphics object on which we will paint
         */
        @Override
        public void draw(Graphics g) {
    	drawTrunk(g);
    	drawBody(g);
        }
    
        /**
         * Draws the trunk. For details on how the lengths are calculated
         *
         * @param g The Graphics object on which we will paint
         * @see gr.aueb.Tree the class description.
         */
        private void drawTrunk(Graphics g) {
    	/* Calculate the trunk rectangle first */
    	Rectangle r = new Rectangle();
    
    	r.x = (int) (dimensions.x + (dimensions.width
                        - dimensions.width * TRUNK_WIDTH_FACTOR) / 2);
    	r.y = (int) (dimensions.y + dimensions.height * BODY_HEIGHT_FACTOR);
    	r.width = (int) (dimensions.width * TRUNK_WIDTH_FACTOR);
    	r.height = (int) (dimensions.height * TRUNK_HEIGHT_FACTOR);
    
    	/* Draw it! */
    	g.drawRect(r.x, r.y, r.width, r.height);
    
    	/* Fill it with brown color */
    	Color c = g.getColor();
    	g.setColor(BROWN);
    	g.fillRect(r.x, r.y, r.width, r.height);
    	g.setColor(c); //Revert paint color to default
        }
    
        /**
         * Draws the body. For details on how the lengths are calculated
         *
         * @param g The Graphics object on which we will paint
         * @see gr.aueb.Tree the class description.
         */
        private void drawBody(Graphics g) {
            /* Create the polygon (triangle) to draw */
            Polygon p = new Polygon();
            p.addPoint(dimensions.x + dimensions.width / 2, dimensions.y);
            p.addPoint(dimensions.x,
                    (int) (dimensions.y + dimensions.height * BODY_HEIGHT_FACTOR));
            p.addPoint(dimensions.x + dimensions.width,
                    (int) (dimensions.y + dimensions.height * BODY_HEIGHT_FACTOR));
            /* Draw the body */
            g.drawPolygon(p);
    
            /* Fill it with green color */
            Color c = g.getColor();
            g.setColor(GREEN);
            g.fillPolygon(p);
            g.setColor(c); // Revert paint color to default
    
            /* Set Ornaments to the body. */
            drawTreeOrnaments(g);
        }
    
        /**
         * Draws the ornaments of the tree.
         * @param g The Graphics object on which we will paint
         * @param x The Abscissa of the part of the body to draw the ornament
         * @param y The Ordinate of the part of the body to draw the ornament
         */
        private void addTreeOrnament(Graphics g, int x, int y) {
            /* Draw Tree Ornament. */
            g.drawOval(x, y, 10, 10);
            /* Set color to Red. */
            g.setColor(RED);
            /* Fill Tree Ornament with color. */
            g.fillOval(x, y, 10, 10);
        }
    
        /**
         * Calls addTreeOrnament for specific locations on
         * the tree body.
         * @param g The Graphics object on which we will paint
         */
        private void drawTreeOrnaments(Graphics g) {
            /* yAxis of the body. */
            int yAxis = (int) (dimensions.y + dimensions.height * BODY_HEIGHT_FACTOR);
            /* Add ornament to down left. */
            addTreeOrnament(g, dimensions.x - 2, yAxis - 2);
            /* Add ornament to down right. */
            addTreeOrnament(g, dimensions.x + dimensions.width - 1, yAxis - 1);
            /* Add ornament to up left. */
            addTreeOrnament(g, dimensions.x + dimensions.width / 2 - 5 - 20, yAxis - 25);
            /* Add ornament to up right. */
            addTreeOrnament(g, dimensions.x + dimensions.width / 2 - 5 + 20,  yAxis - 25);
            /* Add ornament to middle. */
            addTreeOrnament(g,dimensions.x + dimensions.width / 2 - 5, yAxis - 65);
        }
    }
    

    SnowFlake

    
    /*-
     * Copyright 2005-2018 Diomidis Spinellis
     *
     *   Licensed under the Apache License, Version 2.0 (the "License");
     *   you may not use this file except in compliance with the License.
     *   You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *   Unless required by applicable law or agreed to in writing, software
     *   distributed under the License is distributed on an "AS IS" BASIS,
     *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *   See the License for the specific language governing permissions and
     *   limitations under the License.
     */
    
    package gr.aueb.card;
    
    import java.awt.Color;
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import javax.swing.JPanel;
    
    /**
     * A self-drawable 'snowflake' represented by a character. The move pattern and
     * character to be displayed is determined by subclasses.
     *
     * @author Giorgos Gousios, Diomidis Spinellis
     * @opt nodefillcolor white
     */
    public abstract class SnowFlake extends Drawable {
    
        /** The snowflake's background color. */
        private static final Color WHITE = new Color(255, 255, 255);
    
        /**
         * The 'x' current coordinate of the snowflake.
         */
        protected int coordX;
    
        /**
         * The 'y' current coordinate of the snowflake.
         */
        protected int coordY;
    
        /**
         * The character to be displayed as a snowflake
         */
        protected char displayChar;
    
        /**
         * Create a snowflake represented by a point-like character.
         *
         * @param panel The panel to draw the object onto
         */
        public SnowFlake(JPanel panel) {
            super(panel);
            coordX = (int) (bounds.width * Math.random()) + bounds.x;
            coordY = 0;
        }
    
        /**
         * Draw the snowflake and wrap around.
         *
         * @param g The Graphics object on which we will paint
         */
        @Override
        public void draw(Graphics g) {
            // Go back to the top when hitting the bottom
            if (coordY >= bounds.height + bounds.y)
                coordY = 0;
    
            // Draw the character in white
            g.setColor(WHITE);
            g.drawString((Character.valueOf(displayChar)).toString(),
            coordX, coordY);
        }
    }
    

    SlashSnowFlake

    
    /*-
     * Copyright 2005-2018 Diomidis Spinellis
     *
     *   Licensed under the Apache License, Version 2.0 (the "License");
     *   you may not use this file except in compliance with the License.
     *   You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *   Unless required by applicable law or agreed to in writing, software
     *   distributed under the License is distributed on an "AS IS" BASIS,
     *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *   See the License for the specific language governing permissions and
     *   limitations under the License.
     */
    
    package gr.aueb.card;
    
    import java.awt.Graphics;
    import javax.swing.JPanel;
    
    /**
     * A class that animates a slash on a canvas.
     *
     * @author Giorgos Gousios, Diomidis Spinellis
     * @opt nodefillcolor white
     */
    public class SlashSnowFlake extends SnowFlake {
    
        /**
         * Create a snowflake represented by a slash.
         *
         * @param panel The panel to draw the object onto
         */
        public SlashSnowFlake(JPanel panel) {
            super(panel);
            displayChar = '/';
        }
    
        /**
         * Display the slash on the drawing canvas. The slash alternates between
         * forward slash and backslash depending on the current 'y' coordinate.
         *
         * @param g The Graphics object on which we will paint
         */
        @Override
        public void draw(Graphics g) {
    
            /* / on even lines, \ on odd lines */
            displayChar = ((coordY % 2) == 0) ? '/' : '\\';
    
            /* Move by 0 to 10 pixels down*/
            coordY += (int) (Math.random() * 10);
    
            // Draw it through the superclass
            super.draw(g);
        }
    }
    

    PointSnowFlake

    
    /*-
     * Copyright 2005-2018 Diomidis Spinellis
     *
     *   Licensed under the Apache License, Version 2.0 (the "License");
     *   you may not use this file except in compliance with the License.
     *   You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *   Unless required by applicable law or agreed to in writing, software
     *   distributed under the License is distributed on an "AS IS" BASIS,
     *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *   See the License for the specific language governing permissions and
     *   limitations under the License.
     */
    
    package gr.aueb.card;
    
    import java.awt.Graphics;
    import javax.swing.JPanel;
    
    /**
     * A class that animates a point-like character on a canvas.
     * The character can be e.g. a . or a * or an o.
     *
     * @author Giorgos Gousios, Diomidis Spinellis
     * @opt nodefillcolor white
     */
    public class PointSnowFlake extends SnowFlake {
    
        /** The wieght of the snowflake. */
        int weight;
    
        /**
         * Create a snowflake represented by a point-like character.
         *
         * @param panel The panel to draw the object onto
         * @param c The character to draw
         * @param w The snowflake's weight
         */
        public PointSnowFlake(JPanel panel, char c, int w) {
            super(panel);
            displayChar = c;
            weight = w;
        }
    
        /**
         * Display the star onto the canvas. The star changes its 'x' coordinate,
         * depending on the 'y' coordinate.
         *
         * @param g The Graphics object on which we will paint
         */
        @Override
        public void draw(Graphics g) {
    
            // Move the snowflake left and right
            switch (coordY % 3) {
            case 1:
                coordX = coordX - 5;
                break;
            case 2:
                coordX = coordX + 5;
                break;
            default:
                break;
            }
    
            // Move down, based on the weight
            coordY += (int)(Math.random() * weight);
    
            // Draw it through the superclass
            super.draw(g);
        }
    }
    

    MidiPlayer

    
    /*-
     * Copyright 2005-2018 Diomidis Spinellis
     *
     *   Licensed under the Apache License, Version 2.0 (the "License");
     *   you may not use this file except in compliance with the License.
     *   You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *   Unless required by applicable law or agreed to in writing, software
     *   distributed under the License is distributed on an "AS IS" BASIS,
     *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *   See the License for the specific language governing permissions and
     *   limitations under the License.
     */
    
    package gr.aueb.card;
    
    import javax.sound.midi.*;
    import java.io.InputStream;
    import java.io.IOException;
    
    /**
     * Play the specified MIDI file
     * Note:
     * For this to work you must ensure that the computer's mixer
     * is configured to play the software synhtesizer output.
     *
     * @author Diomidis Spinellis
     */
    public class MidiPlayer {
        /** The sequencer we are using to play the MIDI data. */
        static Sequencer sequencer = null;
    
        /** Constructor for playing the specified file. */
        MidiPlayer(String file) {
    	playFile(file);
        }
    
        /** Play the specified file. */
        public void playFile(String file) {
            InputStream midiFile = getClass().getResourceAsStream(file);
            try {
    	    if (sequencer == null)
    		sequencer = MidiSystem.getSequencer();
    	    else
    		end();
    	    sequencer.setSequence(MidiSystem.getSequence(midiFile));
                sequencer.open();
                sequencer.start();
            } catch(MidiUnavailableException e) {
                System.err.println("Midi device unavailable:" + e);
            } catch(InvalidMidiDataException e) {
                System.err.println("Invalid MIDI data:" + e);
            } catch(IOException e) {
                System.err.println("I/O error:" + e);
            }
        }
    
        /** Return true if the music is still playing. */
        public boolean isPlaying() {
    	return sequencer.isRunning();
        }
    
        /* Stop playing. */
        public void end() {
                sequencer.stop();
                sequencer.close();
    	    sequencer = null;
        }
    }
    

    Τεκμηρίωση

    Τα σχόλια μέσα στον κώδικα επιτρέπουν την αυτόματη δημιουργία της τεκμηρίωσης, με τη χρήση του προγράμματος javadoc.
    Τεκμηρίωση σε μορφή XML

    Προαιρετική άσκηση

    Με βάση τον κώδικα της κάρτας υλοποιήστε ένα παιγνίδι (π.χ. απόφυγε το χιόνι, ή μάζεψε τις μπάλες, ή πιάσε τον τάρανδο, κ.λπ.).

    Πληροφορίες για την άσκηση

    Συναρτήσεις και ροές

    Συναρτησιακός προγραμματισμός

    Εκφράσεις λάμδα

    (a) -> {  return a * a; }
    (a, b) -> {  return a + b; }
    () -> {  return true; }
    

    Διαθέσιμοι τύποι

    Το πακέτο java.util.function ορίζει μια σειρά από διεπαφές FunctionalInterface:

    Οι παραπάνω μπορούν κατά περίπτωση να εξειδικευτούν παραπάνω με ένα από τα προθέματα: Bi (δέχεται δύο ορίσματα)· Int, Long, Double (τύπος ορίσματος)· Το (τύπος επιστροφής).

    Μέθοδοι σε συναρτήσεις

    Οι παρακάτω μέθοδοι είναι διαθέσιμες ανάλογα με το αντικείμενο.

    Παράδειγμα λάμδα

    import java.util.function.Function;
    
    class Lambda {
        public static void main(String args[]) {
            // Assign lambda to variable
            Function<Integer, Integer> square = (a) -> a * a;
            // Apply function to value
            System.out.println(square.apply(2));
    
            // Pass function to method and obtain function result
            Function<Integer, Integer> fourthPower = square.compose(square);
            System.out.println(fourthPower.apply(2));
        }
    }
    

    Μέθοδοι ως συναρτήσεις

    Μέθοδοι που ικανοποιούν μια διεπαφή Functional μπορούν να χρησιμοποιηθούν ως τέτοιες με τη χρήση του συμβόλου ::.
    import java.util.function.UnaryOperator;
    import java.math.BigInteger;
    
    // Methods compatible with a functional interface
    class FunctionalFactorial {
        public static BigInteger factorial(BigInteger i) {
            if (i.equals(BigInteger.ZERO))
                return BigInteger.ONE;
            else
                return i.multiply(factorial(i.subtract(BigInteger.ONE)));
        }
    
        public BigInteger instanceFactorial(BigInteger n) {
            return factorial(n);
        }
    
        // Prints 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
        public static void main(String args[]) {
            UnaryOperator<BigInteger> f;
    
            f = FunctionalFactorial::factorial;
            System.out.println(f.apply(new BigInteger("100")));
    
            f = new FunctionalFactorial()::instanceFactorial;
            System.out.println(f.apply(new BigInteger("100")));
        }
    }
    

    Παράδειγμα σύνθεσης μεθόδων

    import java.util.function.DoubleUnaryOperator;
    import java.util.function.Function;
    import static java.lang.Math.abs;
    import static java.lang.Math.PI;
    
    class Inverse {
        public static void main(String args[]) {
            Function<DoubleUnaryOperator, DoubleUnaryOperator> inverse =
                f -> x -> 1. / f.applyAsDouble(x);
    
    	DoubleUnaryOperator cot = inverse.apply(Math::tan); // συνεφαπτομένη
    	DoubleUnaryOperator sec = inverse.apply(Math::cos); // τέμνουσα
    	DoubleUnaryOperator csc = inverse.apply(Math::sin); // συντέμνουσα
    
            final double EPSILON = 1e-15;
            assert abs(sec.applyAsDouble(0) - 1) < EPSILON;
            assert abs(csc.applyAsDouble(PI / 2) - 1) < EPSILON;
            assert abs(cot.applyAsDouble(PI / 4) - 1) < EPSILON;
        }
    }
    

    Ορισμός τύπων συναρτήσεων

    
    @FunctionalInterface
    interface TripletChooser <T> {
        T choose(T a, T b, T c);
    }
    
    class TripletChooserExample {
        public static void main(String args[]) {
            TripletChooser<String> getFirst = (a, b, c) -> a;
            System.out.println(getFirst.choose(args[0], args[1], args[2]));
        }
    }
    

    Παράδειγμα χρήσης τύπου συνάρτησης

    
    @FunctionalInterface
    interface Combiner {
        int combine(int a, char operator, int b);
    }
    
    public class CombinerExample {
        public static void main(String[] args) {
            Combiner arithmeticCombiner = (a, operator, b) -> {
                switch (operator) {
                    case '+': return a + b;
                    case '*': return a * b;
                    default: throw new IllegalArgumentException("Invalid operator for arithmetic: " + operator);
                }
            };
    
            Combiner bitwiseCombiner = (a, operator, b) -> {
                switch (operator) {
                    case '+': return a | b;
                    case '*': return a & b;
                    default: throw new IllegalArgumentException("Invalid operator for bitwise: " + operator);
                }
            };
    
            // Verify Arithmetic Combiner
            assert arithmeticCombiner.combine(5, '+', 3) == 8;
            assert arithmeticCombiner.combine(5, '*', 3) == 15;
    
            // Verify Bitwise Combiner
            assert bitwiseCombiner.combine(5, '+', 3) == 7;
            assert bitwiseCombiner.combine(5, '*', 3) == 1;
        }
    }
    

    Ροές

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

    Τύποι ροών

    Ο τύπος Optional

    Η παραμετρική κλάση java.util.Optional περιέχει μια τιμή τύπου T που μπορεί και να απουσιάζει.

    Χρήσιμες μέθοδοι

    Πηγές ροών

    Ενδιάμεση επεξεργασία ροών

    Τελική επεξεργασία ροών

    Λέξεις κειμένου: Knuth vs McIlroy

    Donald Knuth Douglas McIlroy

    Σχετικά είναι αυτή η εργασία (https://dl.acm.org/doi/pdf/10.1145/5948.315654), αυτό το κόμικ (https://comic.browserling.com/97) και αυτό το βίντεο (https://www.youtube.com/watch?v=kQKrmDLvijo).

    Παράδειγμα: Λέξεις κειμένου

    /*
     * Output ordered list of a file's unique words
     */
    
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.stream.Stream;
    import java.io.IOException;
    
    class UniqueWords {
        public static void main(String args[]) {
            if (args.length != 1) {
                System.err.println("Usage: UniqueWords file");
                System.exit(1);
            }
    
            try {
                Files
                    .lines(Paths.get(args[0]))
                    .flatMap(line -> Stream.of(line.split("\\W+")))
                    .sorted()
                    .distinct()
                    .filter((x) -> x.length() > 0)
                    .forEach(System.out::println);
            } catch (IOException e) {
                System.err.println("Error reading line: " + e.getMessage());
                System.exit(1);
            }
        }
    }
    

    Παράδειγμα: εκτίμηση πληθάριθμου

    
    /**
     * Estimate the number of distinct elements in a data stream
     * (F0 estimation problem) based on the algorithm published in the
     * Proceedings of 30th Annual European Symposium on Algorithms (ESA 2022)
     * https://doi.org/10.48550/arXiv.2301.10191
     */
    
    import java.util.HashSet;
    import java.util.Random;
    import java.util.Set;
    import java.util.function.Function;
    import java.util.stream.IntStream;
    import java.util.stream.Stream;
    
    public class F0Estimator {
    
        // Probability to add an element
        private double p = 1.0;
    
        /**
         * Estimate number of unique elements in the passed stream
         * @param storageSize The storage to use
         */
        public <T> long uniqueElements(Stream<T> stream, int storageSize) {
            final float LOAD_FACTOR = 0.5f;
    
            Set<T> X = new HashSet<>(storageSize , LOAD_FACTOR);
            Random random = new Random();
    
            stream.forEach(element -> {
                // Ensure element is in the set with probability p
                if (random.nextDouble() < p)
                    X.add(element);
                else
                    X.remove(element);
    
                if (X.size() >= storageSize) {
                    // Randomly keep each element in X with probability 1/2
                    X.removeIf(e -> random.nextDouble() < 0.5);
                    p /= 2;
                    if (X.size() >= storageSize) {
                        throw new IllegalStateException("Threshold exceeded after sampling");
                    }
                }
            });
    
            return (long) (X.size() / p);
        }
    
        public static void main(String[] args) {
            // Create a Random instance
            Random random = new Random();
    
            // Create a stream of many random integers
            Stream<Integer> stream = IntStream
                .generate(random::nextInt).limit(1_000_000_000)
                .map(i -> i & 0xffff)
                .boxed();
    
            final int STORAGE_SIZE = 1000;
    
            var estimator = new F0Estimator();
    
            long uniqueCount = estimator.uniqueElements(stream, STORAGE_SIZE);
            System.out.println("Estimated number of unique elements: " + uniqueCount);
        }
    }
    

    Η μέθοδος Newton-Raphson

    Η προσεγγιστική μέθοδος Newton-Raphson μας επιτρέπει να βρούμε τη ρίζα οποιασδήποτε πραγματικής συνάρτησης. x n+1 = x n - f ( x n ) f ( x n )

    Τετραγωνική ρίζα με Newton-Raphson

    Παράδειγμα: Υλοποίηση √2 με NR

    Το παρακάτω παράδειγμα υπολογίζει τη √2 δημιουργώντας μια άπειρου μήκους ακολουθία με διαδοχικά καλύτερες προσεγγίσεις.

    import java.util.Optional;
    import java.util.function.Predicate;
    import java.util.function.DoubleFunction;
    import java.util.stream.Stream;
    
    
    /** Find a square root using the Newton-Raphson approximation */
    class SquareRoot {
    
        /** Obtain successive approximations of a function's root using the
         * Newton-Raphson method. */
        static class NewtonRaphson {
            /** f(x) and f'(x) */
            DoubleFunction fx, fdx;
    
            NewtonRaphson(DoubleFunction fx, DoubleFunction fdx) {
                this.fx = fx;
                this.fdx = fdx;
            }
    
            /** Return next approximation, given the previous one */
            Double nextApproximation(double previous) {
                // xₙ₊₁ = xₙ - f(xₙ) / f′(xₙ)
                return previous - (double)fx.apply(previous) / (double)fdx.apply(previous);
            }
        }
    
        /** Test whether successive parts of a series differ more than a value */
        static class NotWithin implements Predicate<Double> {
            /** Previous value in series */
            Optional<Double> previous = Optional.empty();
            /** Difference value above which the test method returns true */
            Double epsilon;
    
            NotWithin(double d) {
                epsilon = d;
            }
    
            /**
             * Return true if successive parts of the series do not differ by
             * less than the specified epsilon.
             */
            @Override
            public boolean test(Double d) {
                boolean r;
    
                if (previous.isPresent())
                    r = (Math.abs(previous.get() - d) > epsilon);
                else
                    r = true;
                previous = Optional.of(d);
                return r;
            }
        }
    
        public static void main(String args[]) {
            final double SQRT_TO_FIND = 2;
            DoubleFunction fx = (x -> x * x - SQRT_TO_FIND); // f(x) = x² - α
            DoubleFunction fdx = (x -> 2 * x); // f'(x) = 2x
            var rootTwo = new NewtonRaphson(fx, fdx);
            var greaterThanEpsilon = new NotWithin(1e-15);
    
    	// SQRT_TO_FIND is also our first approximation
            System.out.println(Stream.iterate(SQRT_TO_FIND, rootTwo::nextApproximation)
                .dropWhile(greaterThanEpsilon)
                .findFirst()
                .get());
        }
    }
    

    Άσκηση: συναρτήσεις και ροές

    Άσκηση 17

    Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

    Βιβλιογραφία

    Ανάπτυξη διαδικτυακών εφαρμογών

    Περιεχόμενα

    Το μοντέλο αναφοράς OSI

    Φυσικό επίπεδο

    Επίπεδο σύνδεσης

    Επίπεδο δικτύου

    Πρωτόκολλα διαδικτύου: IPv4, IPv6, IPsec, ICMP

    IPv4

        0                   1                   2                   3   
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |Version|  IHL  |Type of Service|          Total Length         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |         Identification        |Flags|      Fragment Offset    |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |  Time to Live |    Protocol   |         Header Checksum       |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       Source Address                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                    Destination Address                        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                    Options                    |    Padding    |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    

    Επίπεδο μεταφοράς

    Πρωτόκολλα διαδικτύου: TCP, UDP, …

    TCP

        0                   1                   2                   3   
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |          Source Port          |       Destination Port        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                        Sequence Number                        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                    Acknowledgment Number                      |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |  Data |           |U|A|P|R|S|F|                               |
       | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
       |       |           |G|K|H|T|N|N|                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |           Checksum            |         Urgent Pointer        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                    Options                    |    Padding    |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                             data                              |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    

    Επίπεδο συνόδου

    Πρωτόκολλα διαδικτύου: Sockets API

    Επίπεδο παρουσίασης

    (Σε παρένθεση σχετικά πρωτόκολλα του διαδικτύου)

    Επίπεδο εφαρμογής

    (Σε παρένθεση σχετικά πρωτόκολλα του διαδικτύου)

    Αρχιτεκτονική του παγκόσμιου ιστού

    Προσδιορισμός στοιχείων με URI

    URI = scheme ":" ["//" authority] path ["?" query] ["#" fragment]
    
    index.html
    https://www.dmst.aueb.gr/dds/
    https://www.google.com/search?q=AUEB
    https://www.aueb.gr/Hmerologio.pdf#page=3
    

    Το πρωτόκολλο HTTP

    Το πρωτόκολλο HTTP υποστηρίζει τις παρακάτω μεθόδους επικοινωνίας:

    Παράδειγμα HTTP

    Αίτηση

    GET /dds/ HTTP/1.1
    Host: www2.dmst.aueb.gr
    User-Agent: curl/7.71.1
    Accept: */*
    

    Απάντηση

    HTTP/1.1 200 OK
    Date: Sun, 08 Jan 2023 10:00:32 GMT
    Server: Apache/1.3.33 (Linux/RHEL)
    Content-Location: index.en.html
    Vary: negotiate,accept-language,accept-charset
    TCN: choice
    Last-Modified: Fri, 30 Dec 2022 21:03:52 GMT
    Accept-Ranges: bytes
    Content-Length: 22599
    Content-Type: text/html
    Content-Language: en
    

    Αίτημα HTTP στη Java

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.IOException;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.net.MalformedURLException;
    
    public class UrlRetriever {
        public static void main(String[] args) {
    	if (args.length != 1) {
    	    System.err.println("Usage: UrlRetriever URL");
    	    System.exit(1);
    	}
    
            URL url = null;
            try {
                // Make a request to the specified URL
                url = new URL(args[0]);
            } catch (MalformedURLException e) {
                    System.err.println("Invalid URL: " + e);
                    System.exit(1);
            }
    
            HttpURLConnection connection = null;
            try {
                connection = (HttpURLConnection)url.openConnection();
            } catch (ClassCastException e) {
                System.err.println("Specified protocol is not HTTP");
                System.exit(1);
            } catch (IOException e) {
                System.err.println("Connection error: " + e);
                System.exit(1);
            }
    
            try {
                connection.setRequestMethod("GET");
    
                // Get the response from the server
                int status = connection.getResponseCode();
                BufferedReader in = new BufferedReader(
                    new InputStreamReader(connection.getInputStream()));
                int c;
                StringBuilder content = new StringBuilder();
                while ((c = in.read()) != -1) {
                    content.append((char)c);
                }
                in.close();
    
                // Print the response
                System.out.println(content.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    Χαρακτηριστικά της αρχιτεκτονικής REST

    Παραδείγματα αιτήσεων REST

    java UrlRetriever https://www.gutenberg.org/cache/epub/1342/pg1342.txt
    
    curl 'https://aviationweather.gov/api/data/metar?ids=LGAV&hours=48'
    curl -v -k "https://www.wikidata.org/w/api.php?action=wbgetentities&format=json&titles=Moon&sites=enwiki" |  jq .
    curl -A "Mozilla/5.0" 'http://telematics.oasa.gr/api/?act=getBusLocation&p1=1822'
    curl -LH "Accept: application/vnd.crossref.unixref+xml;q=1, application/rdf+json;q=0.5" https://doi.org/10.1126/science.169.3946.635
    
    curl --request POST -H "Authorization: Bearer $ROBBIE_API_KEY" --url http://robbie.dmst.aueb.gr:50135/completion --header "Content-Type: application/json" --data '{ "prompt": "You are a helpful Assistant responding to User queries. User: Which city is the capital of Germany?\nAssistant: Berlin\nWhich city is the capital of Greece?"}'
    
    curl https://api.openai.com/v1/engines/davinci/completions \
      -X POST \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $OPENAI_API_KEY" \
      -d '{
        "prompt": "I can convert a String into an int in Java program by ",
        "max_tokens": 50
      }'
    

    Εξυπηρετητής ώρας HTTP στη Java

    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetSocketAddress;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    
    import com.sun.net.httpserver.HttpExchange;
    import com.sun.net.httpserver.HttpHandler;
    import com.sun.net.httpserver.HttpServer;
    
    public class TimeServer {
        static class GetHandler implements HttpHandler {
            @Override
            public void handle(HttpExchange exchange) throws IOException {
    
                var calendar = Calendar.getInstance();
                var dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss\n");
                byte[] response = dateFormat.format(calendar.getTime()).getBytes();
    
                // Set the response header and status code
                exchange.sendResponseHeaders(200, response.length);
    
                // Get the response body output stream
                OutputStream responseBody = exchange.getResponseBody();
    
                System.out.print(exchange.getRemoteAddress());
                responseBody.write(response);
                responseBody.close();
            }
        }
    
        public static void main(String[] args) throws Exception {
            // Create a server on port 8000
            HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
    
            server.createContext("/", new GetHandler()); // "GET /" handler
    
            server.start(); // Start serving requests
        }
    }
    

    Διαδικτυακές εφαρμογές στην πράξη

    Άσκηση: Επικοινωνία Πελάτη-Εξυπηρετητή

    Άσκηση 18

    Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

    Βιβλιογραφία

  • Rogers Candenhead. Πλήρες Εγχειρίδιο της Java 12. 8η Έκδοση. Εκδόσεις X. Γκιούρδα, 2023. Κεφ. 17, 20.
  • Ατομικές ασκήσεις και συμμετοχή

    Αρχείο των ασκήσεων και ηλεκτρονική παράδοση

    Οδηγίες

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

    Προθεσμίες παράδοσης

    Η ώρα παράδοσης είναι πάντα τοπική ώρα Ελλάδος.

    Άσκηση Ημερομηνία και ώρα παράδοσης
    1 Sun Oct 12 23:59:59 2025

    Συχνές ερωτήσεις και απαντήσεις (FAQ)

    Περιεχόμενα

    Που θα βρω τεκμηρίωση για τις κλάσεις που υποστηρίζει η Java;

    Στον αντίστοιχο ιστότοπο της Oracle (https://docs.oracle.com/en/java/javase/index.html).

    Πως θα ρυθμίσω το Visal Studio Code για να παραδώσω τον τρόπο επίλυσης των ασκήσεων

    Διαβάστε την τεκμηρίωση που παραπέμπεται στη σχετική σελίδα των σημειώσεων.

    Για κάποιο πολύ σοβαρό λόγο δεν μπόρεσα να παραδώσω την άσκηση στην ώρα της. Μπορώ να πάρω μια παράταση;

    Η προθεσμία παράδοσης της κάθε άσκησης είναι η τελευταία ημερομηνία στην οποία μπορείτε να παραδώσετε την άσκηση χωρίς επιπτώσεις στο βαθμό της. Καλό είναι να την παραδίδετε πριν το επόμενο μάθημα έτσι ώστε
    1. να μπορέσετε να ασχοληθείτε με την καινούρια όταν αυτή ανακοινωθεί
    2. να έχετε ένα περιθώριο χρόνου για να καλύψετε προσωπικά ή τεχνικά προβλήματα που μπορεί να εμφανιστούν
    Σε περίπτωση που δεν μπορέσατε να παραδώσετε την άσκηση μέσα στην προθεσμία, θα πρέπει να την παραδώσετε το συντομότερο δυνατό για να έχετε τη μικρότερη δυνατή επιβάρυνση στο βαθμό. Για λόγους διαφάνειας και αποτελεσματικότητας στη βαθμολόγηση αυτή γίνεται αυτόματα χωρίς να υπάρχει πρόβλεψη για εξαιρέσεις. Ο αριθμός όμως των ασκήσεων σας επιτρέπει να καλύψετε τη διαφορά στις επόμενες ασκήσεις.

    Πότε πρέπει να κατεβάζω ενημερωμένη έκδοση του αρχείου Jarpeb.jar;

    Στη σελίδα αυτή εμφανίζεται η τρέχουσα έκδοση και η ημερομηνία τελευταίας αλλαγής της κάθε άσκησης. Αν έχετε κατεβάσει το αρχείο πριν από την ημερομηνία τελευταίας αλλαγής της άσκησης που σας ενδιαφέρει ή αν η έκδοση της άσκησης στον υπολογιστή σας είναι προγενέστερη αυτής που περιέχει το αρχείο τότε θα πρέπει να κατεβάσετε νεώτερη έκδοση του αρχείου. Για να μπορέσετε να δείτε την έκδοση της άσκησης που έχετε στον υπολογιστή σας μπορείτε να τρέξετε την εντολή
    java -jar Exercise.jar -v <κωδικός μαθήματος> <κωδικός άσκησης> <ΑΜ φοιτητή>
    

    Μπορώ να ασχοληθώ με ασκήσεις που δεν έχουν ανακοινωθεί ακόμα;

    Ναι, αλλά με δική σας ευθύνη. Ασκήσεις που δεν έχουν ανακοινωθεί επίσημα στο μάθημα και για τις οποίες δεν έχει δωθεί ημερομηνία παράδοσης μπορεί να μην έχουν ελεγχθεί πλήρως, να βρίσκονται ακόμα υπό ανάπτυξη και να περιέχουν λάθη στην εκφώνηση και στη βαθμολόγηση. Ο βαθμός που θα καταχωρήσετε ισχύει, αλλά είναι πιθανό κατά την επίλυση να συναντήσετε προβλήματα που θα έχουν διορθωθεί μέχρι την επίσημη ανακοίνωση της άσκησης. Επίσης, σε ασκήσεις που δεν έχουν ανακοινωθεί, μπορεί οι βοηθοί του μαθήματος και οι επιβλέποντες στα εργαστήρια να μην μπορούν να σας βοηθήσουν.

    Γίνεται να υπολογιστούν στο μάθημα οι βαθμοί των ασκήσεων που είχα λάβει την περασμένη χρονιά;

    Δυστυχώς όχι, αυτό δε γίνεται. Κάθε χρόνο οι εκφωνήσεις των ασκήσεων και οι κωδικοί ελέγχου αλλάζουν. Η βαθμολογία των ασκήσεων ισχύει μόνο για την εξεταστική περίοδο του χειμερινού εξαμήνου και την πρόσθετη εξεταστική περίοδο του Σεπτεμβρίου του ίδιου έτους με αυτό στο οποίο έγιναν οι ασκήσεις.

    Ποιες είναι οι ημερομηνίες παράδοσης των ασκήσεων;

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

    Τι ρόλο παίζει το πεδίο "σχόλια" στη σελίδα παράδοσης της βαθμολογίας; Δεν έχω λάβει απάντηση σε κάποιο σχόλιο που είχα κάνει.

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

    Πως ελέγχεται το ποιος υλοποιεί και ποιος καταχωρεί την άσκηση;

    Το πρόγραμμα Jarpeb καταχωρίζει στοιχεία που έχουν σχέση με την άσκηση, τον ΑΜ του φοιτητή ή της φοιτήτριας, τον τρόπο επίλυσης (όπως καταγράφεται από το Visual Studio Code) και το βαθμό. Επιπλέον κατά την καταχώρηση ο βαθμός και ο ΑΜ του φοιτητή συνδέονται με τη διεύθυνση IP του μηχανήματος που έκανε την καταχώρηση. Με τη χρήση στοιχείων ελέγχου οι διευθύνσεις IP αντιστοιχούνται σε συγκεκριμένους φοιτητές. Όπου διαπιστωθούν στοιχεία που δημιουργούν την εντύπωση πως μπορεί στην υλοποίηση να έχει αναμιχθεί τρίτος ή να έχει χρησιμοποιηθεί λογισμικό παραγωγικής τεχνητής νοημοσύνης, ο αντίστοιχος φοιτητής ή φοιτήτρια μπορεί να κληθεί για συμπληρωματική εξέταση.

    Επιτρέπεται η υλοποίηση και καταχώρηση ασκήσεων σε υπολογιστές εκτός του εργαστηρίου;

    Ναι, αλλά η υλοποίηση πρέπει να γίνεται από τον ίδιο το φοιτητή — απαγορεύεται αυστηρά η κάθε συνεργασία. Σε περιπτώσεις που έχουν βρεθεί στοιχεία που δείχνουν πως έχει υπάρξει συνεργασία, έχει ζητηθεί απο τους φοιτητές να επαναλάβουν την άσκηση στο εργαστήριο. Σε περίπτωση υποτροπής όλες οι αντίστοιχες ασκήσεις μηδενίζονται στο τέλος του χρόνου. Επίσης, δε μπορεί να σας παρασχεθεί βοήθεια σχετικά με την εγκατάσταση και διαμόρφωση του περιβάλλοντος εργασίας της Java στον υπολογιστή σας - ειδικά για το θέμα της εμφάνισης των ελληνικών χαρακτήρων στην οθόνη σας.

    Έχω καταχωρήσει το βαθμό μου αλλά δε βλέπω ούτε το βαθμό ούτε την καταχώρηση στις αντίστοιχες σελίδες. Γιατί;

    Ο έλεγχος των καταχωρήσεων και η ενημέρωση των βαθμών γίνονται σε περιοδικά διαστήματα. Κοιτάξτε την ημερομηνία τελευταίας ενημέρωσης που εμφανίζεται στο κάτω μέρος της σελίδας. Αν είναι μικρότερη από την ημερομηνία που καταχωρήσατε την άσκηση, τότε σωστά δεν εμφανίζονται τα στοιχεία της καταχώρησής σας.

    Έχω καταχωρήσει το βαθμό μου παρατηρώ πως η εκφώνηση της άσκησης έχει αλλάξει. Τι πρέπει να κάνω;

    Οι ασκήσεις που καταχωρούνται με επιτυχία κατοχυρώνονται. Δε χρειάζεται να κάνετε απολύτως τίποτα, εκτός αν θέλετε να ξανακάνετε την άσκηση με τη νέα εκφώνηση για να την καταλάβετε καλύτερα ή για να πάρετε υψηλότερο βαθμό.

    Γιατί σε υπολογιστή με λειτουργικό σύστημα Windows η εκφώνηση εμφανίζεται με περίεργους χαρακτήρες;

    Δοκιμάστε να δώσετε την εντολή
    
    chcp 737
    
    πριν την εκτέλεση του Exercise.jar.

    Δοκιμάστε να αλλάξετε τη γραμματοσειρά του παραθύρου σε Lucida Console (κάντε κλικ πάνω αριστερά - Properties - Font).

    Αν ο υπολογιστής σας τρέχει Windows 7–10 με αγγλικές ρυθμίσεις, θα πρέπει να τις ρυθμίσετε στα ελληνικά, με την παρακάτω διαδικασία:
    Control Panel - Region (and Language) - Administrative - Change System Locale και από εκεί επιλέγουμε "Greek (Greece)".

    Σε υπολογιστή με λειτουργικό σύστημα Windows και Internet Explorer το αρχείο Exercise.jar σώζεται ως Exercise.zip. Τι να κάνω;

    Το πρόβλημα οφείλεται σε δυσλειτουργία (bug) του Internet Explorer. Κατά τη διαδικασία της φύλαξης επιλέξτε από την επιλογή "Save as type" το "All Files" και βεβαιωθείτε πως στην επιλογή "File name" γράφει "Exercise.jar". Εναλλακτικά, χρησιμοποιείστε έναν άλλο φυλλομετρητή όπως τον Firefox (http://www.mozilla.com/en-US/firefox/).

    Γιατί σε υπολογιστή με λειτουργικό σύστημα Linux η εκφώνηση εμφανίζεται με περίεργους χαρακτήρες;

    Καταρχήν, μπράβο που πειραματίζεστε με διαφορετικά λειτουργικά συστήματα! Δοκιμάστε να δώσετε την εντολή
    
    export LANG=el_GR
    
    πριν την εκτέλεση του Exercise.jar.

    Τι να κάνω αν μου εμφανιστεί το μήνυμα «Δεν βρέθηκε εγκαταστημένος μεταγλωττιστής»;

    Φροντίστε να θέσετε σωστά τις μεταβλητές περιβάλλοντος, όπως αναφέρεται στον οδηγό των ασκήσεων (https://docs.google.com/document/d/1-7XbmxX5ZhTrxFEAcoQcxQdqi2cnGeun/view).

    Τι να κάνω αν μου εμφανιστεί το μήνυμα «Can not find an installed compiler»;

    Φροντίστε να θέσετε σωστά τις μεταβλητές περιβάλλοντος, όπως αναφέρεται στον οδηγό των ασκήσεων (https://docs.google.com/document/d/1-7XbmxX5ZhTrxFEAcoQcxQdqi2cnGeun/view).

    Γιατί ο κωδικός που καταχώρισα δεν έγινε δεκτός από το σύστημα;

    1. Βεβαιωθείτε πως τρέχετε την έκδοση 1.7 της Java ή νεώτερη (βλ. προηγούμενη απάντηση).
    2. Βεβαιωθείτε πως τρέχετε τη φετινή έκδοση του συστήματος Jarpeb. Οι κωδικοί ασκήσεων του προηγούμενου χρόνου δεν ισχύουν.

      Μπορείτε να εκτελέσετε την εντολή

      
      java -jar Exercise.jar -version
      
      για να δείτε την έκδοση του συστήματος που έχετε στα χέρια σας. Η ημερομηνία της έκδοσης δεν πρέπει να είναι παλαιότερη από το Σεπτέμβριο του αντίστοιχου ακαδημαϊκού έτους.

    Σωστά καταχωρημένες ασκήσεις

    Χρονοσφραγίδα ΑΜ Άσκηση Βαθμός Διεύθυνση IP Αναγνωριστικό
    2025-10-06T21:40:17 8240156 1 10 [...].242.54.[...] 0085990221BD40A0952C737DC787D63E
    2025-10-08T01:43:21 8240116 1 10 [...].67.74.[...] 348CDFE50E9D48E5BAFE86154728D420
    2025-10-06T22:03:30 8240123 1 10 [...].164.124.[...] 34BC742582D44B5390F6DD81F07A5BDB
    2025-10-07T15:07:37 8240034 1 9 [...].84.142.[...] 3596E93EF9FB4821A45937BFD0682D69
    2025-10-07T14:27:47 8240112 1 10 [...].74.231.[...] 395272E4B8A94760ABCA9A2A3CBAB416
    2025-10-06T22:30:54 8240123 2 10 [...].164.124.[...] 43746F262908427AA042735A644B3F09
    2025-10-06T22:25:36 8240020 1 10 [...].217.174.[...] 46AF4E45BC604AA0B1A0EB499411450A
    2025-10-07T18:49:07 8230149 1 10 [...].87.158.[...] 51FCA513D1BA4CC1B2A605B18F947CCE
    2025-10-07T20:06:21 8240278 1 10 [...].87.224.[...] 54669802A439444695CB8E6DC795C2A6
    2025-10-07T00:35:50 8240080 1 10 [...].54.131.[...] 54BF90627EE14DA0B58F45BBB7261E82
    2025-10-07T16:04:42 8240105 1 10 [...].74.96.[...] 59BDAE79DC974C2DAADC5481A3675097
    2025-10-07T17:56:43 8240085 1 10 [...].54.18.[...] 5C44D18436E7457B8C324A271269550F
    2025-10-07T14:29:38 8240133 1 10 [...].87.112.[...] 636A8416EB2145FE94B5CE5DED310660
    2025-10-05T22:52:38 8230220 1 2 [...].75.216.[...] 8181E86E8B9C4A54823F4D5F1DD535B2
    2025-10-06T23:12:54 8240039 1 10 [...].150.218.[...] 93AE0602C953460D9761B2F482C6BBC7
    2025-10-07T18:09:22 8240240 1 10 [...].168.0.[...] B57C984D409B4ED78F3FC87F4824CC1D
    2025-10-08T02:44:40 8240138 1 10 [...].73.238.[...] BC8281F9A6704109A24565BF3FC462F0
    2025-10-06T20:52:22 8240128 1 10 [...].73.112.[...] BCBD8BAE1947460DBA6C3C9327EB65A5
    2025-10-06T20:01:14 8240067 1 8 [...].176.107.[...] CCC6CEBDCF0F4B408AC01F1CE2B1D5B1
    2025-10-07T00:55:40 8240164 1 10 [...].65.46.[...] D3ECC5F3C9A24520AA6EF55CFD4DBF7A
    2025-10-07T19:41:46 8240110 1 10 [...].59.127.[...] DCBB0607936245519A2BDA263AD413E5
    2025-10-06T23:50:46 8240247 1 10 [...].55.26.[...] E1CE783D13124E4A87F827D5DF2DC283
    2025-10-07T14:26:42 8240065 1 10 [...].131.76.[...] F10265CB288D423CB679012C7378CC76
    2025-10-07T17:35:51 8240042 1 8 [...].129.191.[...] F588B82723CF4072B2950C76A42FCD52
    2025-10-06T19:57:21 8240084 1 10 [...].217.178.[...] F86F39A066C945E3B407919DA0D7D079

    Βαθμοί ασκήσεων ανά Α.Μ.

    Α.Μ. Βαθμοί ατομικής άσκησης Μ.Ο. ατομικών ασκήσεων που έχουν παραδοθεί Μ.Ο. απαιτούμενων ατομικών ασκήσεων (1) Ομαδικές ασκήσεις
    8230149Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8230220Α1=2 2.02.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240020Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240034Α1=9 9.09.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240039Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240042Α1=8 8.08.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240065Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240067Α1=8 8.08.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240080Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240084Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240085Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240105Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240110Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240112Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240116Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240123Α1=10 Α2=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240128Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240133Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240138Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240156Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240164Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240240Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240247Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0
    8240278Α1=10 10.010.0 Ομ.1=0 Ομ.2=0 Αρχηγός=0

    Φοιτητές που παραδίδουν ασκήσεις: 24
    Μέσος όρος ατομικής άσκησης για φοιτητές που παραδίδουν ασκήσεις: 9.5
    Ατομικές ασκήσεις με προθεσμία παράδοσης: 1
    Μέσος όρος 1 ατομικών ασκήσεων για φοιτητές που παραδίδουν ασκήσεις: 9.5

    Λάθη στον έλεγχο του βαθμού

    Χρονοσφραγίδα ΑΜ Άσκηση Βαθμός Διεύθυνση IP Αναγνωριστικό

    Ενδιαφέρουσα βιβλιογραφία

    Θέματα εξετάσεων

    Πιλοτικά θέματα εξετάσεων

    Τα πιλοτικά θέματα σε μορφή PDF (έκδοση 1.1 - 2004.02.13).

    Για να βρείτε τις σωστές απαντήσεις αρκεί να μεταγλωττίσετε το πρόγραμμα με μερικές εντολές println στο τέλος.

    Εξεταστική περίοδος Φεβρουαρίου 2004

    Μια διατύπωση των θεμάτων σε μορφή PDF.

    Για να βρείτε τις σωστές απαντήσεις αρκεί να μεταγλωττίσετε το πρόγραμμα με μερικές εντολές println στο τέλος.

    Παράδειγμα προγράμματος

    class Exam {
        public static void main(String args[]) {
            int gargoyle = 5;
            int i = 2;
            int dobby = 5;
            while (i < 11) {
                i = i + 4;
                gargoyle = gargoyle + 2;
            }
            for (i = 2; i < 11; i = i + 4)
                dobby = dobby + 2;
            int dockhead = 6;
            try {
                dockhead = 11;
                if (dockhead == 11)
                    throw new Exception();
                dockhead = 21;
            } catch (Exception e) {
                dockhead = 16;
            }
            Ingluvial y = new Ingluvial(2);
            Ingluvial z = new Ingluvial();
            Ingluvial w = y;
            Aneurism x = new Aneurism();
            Ingluvial u = y; Aneurism v = x;
            int toeplate = 11;
            int tubeful = z.m() + 2 * x.m() + 3 * x.t();
            int fenrir = y.naumk;
            toeplate = 20;
            if (w.naumk != y.naumk)
                toeplate += 1;
            else
                toeplate += 10;
            String s = "footful" + "hexameron";
            int unparty = s.substring(1, 13).length();
            int umbelwort = Aneurism.count;
            int arusa = 23;
            Ingluvial r = new Aneurism();
            arusa = r.m();
            int smethe = 25;
            boolean array[] = new boolean[16];
            try {
                if (array[24])
                    smethe = 54;
                else
                    smethe = 44;
            } catch (ArrayIndexOutOfBoundsException e) {
                smethe = 31;
            }
        }
    }
    class Ingluvial {
        public int naumk;
        private char kahan;
        Ingluvial() {naumk = 11; }
        Ingluvial(int v0) { naumk = v0; }
        public int t() { return 1; }
        public int m() { return 37; }
    }
    class Aneurism extends Ingluvial {
        public static int count = 6;
        Aneurism() { count += 6; }
        public int n() { return naumk; }
        public int m() { return 15; }
    }
    

    Μεταβλητές

    Προσοχή

    Τα παραπάνω θέματα μοιάζουν αρκετά με τα πιλοτικά θέματα. Αυτό είναι απίθανο να συμβεί σε επόμενες εξεταστικές περιόδους.

    Εξεταστική περίοδος Σεπτεμβρίου 2005

    Μια διατύπωση των θεμάτων σε μορφή PDF.

    Για να βρείτε τις σωστές απαντήσεις αρκεί να μεταγλωττίσετε το πρόγραμμα με μερικές εντολές println στο τέλος.

    Παράδειγμα προγράμματος

    class Exam {
        static boolean ba[] = new boolean[6];
        public static void main(String args[]) {
            int lunula = 12;
            for (int i = 3; i < 11; i += 1)
                if (i % 3 == 1)
                    lunula = lunula + 2;
            int upglean = upslant(4, 9);
            String s = "alfet";
            s += "ceras" + "alfet";
            int chinaware = (s.substring(1, 8) + s).length();
            int bedstock = 6;
            try {
                bedstock = 10;
                if (bedstock == 10)
                    throw new Exception();
                bedstock = 20;
            } catch (Exception e) {
                bedstock = 15;
            }
            Bitted y = new Bitted(2);
            Bitted z = new Bitted();
            Bitted w = y;
            Samantha x = new Samantha();
            Bitted u = y; Samantha v = x;
            int megachile = 11;
            int powerless = z.m(16) - 2 * x.m(18) - 3 * x.t();
            int peccable = y.kangaroo;
            megachile = 23;
            if (w.kangaroo != y.kangaroo)
                megachile += 2;
            else
                megachile += 12;
            int archwise = Samantha.count;
            int drumming = 26;
            int ai = 0;
            ba[ai++] = false; ba[ai++] = true; ba[ai++] = true;
            ba[ai++] = true; ba[ai++] = true; ba[ai++] = true;
            for (int i = 0; i < ba.length - 1; i++) {
                if (!ba[i]) drumming += 11;
                if (ba[i] || ba[i + 1]) drumming += 9;
                if (ba[i] && ba[i + 1]) drumming -= 3;
            }
            int unhumble = 25;
            Bitted r = new Samantha();
            unhumble = r.m(17);
        }
        private static int upslant(int a, int b) {
            int loc1 = a;
            int loc2 = b;
            return (3 * loc1 + 2 * loc2 * loc2);
        }
    }
    class Bitted {
        public int kangaroo;
        Bitted() {kangaroo = 11; }
        Bitted(int v0) { kangaroo = v0 + 1; }
        public int t() { return 2 * 2; }
        public int m(int v) { return 31 - v; }
    }
    class Samantha extends Bitted {
        public static int count = 5;
        Samantha() { count += 7; }
        public int m(int v) { return v - 13 * 2; }
    }
    

    Μεταβλητές

    Περιεχόμενα