Download as pdf or txt
Download as pdf or txt
You are on page 1of 331

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

(Java)
Ιωάννης Βιόλος

Χαροκόπειο Πανεπιστήμιο
1

1. Εισαγωγή

1
Στόχοι
 Όσοι ολοκληρώνουν το μάθημα με επιτυχία να:
 Γνωρίζουν καλά τις βασικές αρχές του αντικειμενοστρεφούς
προγραμματισμού: αντικείμενα, κλάσεις, γνωρίσματα,
μεθόδους, αφαιρετικούς τύπους δεδομένων, ενθυλάκωση,
κληρονομικότητα, διεπαφές
 Είναι εξοικειωμένοι με βασικές τεχνικές του προγραμματισμού με
Java όπως: χειρισμός εξαιρέσεων, πολυνηματισμός, χρήση
εφαρμογών τρίτων, χειρισμός συλλογών αντικειμένων, σύνδεση
με ΒΔ και αρχεία
 Μπορούν να καθορίζουν τη λογική για την επίλυση ενός
προβλήματος σύμφωνα με το υπόδειγμα του
αντικειμενοστρεφούς προγραμματισμού και κατόπιν να είναι σε
θέση να την υλοποιούν σε μια ολοκληρωμένη εφαρμογή
 Πώς να τεκμηριώνουν και να προετοιμάζουν ένα επαγγελματικό
πρόγραμμα χρησιμοποιώντας τα εργαλεία της Java

Θεματολογία
 Εισαγωγή (1ο μάθημα)
 Σύνδεση με το δομημένο προγραμματισμό
 Κλάσεις: ενθυλάκωση και ελεγχόμενη πρόσβαση, στατικά μέλη
 Αντικείμενα: σχεδίαση αντικειμένων, αρχικοποίηση και κατασκευαστές
 Μέθοδοι (2ο μάθημα)
 γνωρίσματα, παράμετροι, τοπικές μεταβλητές, αποτελέσματα και τιμές
επιστροφής
 υπερφόρτωση μεθόδων και κατασκευαστών
 Κληρονομικότητα και σύνθεση
 υπέρβαση μεθόδων
 πολυμορφισμός
 Αφηρημένες κλάσεις και μέθοδοι. Διεπαφές.

3
Θεματολογία
 Χρήση κώδικα τρίτων (3ο-4ο μάθημα)
 Διαχείριση εξαιρέσεων
 Διαχείριση αρχείων (5ο μάθημα)
 Συλλογές δεδομένων (6ο μάθημα)
 Διάσχιση, Εισαγωγή, Διαγραφή, Αναζήτηση
 Σύνδεση με ΒΔ, καταχώρηση δεδομένων (7ο μάθημα)
 Γραφικά και χειρισμός γεγονότων (8ο-9ο μάθημα)
 Πολυνηματισμός (10ο μάθημα)
 Τεκμηρίωση εφαρμογών, Java EE (11ο μάθημα)
 Επίλυση σφαλμάτων (12ο μάθημα)
 Παρουσίαση εργασιών (13ο μάθημα)

Βιβλιογραφία
 Java προγραμματισμός : 8η έκδοση, H. M. Deitel , P. J.
Deitel (μτφρ. Χρυσούλα Απ. Κουτρούμπα).
Εκδ. Γκιούρδας Μ. 2010. Αθήνα
 Πλήρες εγχειρίδιο της Java 6, Laura Lemay & Rogers
Cadenhead. Εκδ. Γκιούρδας. 2007. Αθήνα.
 Εισαγωγή στην Java, 3η έκδοση, Γ. Λιακέας.
Εκδ. Κλειδάριθμος ΕΠΕ. 2008. Αθήνα
 Στο e-class: διαφάνειες και ασκήσεις που δίνονται στα
εργαστήρια

7
Ας ξεκινήσουμε

10

Τι θα πρέπει να ξεχάσουμε
 Τη λογική του δομημένου προγραμματισμού
 Μια εφαρμογή Java χρησιμοποιεί τις 4 δομές:
 Ακολουθία
 Επιλογή
 Επανάληψη
 Αναδρομή
αλλά δεν στηρίζεται σε αυτές
 Η εφαρμογή μας δεν πρέπει να είναι μια σειρά
από μεθόδους που η μια καλεί την άλλη και
όλες μαζί διαχειρίζονται δεδομένα.
11
Γιατί δεν αρκεί ο δομημένος
προγραμματισμός
 Τα δεδομένα δεν παριστούν πάντοτε οντότητες του
πραγματικού κόσμου
 Τα δεδομένα είναι πολύπλοκα και έχουν εξαρτήσεις
 Όταν αλλάξουν τα δεδομένα χρειάζονται σημαντικές
αλλαγές σε όλο το πρόγραμμα
 Είναι προτιμότερο να σχεδιάσουμε την εφαρμογή γύρω
από οντότητες που αντιλαμβανόμαστε:
Αντικειμενοστρεφής προγραμματισμός

12

Τι θα πρέπει να θυμόμαστε
 Τα πάντα είναι αντικείμενα. Τα αντικείμενα περιέχουν:
 Κατάσταση: δεδομένα, χαρακτηριστικά, μεταβλητές
 Συμπεριφορά: λειτουργίες, μεθόδους
 Ταυτότητα: είναι μοναδικά
 Κάθε αντικείμενο έχει ένα τύπο (κλάση). Ο τύπος περιγράφει τα
δεδομένα που μπορεί να αποθηκεύει (όχι όμως τις τιμές των
μεταβλητών) και τις λειτουργίες που μπορεί να επιτελεί το
αντικείμενο.
 Όλα τα αντικείμενα ίδιου τύπου μπορούν να λαμβάνουν τα ίδια
μηνύματα.
 Κάθε αντικείμενο μπορεί να αποτελείται από άλλα αντικείμενα.
 Μια εφαρμογή σε Java είναι μια συλλογή αντικειμένων που
επικοινωνούν μεταξύ τους με μηνύματα.
13
κλάσεις και αντικείμενα
 Αφηρημένοι τύποι δεδομένων (κλάσεις)
 κλάση: Ένα σύνολο αντικειμένων με κοινά
χαρακτηριστικά (data elements) και λειτουργικότητα
(functionality)
 Οι κλάση ορίζεται μία φορά και μπορούμε να
δημιουργούμε όσα στιγμιότυπα θέλουμε.
 Οι αφηρημένοι τύποι λειτουργούν όπως οι συνήθεις
τύποι δεδομένων
 Μεταβλητές κάποιου τύπουαντικείμενα (objects) ή
στιγμιότυπα (instances) της κλάσης

14

Ορισμός κλάσης Στόχο έχουν να


class Human { χειρίζονται τα
boolean alive; δεδομένα, να τα
int age; Δεδομένα τροποποιούν ή να
String name; επιστρέφουν τις τιμές
void born()
αυτών, σε όποιον τις
{ ζητήσει
alive = true;
}
void speak() Λειτουργίες
{

}
System.out.println(“Hi!”); Μέθοδοι
void incr_age()
{
age = age +1;
}
}
Κλήση μεθόδου = Αποστολή Μηνύματος
15
Γνωρίσματα - Δεδομένα
 Τα δεδομένα μπορεί να είναι απλού
τύπου: int, boolean, double, float, long
κλπ.
 Μπορεί να είναι σύνθετου τύπου. Δηλαδή
αντικείμενα μιας άλλης κλάσης: String,
Date, Human

Δεν είναι απλός


τύπος; Είναι
κλάση; 16

Λειτουργίες - Μέθοδοι
 Οι μέθοδοι περιγράφουν τις λειτουργίες της κλάσης πάνω στα
δεδομένα. Είναι ο τρόπος με τον οποίο επικοινωνούν τα αντικείμενα
διαφόρων κλάσεων μεταξύ τους.
 Μία μέθοδος στη Java έχει:
 Όνομα
 Τύπο επιστροφής
 Λίστα ορισμάτων
 Το σώμα της μεθόδου πρέπει στο τέλος να επιστρέφει τιμή με
χρήση της εντολής return
 Αν ο τύπος επιστροφής είναι void δεν χρειάζεται return.
returnType methodName( /* λίστα ορισμάτων */ ) {
/* σώμα μεθόδου */
return …;
}

17
Δημιουργία κλάσης Human
 Τα πάντα στην Java είναι αντικείμενα κάποιας κλάσης.
Για το λόγο αυτό σε κάθε μας πρόγραμμα χρειάζεται να
ορίσουμε τουλάχιστον μία κλάση. Η κλάση αυτή θα έχει
το ίδιο όνομα με το αρχείο που θα την αποθηκεύσουμε.
π.χ. Η κλάση Human θα πρέπει να αποθηκευθεί στο
αρχείο Human.java
 Kλήση του Java compiler
 javacHuman.java
παράγει ένα αρχείο Human.class

18

1. Αρκεί μόνο η κλάση Human;


 Θεωρητικά αρκεί. Αλλά είναι προτιμότερο:
 Η εφαρμογή που θα διαχειρίζεται αντικείμενα της κλάσης
Human θα είναι ένα java application σε μια δεύτερη
κλάση με το όνομα Demo στο αρχείο Demo.java
 Για να μπορέσει η εφαρμογή Demo να εκτελεστεί πρέπει
να έχει μια μέθοδο με το όνομα main.
 Η μέθοδος αυτή θα φτιάχνει αντικείμενα της κλάσης
Human και θα καλεί τις μεθόδους τους.

19
Αντικείμενο = Χαρακτηριστικά + Μέθοδοι
 Για να χρησιμοποιήσουμε ένα
αντικείμενο πρέπει πρώτα να Human john = new Human();
το δημιουργήσουμε // Δημιουργείται ένας human
 Για να στείλουμε μήνυμα σε
ένα αντικείμενο, δίνουμε το john.speak();
όνομα του αντικειμένου μία
john.age=0;
τελεία και το όνομα της
διαθέσιμης λειτουργίας Human
 Παρόμοια δίνουμε τιμή στα age
χαρακτηριστικά ενός alive
αντικειμένου born()
 To σύνολο των διαθέσιμων speak()
λειτουργιών ενός αντικειμένου incr_age()
αποτελεί τη διεπαφή του με τα
υπόλοιπα αντικείμενα
20

Τα αντικείμενα και η μνήμη


 Όταν δημιουργούμε ένα αντικείμενο στη Java,
δεσμεύουμε γι’ αυτό μνήμη και χρησιμοποιούμε πάντα
μια αναφορά σ’ αυτό.
 Η εντολή: Human John;
ορίζει την αναφορά John σε ένα Human αντικείμενο,
αλλά δεν δεσμεύει μνήμη γι’ αυτό.
 Η εντολή: Human John = new Human();
δεσμεύει μνήμη για ένα αντικείμενο Human και ορίζει μια
αναφορά John σ’ αυτό.

21
Κλήση μεθόδων
 Μια μέθοδος καλείται από κάποιο αντικείμενο (συνήθως)
π.χ.
Human John= new Human();
John.born();
John.speak();
John.setAge(10);
 Μπορούμε να αναφερθούμε απευθείας στα δεδομένα
του αντικειμένου.
John.age=15;
int z=John.getAge();

22

Η μέθοδος main
 Η μέθοδος αυτή πρέπει να είναι διαθέσιμη σε όλες τις κλάσεις άρα
να δηλωθεί public.
 Η μέθοδος πρέπει να μπορεί να κληθεί χωρίς να έχει δημιουργηθεί
αντικείμενο της συγκεκριμένης κλάσης, άρα να δηλωθεί static.
 Τέλος πρέπει να παίρνει ορίσματα (παραμέτρους) από τη γραμμή
εντολών και δεν είναι απαραίτητο να επιστρέφει κάποια τιμή.
 Έτσι προκύπτει η ανάγκη για μια μέθοδο στην κύρια κλάση της
εφαρμογής μας που ορίζεται ως εξής:
class Demo{
public static void main(String args[]){
/* σώμα της main*/
Human john=new Human();
john.born();
john.speak();
}
}
23
Μεταγλώττιση και εκτέλεση
 Κλήση του Java compiler
 javacDemo.java
Παράγει ένα αρχείο Demo.class
 Πρέπει τo Human.class να είναι στον ίδιο
φάκελο
 Κλήση του Java Virtual Machine
 java
Demo
τυπώνει το μήνυμα στην οθόνη

24

2. Έλεγχος πρόσβασης - Ενθυλάκωση

 Είναι καλή πρακτική να μην επιτρέπουμε πρόσβαση σε


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

25
Τα όρια μιας κλάσης
 Υπάρχουν τρεις τύποι πρόσβασης στα μέρη μιας κλάσης: public,
private, και protected.
 Δημόσια (public), τα μέρη είναι διαθέσιμα σε όλους
 Ιδιωτική (private), τα μέρη είναι διαθέσιμα μόνο στην ίδια την κλάση
και τις λειτουργίες της
 Προστατευμένη (protected), τα μέρη είναι διαθέσιμα στην κλάση και
σε όσες κλάσεις την κληρονομούν.
 Δεδομένη (default) πρόσβαση, όταν δεν δηλώνεται κάποια από τις
προηγούμενες, τα μέρη είναι διαθέσιμα στην κλάση και σε όλες τις
υπόλοιπες κλάσεις της ίδιας εφαρμογής (του ίδιου package)

26

Παράδειγμα
 Αν δε δηλώσουμε κάτι διαφορετικό, η κλάση Demo έχει πρόσβαση και στις
μεθόδους και στα χαρακτηριστικά των αντικειμένων τύπου Human.
John.age=15;  John.setAge(15);
 Άν όμως κάνουμε το age private
class Human{
private int age;

}
 Τότε η Demo δεν μπορεί να αναφερθεί στο age μέσα από αντικείμενα τύπου
Human.
John.setAge(15);
 Αντίθετα εντός της Human, μπορούμε να αναφερθούμε στο age.
π.χ. Στο σώμα των setAge και getAge
 Το ίδιο μπορεί να γίνει και για τις μεθόδους μιας κλάσης

27
Μέθοδοι
 Οι μέθοδοι μιας κλάσης μπορεί να είναι:
 Μέθοδοι πρόσβασης (get) που διαβάζουν τις τιμές
των χαρακτηριστικών
 Μέθοδοι τροποποίησης (set) που τροποποιούν τις
τιμές των χαρακτηριστικών
 Μέθοδοι κατασκευής (constructor) που αρχικοποιούν
τις τιμές των χαρακτηριστικών κατά τη δημιουργία των
αντικειμένων.
 Άλλες βοηθητικές μέθοδοι.

28

Νέος ορισμός κλάσης


class Human { void speak()
private boolean alive; {
private int age; System.out.println(“Hi!”);
void Human() }
{
void incr_age()
alive = true;
{
age = 0
age = age +1;
}
int getAge()
}
{ }
return age;
}
void setAge(int a)
{
age=a;
}
29
Συμπερασματικά
 Σε ένα πρόβλημα:
 Προσπαθώ να δω: ποια αντικείμενα εμπλέκονται, τι δεδομένα
έχει το καθένα από αυτά και ποιες λειτουργίες επιτελεί και στη
συνέχεια ορίζω τις αντίστοιχες κλάσεις
 Σε μια κλάση
 Ορίζω χαρακτηριστικά: name, surname, age
 Ορίζω μεθόδους πρόσβασης: getName(), setName() ..
 Ορίζω άλλες βοηθητικές μεθόδους
 Στο τέλος
 Ορίζω μια κλάση με μια μέθοδο main()
 Η κλάση αυτή εκτελεί το πρόγραμμά μου. Μόνο που δεν περιέχει
όλη τη λύση. Κάποια πράγματα τα αναλαμβάνουν τα αντικείμενα

30

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


 Για τους βασικούς τύπους
(primitive types) η Java δημιουργεί
μεταβλητές και όχι αναφορές στη
μνήμη.
 Δήλωση μεταβλητής
int age;
//(τύπος) (Όνομα Μεταβλητής)
 Υπάρχουν αντίστοιχες τάξεις
(wrapper types) για καθέναν από
αυτούς, π.χ.
char c = 'x';
Character C = new Character(c);
Character C = new Character('x');

31
Διαφορές
Απλός τύπος Wrapper type
 τιμή  αντικείμενο
double d= 10.50; Double d1 = new Double(10.50);
 ένας μόνο τρόπος  πολλοί τρόποι αρχικοποίησης
αρχικοποίησης Double d2=new Double(“10.60”);
Double d3=new Double(10.50);
 δεν έχει μεθόδους  έχει μεθόδους
int x=d.intValue(); // x = 10
int a = d1.compareTo(d2); // a<0
 σύγκριση τιμών  σύγκριση αντικειμένων
if (d==10.50) true if (d1==d3) false
if (d1.equals(d3) true
32

Δηλώσεις μεταβλητών παντού


 Οι δηλώσεις των μεταβλητών γίνονται παντού, όχι μόνο
στην αρχή ενός block
{
for ( int i=0; i< 20; i++) {
System.out.println(“Hi!”);
Char ch=’A’;
}
double pi = 3.14159;
}
 Παραμένουν σε ισχύ μέχρι την έξοδο από το block που
τις περιβάλλει.
 Οι μεταβλητές πρέπει να αρχικοποιούνται πριν την
χρήση τους (Ο compiler της Java επιβάλλει κάτι τέτοιο).

33
Εμβέλεια μεταβλητών/αντικειμένων
 Κάθε μεταβλητή έχει ισχύ εντός του μπλοκ στο οποίο ορίζεται και σε κάθε
μπλοκ που υπάρχει μέσα σε αυτό. {
{
int x = 12;
int x = 12;
/* μόνο το x υπάρχει */ {
{ int x = 96; /* Δεν επιτρέπεται
int q = 96;
/* υπάρχουν τα x & q */ γιατί έχει ήδη οριστεί το x*/
} }
q=150 /* δεν επιτρέπεται }
γιατί μόνο το x υπάρχει */
/* εκτός της εμβέλειας του q */
}

34

attribute

Σε μια κλάση Input parameters

method
return type

class Human { System.in System.out


boolean alive;
int age; name
String name;
phrase void
void speak(String phrase)
{ speak
System.out.println(“Hi!”); name,
System.out.println(“My name is ”+name); phrase
System.out.print(“You asked me to say:”);
System.out.println(phrase); age
}
int getAgeAfter(int months){ months return type
int years=months/12; getAgeAfter
int ageafter=age+years;
return ageafter;
}
age
void setAge(){
Scanner keyboard=new Scanner(System.in); void
System.out.println(“How old are you?”);
age=keyboard.nextInt(); setAge
} System.in System.out
}
35
Προαγωγή τύπου
 Σε αριθμητικές εκφράσεις που περιλαμβάνουν διάφορους τύπους,
όλοι οι τύποι προάγονται στον πιο ευρύ οπό όλους.
short s; int i; double d;
System.out.println(s+i+d); //result is double
 Η διαίρεση ακεραίων δίνει μόνο το ακέραιο μέρος;
int years=42/12;  years=3
double years= 42/12;  years=3.0
double years=(double)42/12;  years=3.5
 Υπολογισμοί που αφορούν τους τύπους byte, short, char
προάγονται σε υπολογισμούς με int:
short s = 4; int t = 6;
s = (short ) ( s + t ); //cast required

36

Στένεμα και διεύρυνση τύπων


 Η C ελεύθερα κάνει αναθέσεις μεταξύ αριθμητικών τύπων, αλλά η
Java απαιτεί casting για την ανάθεση ενός τύπου σε έναν άλλο
μικρότερο.
 Το στένεμα γίνεται από περισσότερο σε λιγότερο πλούσιο τύπο
Πιθανή απώλεια πληροφορίας, γι’αυτό χρειάζεται το casting
π.χ. ανάθεση short σε byte, double σε float
 Το πέρασμα παραμέτρων είναι το ίδιο σαν την ανάθεση.
 Δεν μπορούμε να κάνουμε τίποτα cast σε boolean.
Λάθος: boolean b = (boolean) num;
Σωστό: boolean b = (num ! = 0 );

37
Θεμελιώδεις περικλείουσες κλάσεις

 Byte, Boolean, Short, Integer, Long, Float, Double


 Μπορούν να υπάρχουν επειδή η Java είναι case-sensitive
 H κάθε μια τους είναι wrapper κλάση για έναν απλό τύπο
 Δεν μπορεί να αλλάξει η τιμή τους (τίθεται μόνο στον
constructor και δεν υπάρχουν μέθοδοι που να την
αλλάζουν)
 Παράδειγμα
Integer i = new Integer(15);
Float f = new Float(“3.15169”);
int k = i.intValue();
double d = f.floatValue();

38

String type
 Οι σταθερές String περικλείονται με διπλά εισαγωγικά
String s = “a string literal”;
String s = new String(“A string literal”);
 Οι τελεστές + και += υπερφορτώνονται για την ένωση
δύο ή περισσοτέρων Strings.
s = “Welcome to” + 1998 + “!”;
 Οτιδήποτε μπορεί να μετατραπεί σε αναπαράσταση
string (όλοι οι primitive τύποι και τα αντικείμενα)
 Μεγάλη λειτουργικότητα
εύρεση μήκους, ανάκτηση συγκεκριμένων χαρακτήρων
αναζήτηση για χαρακτήρες και substrings
ένωση strings, εύρεση/αντικατάσταση, σύγκριση μεταξύ
strings

39
String type
 Τα Strings είναι αμετάβλητα
Οι χαρακτήρες που τα αποτελούν θέτονται στον constructor και
δεν αλλάζουν
 Αντιπροσωπευτικές μέθοδοι
 int length ()
 char charAt (int index)
 int indexOf (char ch)
 int indexOf (String s)
 boolean equals (String s)
 String toLowerCase ()
 String replace (char oldChar, char newChar)
 String concat (String s)
 String substring (int offset, int endIndex)
 String[] split (String regex)

40

Τελεστές

41
Τελεστές
 πρόσθεση (+)
 αφαίρεση(-)
 πολλαπλασιασμός (*)
 διαίρεση(/) (για ακεραίους επιστρέφει το ακέραιο μέρος του
αποτελέσματος)
 υπόλοιπο διαίρεσης (%)
 ανάθεση τιμής σε μεταβλητή(=)
 x+=4;
 x-=a;
 Τελεστές προσαύξησης και μείωσης:
x=a++; x=++a; x=a--; x=--a;

42

Τελεστής ανάθεσης
 Δημιουργώντας ένα αντικείμενο, public class Complex {
ουσιαστικά δεσμεύουμε μνήμη και private double x,y;
δημιουργούμε μια αναφορά σε αυτή.
public double real() { return x; }
Complex c1 = new Complex();
Complex c2 = new Complex(); public double imag() { return y; }
c1.setReal(9); public void setReal(double u) {x=u; }
c1.setImag(47); public void setImag(double v) {y=v; }
c2=c1;
}
 Όταν αναθέσουμε ένα αντικείμενο (c1)
σε ένα άλλο (c2), ουσιαστικά έχουμε
δύο αναφορές στην ίδια θέση μνήμης
c2
(αυτή που δεσμεύτηκε για το c1)
c2 = c1; c1
 To φαινόμενο αυτό ονομάζεται aliasing x=9.0, y=47.0
(συνωνυμία) public double real()
public double imag()
public void setReal(double u)
public void setImag(double v)

43
Σχεσιακοί τελεστές
 Επιστρέφουν true ή false Integer n1 = new Integer(47);
 Ισότητα (==) Integer n2 = new Integer(47);
 Ανισότητα (!=) System.out.println(n1 ==n2);
 Μικρότερο/Μεγαλύτερο //τυπώνει false
(>,<,<=,>=)
System.out.println(n1 != n2);
 Για objects οι τελεστές
συγκρίνουν αναφορές και όχι //τυπώνει true
τα ίδια τα αντικείμενα. System.out.println(n1.equals(n2));
 Για να συγκρίνουμε //τυπώνει true
αντικείμενα χρησιμοποιούμε
τη μέθοδο equals().

44

Λογικοί τελεστές
 Επιστρέφουν true ή false
 AND (&&)
 OR (||)
 NOT (!)
 Bitwise operators
 AND (&) π.χ. 3&5  00000011 & 00000101  00000001 1
 OR (|)
 XOR (^)
 NOT (~)
 right-shift (>>), left-shift (<<), unsigned right shift (>>>)

45
Άλλοι τελεστές
 Τριαδικός (ternary) τελεστής
boolean-exp ? valueIfTrue : valueifFalse
π.χ.
int x=55;
String z= (x%2==1?"Περιττός":"Άρτιος");
 Τελεστής ; (comma)
Χρησιμοποιείται μόνο στη λίστα παραμέτρων του for
 Τελεστής πρόσθεσης String (+)
int x = 0, y = 1, z = 2;
String sString = "x, y, z ";
System.out.println(sString + x + y + z);
 Τελεστές μετατροπής (casting)
int i = 200;
long l = (long)i;
long l2 = (long)200;

46

Προτεραιότητες

47
H equals στις κλάσεις χρήστη
 Ορίζοντας τη μέθοδο equals καθορίζουμε τον
τρόπο με τον οποίο θα συγκρίνονται τα
αντικείμενα της κλάσης μας
public class Complex {
private double x,y;

public boolean equals(Complex c) {
if (x==c.x && y==c.y)
return true;
else return false;
}
}

48

Έλεγχος ροής
προγράμματος

49
if - else
if(συνθήκη εισόδου) public class IfElse {
public int test(int testval, int target) {
εντολές int result = 0;
else if(συνθήκη εισόδου) if(testval > target)
result = +1;
εντολές else if(testval < target)
else result = -1;
else
εντολές result = 0; // Match
return result;
}
}

50

return
 To return public class IfElse2 {
 καθορίζει την τιμή public int test(int testval, int target){
που θα επιστρέψει int result = 0;
μια μέθοδος if(testval > target)
 διακόπτει τη ροή return +1;
εκτέλεσης της else if(testval < target)
μεθόδου και return -1;
επιστρέφει την τιμή else
return 0; // Match
}
}

51
while & do-while
while(συνθήκη εισόδου) public class WhileTest {
εντολές public static void main(String[] args) {
double r = Math.random();
while(r < 0.5)
{ System.out.println(r);
r = Math.random();
}
do do
εντολές { System.out.println(r);
while(συνθήκη συνέχισης); r = Math.random();
} while(r < 0.5);
To statement εκτελείται }
τουλάχιστον μία φορά }

52

for
 for(αρχικοποίηση; συνθήκη τερματισμού; βήμα)
{… εντολές …}
 public class ListCharacters {
public static void main(String[] args) {
for( char c = 0; c < 128; c++)
if (c != 26 ) // ANSI Clear screen
System.out.println("value: " + (int)c +" character: " + c);
}
}
 public class CommaOperator {
public static void main(String[] args) {
for(int i = 1, j = i + 10; i < 5; i++, j = i * 2) {
System.out.println("i= " + i + " j= " + j);
}
}
}

53
break / continue
 To break διακόπτει την public class BreakAndContinue {
εκτέλεση και βγαίνει από public static void main(String[] args)
{
το βρόχο
for(int i = 0; i < 100; i++) {
 Το continue διακόπτει if(i == 74) break;
την εκτέλεση της // Out of for loop
συγκεκριμένης if(i % 9 != 0) continue;
επανάληψης και
// Next iteration
συνεχίζει από την αρχή
System.out.println(i);
του βρόχου
}
 Προσοχή στους }
βρόχους που δεν }
τερματίζουν

54

Επανάληψη και αναδρομή


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

55
Παράδειγμα με παραγοντικό

 Ν!=Ν*(Ν-1)*(Ν-2)*…*1  Ν!=Ν*(Ν-1)!
 Επαναληπτικό  Αναδρομικό
long factorial (int n){ long factorial (int n){
long result = 1; if (n<=1)
for ( int i =n; i>1; i--) return 1;
result *=i; return n * factorial(n-1);
return result; }
}

56

Γνωρίσματα κλάσης

57
static γνωρίσματα- μέθοδοι

 Αν ένα γνώρισμα είναι κοινό για όλα τα αντικείμενα μιας κλάσης τότε
δεσμεύουμε μια φορά χώρο για όλα τα αντικείμενα.
 Κατά τη δήλωση της κλάσης, τη δηλώνουμε static. Το γνώρισμα αυτό θα
δημιουργηθεί μία φορά μόλις δηλωθεί το πρώτο αντικείμενο αυτής της
κλάσης και θα μπορεί να χρησιμοποιείται από κάθε αντικείμενο της ίδιας
κλάσης.
π.χ. static float bonus;
 Αν θέλουμε να αναφερθούμε στο γνώρισμα αυτό, μπορούμε απ’ ευθείας
μέσω της κλάσης:
π.χ. Human.bonus=100,00;
 Παρόμοια ισχύουν και για τις μεθόδους.
π.χ. static setBonus(float b)
Human.setBonus(200,00);
 Τα static μέλη μπορούμε να τα καλούμε είτε απ’ευθείας μέσω της κλάσης
είτε μέσω των αντικειμένων που δημιουργούμε. Οι static μέθοδοι έχουν
πρόσβαση στα static μέλη της κλάσης.

58

Final γνωρίσματα
 Πρακτικά: final = μόνο για ανάγνωση
 Αν ένα γνώρισμα δηλωθεί final, τότε λειτουργεί ως σταθερά που
 πρέπει να αρχικοποιηθεί
 και δεν αλλάζει τιμή
 Αν η παράμετρος εισόδου μιας μεθόδου δηλωθεί final τότε δεν
μπορεί να αλλάξει τιμή στο σώμα της μεθόδου.
 public void setHour(final int hrs)
 Αν ένα αντικείμενο δηλωθεί final τότε το όνομα του αντικειμένου θα
αναφέρεται πάντα στο ίδιο αντικείμενο.
 Αν μια κλάση δηλωθεί final τότε δεν μπορεί να κληρονομηθεί από
άλλη κλάση.

59
Γνωρίσματα static και final
 O πιο αποτελεσματικός τρόπος για να υλοποιηθούν σταθερά
γνωρίσματα μίας κλάσης είναι ως static final:
public class Time {
private static final int NumHours = 24;
public static final int NumMinutes = 60;
}
 Μπορούν να είναι private αν πρόκειται να χρησιμοποιηθούν μόνο
εσωτερικά
 Έχουν μόνο μία θέση αποθήκευσης όσα και αν είναι τα στιγμιότυπα
μιας κλάσης και αυτή είναι αμετάβλητη.
double totalminutes=280;
double hours=totalminutes/Time.NumMinutes;
double minutes=totalminutes-hours*Time.NumMinutes;

60

Μέθοδοι

61
Δομή μεθόδου
πρόσβαση τύποςΕπιστροφής όνομαΜεθόδου (τυπος1 παράμετρος1, …)
{

}

public double addDouble (double num1, double num2)


{
return num1+num2;
}

62

Βασικές μέθοδοι
class Human {
private boolean alive;
 Μέθοδοι πρόσβασης private int age;
private String name;
getAttribute, setAttribute public void setAlive(boolean aAlive)
{
για ανάγνωση, ενημέρωση alive=aAlive;
αντίστοιχα }
public boolean getAlive()
{
 Μέθοδος toString }
return alive;

Επιστρέφει μια String …


public String toString(){
περιγραφή του αντικειμένου return name+" “+age +" “ +alive;
}

public Human(boolean aAlive, int aAge, String aName){
alive=aAlive;
 Μέθοδος αρχικοποίησης: age=aAge;
Κατασκευαστής - Constructor }
name=aName;

} 63
2. Μέθοδοι

Περιεχόμενα
 Μέθοδοι
 Πέρασμα αντικειμένου σε μέθοδο
 Υπερφόρτωση μεθόδων
 Μέθοδοι κατασκευαστές
 Υπερφόρτωση κατασκευαστών
 Επαναχρησιμοποίηση κώδικα
 Σύνθεση και κληρονομικότητα
 Πολυμορφισμός
 Αφηρημένες κλάσεις
 Διεπαφές

2
Μέθοδοι

Δομή μεθόδου
πρόσβαση τύποςΕπιστροφής όνομαΜεθόδου (τυπος1 παράμετρος1, …)
{

}

public double addDouble (double num1, double num2)


{
return num1+num2;
}

4
Κλήση και αποτέλεσμα
 Όταν καλούμε μια μέθοδο αυτή
 είτε επιστρέφει μια τιμή
π.χ. public String getName(){…}
 είτε δεν επιστρέφει τίποτε
π.χ. public void setName(String n){…}
 Για να καλέσουμε μια μέθοδο, (συνήθως) χρειαζόμαστε ένα
αντικείμενο της αντίστοιχης κλάσης
 Human h1=new Human();
 h1.setName(“John”);
 Όταν η μέθοδος επιστρέφει τιμή τότε πρέπει να την κρατάμε σε μια
προσωρινή μεταβλητή. Διαφορετικά η επιστρεφόμενη τιμή χάνεται
 String temp = h1.getName();

static μέθοδοι
 Καλούνται απευθείας μέσω της κλάσης
ή μέσω αντικειμένων της κλάσης
 Οι static μέθοδοι έχουν πρόσβαση στα
static μέλη της τάξης

6
Πέρασμα αντικειμένου σε μέθοδο
 Όταν περνάμε ένα αντικείμενο σε μια μέθοδο, το πέρασμα γίνεται με
αναφορά στο πραγματικό αντικείμενο.
public void giveName(Human h, String n){
h.setName(n);
}
 Όποιες αλλαγές γίνουν στο αντικείμενο εντός της μεθόδου, περνούν
μόνιμα στο αντικείμενο
Human nonos=new Human();
Human paidi=new Human();
nonos.giveName(paidi, “Mary”);

Κατασκευαστές
Μέθοδος κατασκευαστής
 Βασικός ή κενός κατασκευαστής:
 Μια public μέθοδος με όνομα ίδιο με αυτό της τάξης,
χωρίς παραμέτρους και τύπο επιστροφής.
 public Human(){ } – Δεσμεύει μνήμη για το
αντικείμενο και κάνει τις αρχικοποιήσεις
 Αν τον ορίσουμε στην τάξη, μπορούμε να ορίσουμε
τις αρχικοποιήσεις που θα κάνει
 Μπορούμε να ορίσουμε άλλους κατασκευαστές.
Οπότε αναιρείται ο βασικός. Αν θέλουμε και το βασικό
κατασκευαστή πρέπει υποχρεωτικά να τον ορίσουμε.

Παράδειγμα (1)
 Ορισμός ενός καλύτερου κατασκευαστή για τη Human
public Human (String tempName, String tempSurname,
int tempAge)
{
name=tempName;
surname=tempSurname;
age=tempAge;
}
 Αν ορίσουμε μόνο αυτόν τον κατασκευαστή τότε στη
demo θα μπορούμε να χρησιμοποιούμε μόνο αυτόν.
Human h1=new Human(); // βγάζει λάθος
10
Παράδειγμα (2)
 Ορισμός του βασικού κατασκευαστή στη Human
public Human(){
name=“”;
surname=“”;
age=0;
}
 Διαφορετικά τα name και surname σε κάθε νέο Human
είναι null.
Human h1=new Human();
System.out.println(h1.name); //τυπώνει null
11

Η λέξη this
 Χρησιμοποιείται μέσα σε μια μέθοδο για να αναφερθούμε στο
αντικείμενο για το οποίο καλείται η μέθοδος.
 Το this είναι μια αναφορά στο αντικείμενο στο οποίο βρισκόμαστε.
 Αν για παράδειγμα μια μέθοδος της τάξης Human έπρεπε να
επιστρέφει το ίδιο το αντικείμενο:
Human increaseAge(){
age++;
return this;
}
 Human h1=new Human(“Nikos”, “Nikolaou”,20);
 int x=h1.increaseAge().increaseAge().getAge();

12
Το this και οι κατασκευαστές
 Με τη χρήση του this μπορεί να καλεί ο
ένας κατασκευαστής τον άλλο.
public Human (String tempName, String tempSurname)
{
this (tempName, tempSurname,0);
}

13

To this και οι συνωνυμίες


μεταβλητών

public Human (String name, String surname, int age)


{
this.name=name;
this.surname=surname;
this.age=age;
}
14
Η μέθοδος finalize()
 Η Java διαθέτει μηχανισμό απελευθέρωσης της
μνήμης που δεσμεύουμε και παύουμε να
χρησιμοποιούμε (garbage collector)
 Ο μηχανισμός απελευθερώνει μνήμη που
δεσμεύτηκε με new (π.χ. όταν βγούμε από το
μπλοκ που έγινε η δέσμευση)
 Πριν ο garbage collector αποδεσμεύσει το χώρο
ενός αντικειμένου καλεί τη finalize.

15

Πότε ορίζουμε την finalize


 Το garbage collection δεν σημαίνει απόλυτη διαγραφή
των πράξεων του αντικειμένου,
 π.χ. αν το αντικείμενο έχει αυξήσει μια static μεταβλητή/ μετρητή
θα πρέπει να τη μειώσουμε στη finalize()
 Το garbage collection δεν γίνεται άμεσα,
 π.χ. συμβαίνει όταν χρειαστεί μνήμη το πρόγραμμα
 Το garbage collection απλά αποδεσμεύει μνήμη
 π.χ. αν θέλουμε να παρακολουθούμε πότε αποδεσμεύεται μνήμη
μπορούμε να ορίσουμε τη finalize() να τυπώνει κάποιο μήνυμα

16
Υπερφόρτωση μεθόδου

Υπερφόρτωση μεθόδων
 Σε μια τάξη μπορούμε να ξαναχρησιμοποιήσουμε το ίδιο
όνομα για μεθόδους που έχουν ελαφρώς διαφορετική
συμπεριφορά
 Διαφορετικούς τύπους ορισμάτων
 Διαφορετικό πλήθος ορισμάτων

void speak (String phrase);


void speak ();
void speak (int times, String phrase);

18
Περισσότερη υπερφόρτωση
 Δεν μπορούμε να χρησιμοποιήσουμε
υπερφόρτωση μόνο στην επιστρεφόμενη τιμή
boolean speak(String phrase ); void speak ( String phrase );
Δεν είναι φανερό ποια συνάρτηση από τις δύο θα χρησιμοποιηθεί
 Γιατί να προσθέσουμε υπερφόρτωση;
οικονομία σε ονόματα
ευανάγνωστος κώδικας
βιβλιοθήκες, λιγότερα ονόματα για να μάθει κανείς
 Μειονεκτήματα
Γίνονται λάθη ευκολότερα
μερικές φορές εμφανίζονται παραπλανητικά μηνύματα λάθους

19

Κλήση υπερφορτωμένης
μεθόδου
 Ο compiler ψάχνει αυτήν που ταιριάζει καλύτερα
Προτιμά ακριβές ταίριασμα από όλα τα άλλα
Βρίσκει την πιο κοντινή προσέγγιση
Επιδιώκει μόνο τις μετατροπές που έχουμε διεύρυνση τύπων και
όχι στένεμα π.χ.
void add (int I, int j);
void add (double d, double e);
H add(10,8) θα χρησιμοποιήσει το (int, int)
H add(3.5, 4) θα χρησιμοποιήσει το (double, double)
 Μπορούμε να χρησιμοποιήσουμε casting για να
επιβάλλουμε μια επιλογή, ή για να αποφύγουμε
σύγχυση
20
Παράδειγμα
class Calculator{
static int add(int a, int b) {return a+b;}
static float add(float a, float b) {return a+b;}
static double add(double a, double b) {return a+b;}

public static void main(String args[] ){


int x=5; int y=6;
double k=5.3; double m=4.5;
System.out.println(“Atrhoisma “+ add(x,y));
System.out.println(“Athroisma “+ add(k,m));
System.out.println(“Athroisma “+ add(x,m));
}
}

21

Κληρονομικότητα
Επαναχρησιμοποίηση κλάσεων
 Δημιουργία ενός αντικειμένου μιας κλάσης
 Χρήση μιας κλάσης στον ορισμό μιας
άλλης κλάσης - Σύνθεση (composition ή
aggregation)
 π.χ.Φτιάχνουμε μια κλάση«μηχανή» και στη
συνέχεια μια κλάση«αυτοκίνητο» που «έχει»
μία «μηχανή»

23

Κληρονομικότητα
 Αντιγραφή της δομής της κλάσης και επέκτασή
της με νέα χαρακτηριστικά και λειτουργίες.
 Αν αλλάξει η βασική κλάση
(base ή super ή parent class),
τότε αλλάζει και η παράγωγη
κλάση (derived ή inherited ή sub
ή child class).
 Στη Java κάθε τάξη μπορεί να
κληρονομεί μόνο μία κλάση
24
Παράδειγμα
class Human{
String name;
String surname;
int age;
void setName(String tempName){name=tempName;}
String getName(){return name;}

}
class Address{
String street;
int number;
String state;
long postcode;
}
25

Παράδειγμα
public class Employee extends Human{ //κληρονομικότητα
String position;
Address residence; //σύνθεση
void setPosition(String temp){position=temp;}
String getPosition () {return position;}
void setAddress(Address tempad){residence=tempad;}
Address getAddress() {return residence;}
}
… main(..){ Name
Surname Human
Employee e1=new Employee(); Age
Address a1=new Address();
street
a1.street=“Patision”; … number
e1.setAddress(a1); state residence Employee
} postcode
position
26
Παράδειγμα
Employee (abstract)
- private
-residence : Address
-position : String # protected
#bonus : double + public
+(abstract) getSalary() : double
+getResidence() : Address
+setResidence(in getResidence : Address) : void
+getPosition() : String
+setPosition(in position : String) : void
+worksFor(in manager : Manager) : void

Manager PieceWorker HourlyWorker


-weeklySalary : double -wagePerPiece : double -wage : double
+Manager() -quantity : int -hours : int
+getSalary() : double +PieceWorker() +HourlyWorker()
+getSalary() : double +getSalary() : double
27

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


 Από τα μέλη της Employee:
 Στην Employee και τα αντικείμενά της: είναι όλα ορατά private,
protected και public
 Στις Manager, PieceWorker, HourlyWorker και τα αντικείμενά
τους: είναι μόνο τα public και protected (π.χ. το bonus και όλες οι
μέθοδοί της) π.χ. στην Manager:
double getSalary(){ return weeklySalary*4+bonus;}
public Manager(){
position=“manager”; //ΛΑΘΟΣ: το position
είναι protected
setPosition(“manager”); //ΣΩΣΤΟ
}
 Σε οποιαδήποτε άλλη κλάση: είναι μόνο τα public (π.χ. οι
μέθοδοι)
28
Κληρονομικότητα και κατασκευαστές
 Οι κατασκευαστές δεν κληρονομούνται
 Είναι στενά δεμένοι στην κλάση με τον ορισμό τους
 Αν η Εmployee όριζε δύο κατασκευαστές
public Employee(String nm, int wage, int hours,
double attitude)
public Employee(String nm, int wage)
 και η Manager όριζε ένα constructor
public Manager(String nm, int wage, int hours, double
attitude, Employee under)
 Τότε η Manager δεν μπορεί να κληρονομήσει τους
κατασκευαστές των 2 και 4 ορισμάτων
Manager b = new Manager("Ralph", 25); // Λάθος
Manager s = new Manager("Pat",25,50,.8,null); // Σωστό

29

Υπέρβαση (overloading)
Υπέρβαση μεθόδων
 Η getCompleteData της Human
String getCompleteData(){
String data=new String();
data=name+“ “+surname+” “+age+” years old”;
return data;
}
 Λόγω κληρονομικότητας μπορούμε να την
καλέσουμε για έναν Employee, αλλά δε θα
έχουμε όλες τις πληροφορίες γι’αυτόν.

Η λύση
 Υπερβαίνουμε τη μέθοδο, δηλώνοντάς την ΚΑΙ στην
Employee με το ίδιο όνομα
 Καλούμε στο σώμα της τη μέθοδο της employee με τη
δήλωση super
class Employee{
...
String getCompleteData(){
String data=new String();
data=super.getCompleteData() + " "+
residence.getCompleteAddress()+" position:"+
position;
return data;
}
}
Υπέρβαση της toString
 Η τάξη Object την οποία κληρονομεί εξ ορισμού κάθε
τάξη στη Java έχει μια public μέθοδο toString η οποία
επιστρέφει String.
 Μπορούμε να την υπερβούμε και στις τρεις τάξεις που
φτιάξαμε μετονομάζοντας τις getCompleteData και
getCompleteAddress.
 Πρέπει υποχρεωτικά να είναι public γιατί στην Object
είναι public.
 Αλλάζει ο τρόπος κλήσης της, π.χ. στην Employee
public String toString(){
String data=new String();
data=super.toString() + " "+residence+" position:"+position;
return data;
}

Τελικοί (Final) μέθοδοι


 Οι “final” μεταβλητές γίνονται σταθερές
 Ανατίθεται ακριβώς μία φορά και δε μπορεί να
αλλάξει
 Οι “final” μέθοδοι δεν είναι overridable
Η κλάση γονέα τις ορίζει μία φορά και δεν ορίζονται
ξανά στις υπο-κλάσεις
 Όλες οι private μέθοδοι είναι έμμεσα τελικές
(implicitly final)
 Εξασφαλίζουμε ότι η συμπεριφορά διατηρείται και
δεν μπορεί να τις αλλάξει κανείς στις υπο-κλάσεις

34
Final κλάσεις
 Οι “final” κλάσεις δεν κληρονομούνται
 Ολοι οι μέθοδοι της γίνονται έμμεσα τελικές
 Οταν θέλουμε να είμαστε σίγουροι ότι κανείς δεν θα
τις κληρονομήσει

public final class String{ …..}

 Οι final μέθοδοι και κλάσεις δεν


χρησιμοποιούνται συχνά

35

Παράδειγμα (1)
Employee (abstract)
-residence : Address
-position : String
+getSalary (abstract)()

Manager PieceWorker HourlyWorker


-weeklySalary -wagePerPiece -wage
+getSalary() -quantity -hours
+getSalary() +getSalary()
Παράδειγμα (2)
public abstract class Employee {
...
public abstract double getWeeklySalary(); // ορίζεται στις απόγονες
}
public final class Manager extends Employee {
private double weeklySalary;
public double getWeeklySalary( ) {return weeklySalary;}
}
public final class PieceWorker extends Employee {
private double wagePerPiece; // μισθός ανά τεμάχιο
private int quantity; //τεμάχια παραγωγής
public double getWeeklySalary( ) {return wagePerPiece*quantity;}
}
public final class HourlyWorker extends Employee {
private double wage; // μισθός ανά ώρα
private double hours; //ώρες εργασίας
public double getWeeklySalary( ) {return wage*hours;}
}

Διαχείριση
αντικειμένων
Κατασκευαστές
public Human(){
name=“Unknown”; surname=“Unknown”; age=0;
System.out.println(“A new Human has been created”);
}
public Address(){
street=“Unknown”; number=0; city=“Unknown”;
System.out.println(“A blank Address has been created”);
}
public Employee(){
residence=new Address();
position=“Unemployed”;
System.out.println(“A new Employee has been created”);
}
 Με ποια σειρά καλούνται οι κατασκευαστές;

Δημιουργία αντικειμένων
Address ad1=new Address();
A blank Address has been created
Human h1=new Human();
A new Human has been created
Employee e1= new Employee();
A new Human has been created
A blank Address has been created
A new Employee has been created
 Καλείται αυτόματα ο βασικός κατασκευαστής της
Human
Αν η Human δεν έχει βασικό κατασκευαστή;
public Human(String name,String surname, int age){
this.name=name; this.surname=surname; this.age=age;
System.out.println(name+” “+surname+“ has been created”);
}
 Πρέπει να δηλώσουμε στον κατασκευαστή της Employee
ποιο συγκεκριμένο κατασκευαστή της Human θα καλέσει
 Αυτό γίνεται με τη λέξη super.
public Employee(){
super(“Unknown”,”Unknown”,0);
residence=new Address();
position=“Unemployed”;
System.out.println(“A new Employee has been created”);
}

Παράδειγμα χρήσης
class Demo {
public static void main (String args[]){
Employee emp1=new Employee();
}
}

Unknown Unknown has been created


A blank Address has been created
A new Employee has been created
Καταστροφείς - finalize
class Human{…
protected void finalize(){
System.out.println("The human has been cleared");
}…}

class Employee{…
protected void finalize(){
super.finalize();
System.out.println("The employee has been cleared");
}…}

Με ποια σειρά καλούνται οι καταστροφείς;


class Demo {
public static void main (String args[]){
new Employee(); //φτιάχνει ένα αντικείμενο άχρηστο
System.gc(); //καλεί τον garbage collector
}}
Unknown Unknown has been created
A new Address has been created
A new employee has been created
The human has been cleared
The employee has been cleared
The address has been cleared
 Αφού καταστραφεί ο employee είναι άχρηστο το
αντικείμενο address
Πολυμορφισμός

Κληρονομικότητα - Παράδειγμα
Δομές και κληρονομικότητα
 Σε ένα array με αντικείμενα Human μπορούμε να
βάλουμε και αντικείμενα Employee (upcasting)
Human[] group=new Human[];
group[0]=new Human();
group[1]=new Employee();
 Στα αντικείμενα αυτά μπορούμε χωρίς κίνδυνο να
καλέσουμε χαρακτηριστικά και μεθόδους της Human.
 Για να καλέσουμε χαρακτηριστικά και μεθόδους της
Employee από κάποιο αντικείμενο πρέπει πρώτα να
το μετατρέψουμε σε Employee (downcasting)
(Employee)group[1].getPosition();
(Employee)group[0].getPosition(); //Class Cast Exception

Η λύση - RTTI
 Για τη μέθοδο toString που υπάρχει και στις δύο τάξεις,
το πρόβλημα λύνεται αυτόματα.
 Χωρίς να κάνουμε downcasting.
group[1].toString();
group[0].toString();
 Αν βρει αντικείμενο της τάξης Human καλεί την toString
της Human. Αν βρει αντικείμενο της τάξης Employee
καλεί αυτόματα την αντίστοιχη toString.
 Run Time Type Identification – Καθορισμός τύπου την
ώρα εκτέλεσης
Δομές αντικειμένων
 Σε ArrayList και Vector αποθηκεύουμε αντικείμενα
διαφόρων τάξεων που όλες κληρονομούν από την ίδια
βασική τάξη.
 Η βασική τάξη έχει μεθόδους και οι παράγωγες τάξεις τις
υπερβαίνουν
 Όταν ανακτούμε ένα αντικείμενο από τη δομή το
μετατρέπουμε στη βασική τάξη και καλούμε τις μεθόδους
του.
 Ανάλογα με τον τύπο του αντικειμένου παίρνουμε και
άλλη συμπεριφορά - Πολυμορφισμός

Πλεονεκτήματα του πολυμορφισμού

 Μπορούμε να ασχολούμαστε με τη γενική


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

κλάσεις αφηρημένου τύπου (abstract)

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


οργανώσουμε μία κοινή ιδιότητα, οι οποία όμως
δεν χρησιμοποιείται από μόνη της
 π.χ. Τετράπλευρο, Έλλειψη, Πολύγωνο ..
 έχουν πολλά κοινά

 Θέλουμε να οργανώσουμε αυτή την κοινή


συμπεριφορά σε έναν γονέα γενικού τύπου
 με το όνομα “Shape"

52
Αφηρημένες τάξεις – abstract
classes
 Μια abstract τάξη βρίσκεται στην κορυφή μιας
ιεραρχίας τάξεων και συγκεντρώνει λειτουργίες.
 Οι υπόλοιπες τάξεις της ιεραρχίας υλοποιούν τις
λειτουργίες αυτές με το δικό τους τρόπο
 Δεν μπορούμε να φτιάξουμε αντικείμενα abstract
τάξεων μπορούμε όμως να έχουμε αναφορές σε
abstract τάξεις.

Interfaces
Abstract class- Interface
 Για μια κλάση που δηλώνεται abstract δεν μπορούμε να
φτιάξουμε αντικείμενα.
 Μπορούμε να δηλώσουμε κάποια λειτουργικότητα και
κάποια βασικά χαρακτηριστικά που θα τα
κληρονομήσουν οι απόγονες κλάσεις.
 Τις abstract κλάσεις που ορίζουν μόνο μεθόδους τις
δηλώνουμε ως διεπαφές – interfaces
 Τα interfaces συγκεντρώνουν μόνο δηλώσεις
λειτουργικότητας. Άλλες κλάσεις αναλαμβάνουν να
υλοποιήσουν (implement) τις δηλώσεις αυτές

55

Interface
 To interface είναι μια συλλογή από “υπογραφές“
μεθόδων (δεν υπάρχουν στιγμιότυπα, ούτε
υλοποιήσεις των μεθόδων)
 Περιγράφει πρωτόκολλο/συμπεριφορά αλλά όχι
υλοποίηση
 Όλες οι μέθοδοι του είναι public και abstract
(ποτέ static)
 Όλες οι μεταβλητές είναι static και final
 Μια κλάση υλοποιεί (implements) ένα interface
56
Πλεονεκτήματα
 Δηλώνουν μια επιθυμητή λειτουργικότητα και αφήνουν
στις τάξεις να την ορίσουν
public interface Shape {
public abstract double area(); // calculate area
public abstract double volume(); // calculate volume
public abstract String getName()// return shape name
}
public class Triangle implements Shape {…}
 Υποχρεωτικά θα πρέπει να ορίσει τις μεθόδους της
διεπαφής Shape
 Είναι ένας έμμεσος τρόπος να έχουμε πολλαπλή
κληρονομικότητα λειτουργιών στη Java

Παράδειγμα – Enumeration, Iterator


 java.util.Enumeration: είναι ένα interface. Περιγράφει
μεθόδους για το ψάξιμο μέσα σε μια συλλογή
public interface Enumeration{
boolean hasMoreElements();
Object nextElement(); }
 Ένας iterator υλοποιεί αυτό το interface
 Οι κλάσεις Vector, Hashtable, Set, Graph, Tree κλπ.
υλοποιούν το Enumeration ορίζοντας πώς θα
ανταποκρίνεται η κάθε μέθοδος
 Μπορούμε να χρησιμοποιήσουμε το interface ως όνομα
τύπου σε όσες κλάσεις υλοποιούν το interface.
void printAll(Enumeration e) {
while(e.hasMoreElements())
System.out.println(e.nextElement());}
58
Παράδειγμα: VectorEnumerator
class VectorEnumerator implements Enumeration{
private Vector vector;
private int count;
VectorEnumerator(Vector v) {
vector = v;
count = 0; }
public boolean hasMoreElemets() {
return count < vector.size(); }
public Object nextElement() {
return vector.elementAt(count++);}
}
59

Σύνταξη του interface


 ΟΛΕΣ οι μέθοδοι ενός interface πρέπει να
υλοποιηθούν, αλλιώς η νέα κλάση θα πρέπει να
οριστεί ως abstract
 Οι μέθοδοι του interface πρέπει να είναι public
 Μια κλάση μπορεί να υλοποιήσει πολλαπλά
interfaces
public class Shape implements Colorable, Printable { …}
 Πρέπει να προσέχουμε τα ονόματα των
μεθόδων στα interfaces που θα συνδυαστούν να
μη συμπίπτουν γιατί δημιουργούνται συγχύσεις.
60
Κληρονομικότητα Interfaces
 Τα interfaces μπορούν να επεκτείνουν αλλά
interfaces
public interface Beepable {
public void beep(); }
public interface VolumeControlled extends Beepable {
public int getVolume (int newVol);
public void setVolume( int newVol);
public void mute(); }
 Η κλάση είναι συμβατή με τον τύπο του interface.
Κάνουμε upcasting σε τύπο interface όπως θα
κάναμε σε μια abstract ή σε μια οποιαδήποτε
κλάση

61

Interfaces ή abstract κλάσεις ?


 Παρόμοιες χρήσεις
 Σχεδιάστηκαν για την ομαδοποίηση της συμπεριφοράς,
 για να επιτρέπουν το upcasting,
 για την εκμετάλλευση του πολυμορφισμού
 Μια κλάση μπορεί να υλοποιήσει πολλαπλά interfaces,
αλλά έχει μόνο μια υπερ-κλάση
 Το interface δεν έχει καθόλου υλοποίηση
 Είναι καλό, αν η ομοιότητα συμπεριφοράς είναι μόνο στο όνομα
 Είναι κακό, αν υπάρχει κοινός κώδικας που θα μπορούσε να
μεταφερθεί στην abstract κλάση (σε μια όχι abstract μέθοδο)
 Αν υπάρχει κοινός κώδικαςabstract κλάση, αλλιώς
interface

62
Τα πεδία των interfaces
 Είναι static και final και μπορούν να χρησιμοποιηθούν
για να ομαδοποιήσουν σταθερές
public interface Months {
ιnt JANUARY = 1, ..., DECEMBER = 12; }
...
Από κάθε άλλη κλάση: Months.JANUARY
 Αρχικοποίηση γίνεται όταν αναφερθούμε για πρώτη
φορά στο Interface.
public interface RandVals {
int rint = (int)(Math.random() * 10);}

RandVals.rint;
63

Εσωτερικά interfaces και κλάσεις


 Μέσα σε ένα interface (σε μία κλάση) μπορούμε να
δηλώσουμε ένα άλλο interface (μια κλάση)
 Χρησιμοποιούνται
 για να ομαδοποιήσουμε σχετικά μεταξύ τους interfaces ή
κλάσεις (λειτουργικότητα), που δε χρησιμοποιούνται σε άλλο
περιεχόμενο.
 για να διαχωρίσουμε τη λειτουργικότητα σε μια κλάση από
την ίδια την κλάση
 Παράδειγμα:
 μια κλάση BinaryTree μπορεί να έχει τις μεθόδους για
προσθήκη και αφαίρεση κόμβων.
 Μέθοδοι που υλοποιούν κάποιο αλγόριθμο ταξινόμησης ή
αναζήτησης κόμβων ομαδοποιούνται σε εσωτερική κλάση
της BinaryTree. Διαχωρίζοντας έτσι τις λειτουργίες
64
3. Διαχείριση πολλαπλών
αντικειμένων

Πίνακες
 Προκαθορισμένο μέγεθος
 Συνεχείς θέσεις
 Πίνακες τιμών
 Αρχικοποιούνται σε 0 ή false
 int[] a=new int[10];
 boolean[] b=new boolean[10];

 Πίνακες αντικειμένων
 Αρχικοποιούνται σε null
 String[] c= new String[10]

2
Περιορισμοί των πινάκων
 Οι εισαγωγές και οι διαγραφές σε κάποια θέση «κοστίζουν»
 Πρέπει να μετακινηθούν όλα τα υπόλοιπα στοιχεία για να καλύψουν το
κενό ή να δημιουργήσουν χώρο.
 Αν γεμίσουν οι θέσεις θα πρέπει να αντιγράψουμε όλα τα στοιχεία σε
νέο, μεγαλύτερο πίνακα.
 Η λογική διαδοχή των θέσεων του πίνακα ταυτίζεται με την
πραγματική (ο πίνακας αποθηκεύεται σε συνεχόμενες θέσεις
μνήμης)
 Θέλουμε να αποσυνδέσουμε τη λογική από την πραγματική
διαδοχή θέσεων.
 Έτσι θα έχουμε διαγραφές και εισαγωγές χωρίς μετακίνηση

Δυναμικές δομές δεδομένων


 Περιέχουν αντικείμενα (οποιουδήποτε τύπου)
 Επιτρέπουν την εισαγωγή αντικειμένων με περισσότερες ελευθερίες
από τους πίνακες
 Λίστες
 Κάθε στοιχείο (κόμβος) αποτελείται από το αντικείμενο και από ένα
σύνδεσμο στο «επόμενο» στοιχείο
 Το τελευταίο στοιχείο δείχνει σε null

4
Υλοποιήσεις
 Η κλάση Vector
 Επιτρέπει να φτιάξουμε δομές όπως οι πίνακες που
το μέγεθός τους αυξομειώνεται δυναμικά.
 Η κλάση ArrayList
 Υλοποιεί τη δομή της λίστας στη Java
 Χρησιμοποιεί πίνακες τους οποίους διπλασιάζει σε
μέγεθος δυναμικά, όποτε απαιτείται

Η κλάση ArrayList
 Προτείνεται από τους δημιουργούς της Java
 ArrayList list = new ArrayList();
ή
 ArrayList<type> list = new ArrayList<>();
 add(Object searchkey), get(int position)

Iterator it = list.iterator();
StringBuffer buf = new StringBuffer();
while (it.hasNext())
buf.append( it.next()) .append( " " );
System.out.println(buf.toString());

6
Άλλες μέθοδοι της ArrayList
void clear(); //αδειάζει τη λίστα
Object clone(); //δημιουργεί αντίγραφο
boolean addAll(Collection c);//προσθέτει όλα τα
//αντικείμενα της c στη λίστα
boolean contains(Object elem); // αναζητά το elem
int indexOf(Object elem); //βρίσκει την θέση 1ης
//εμφάνισης
Object remove(int index); //διαγράφει στοιχείο
Object[] toArray();// επιστρέφει τα στοιχεία της
//λίστας σε πίνακα αντικειμένων
7

Μειονέκτημα των containers


(Vector, ArrayList κλπ).
 Αν δε χρησιμοποιηθεί ο περιορισμός τύπου:
 Όλα τα στοιχεία αποθηκεύονται ως Object
 Πρέπει να μετατραπούν (cast) για να χρησιμοποιηθούν οι μέθοδοί
τους.
 Τα containers μπορεί να περιέχουν αντικείμενα διαφόρων κλάσεων
list.add(new Employee());
list.add(new Address());
list.add(new Manager());
((Employee)list.get(0)).getName();
((Address)list.get(1)).getCity();
((Address)list.get(2)).getCity(); //ΛΑΘΟΣ casting

Όπως πάντα… το μειονέκτημα …


έγινε τελικά πλεονέκτημα
8
Χρήσιμες μέθοδοι

Εισαγωγή με έλεγχο διπλοτύπων


 Η εισαγωγή με έλεγχο διπλοτύπων θα γίνει σε δύο φάσεις:
 Αναζήτηση για το αν υπάρχει ή όχι το αντικείμενο στον πίνακα ή τη
λίστα
 Εισαγωγή – στο τέλος ή σε κενή θέση - σε περίπτωση που δεν υπάρχει
 Υπάρχουν πιο γρήγορες λύσεις;
 Η ArrayList διαθέτει μεθόδους:
 int indexOf(Object elem): επιστρέφει τη θέση πρώτης εμφάνισης του
elem στη λίστα
 int lastIndexOf(Object elem)
 boolean contains(Object elem) : επιστρέφει true αν η λίστα περιέχει το
elem
 Object remove(int index) : διαγράφει το στοιχείο στη θέση index της
λίστας και μας το επιστρέφει

10
Σύγκριση: Η μέθοδος equals
 Για να δουλέψουν οι προηγούμενοι μέθοδοι για λίστες με αντικείμενα
δικών μας κλάσεων πρέπει στις κλάσεις μας να έχουμε μια μέθοδο
equals π.χ.
public boolean equals(Object o){
Department d=(Department)o; // πιθανό να παράγει
//ClassCastException
if (this.id==d.getId() && this.name.equals(d.getName()) &&
this.numStudents==d.getNumStudents())
return true;
else
return false;
}
11

Ταξινόμηση
 Με ποιο τρόπο μπορώ να ταξινομήσω τα στοιχεία ενός πίνακα ή μιας
λίστας; BubbleSort:
public void bubbleSort(int[] unsortedArray, int length) {
int temp, counter, index;
for(counter=0; counter<length-1; counter++) {
for(index=0; index<length-1-counter; index++) {
if(unsortedArray[index] > unsortedArray[index+1]) {
temp = unsortedArray[index];
unsortedArray[index] = unsortedArray[index+1];
unsortedArray[index+1] = temp;
}
}
}
}
12
Διάταξη
 Η διάταξη στους ακεραίους είναι δεδομένη
 Τι γίνεται όμως με τις δικές μας κλάσεις;
 Πώς μπορούμε να ορίσουμε διάταξη στα αντικείμενά
τους;

Comparable
public interface Comparable
{
int compareTo(Object o);
}
Department

13

public class Department implements Comparator{



public int compareTo(Object o){
Department d=(Department)o; // πιθανό να παράγει
//ClassCastException
if (this.numStudents>d.getNumStudents())
return 1;
else if (this.numStudents<d.getNumStudents())
return -1;
else
return 0;
}
}
14
Ταξινόμηση

Collections.sort(allDeps);

Ταξινομεί τα τμήματα με βάση τον αριθμό


σπουδαστών που έχουν
Χρησιμοποιεί την QuickSort

15

Χρήση κώδικα τρίτων


http://jsoup.org/
 Έτοιμη βιβλιοθήκη για το
χειρισμό του περιεχομένου
ιστοσελίδων

17

Προσθήκη package στο Netbeans


 Κατεβάζουμε ένα μεταγλωττισμένο package για σύνδεση με την
Oracle
 Βάζουμε το αρχείο σε ένα φάκελο lib εντός του project
 Ανοίγουμε τα properties του project και πηγαίνουμε στην
επιλογή Libraries

18
Προσθήκη package στο Netbeans

 Επιλέγουμε Add JAR/Folder και


εντοπίζουμε το αρχείο που κατεβάσαμε

19

Βασικά στοιχεία
HTML

20
Παράδειγμα HTML

<html>
<head>
<title>My Title</title>
</head>
<body>
<h1>My header</h1>
<a href="http://www.hua.gr">My link</a>
</body>
</html>

HTML DOM

 Ο κώδικας της σελίδας έχει μια δομή


δέντρου
DOM Nodes

 Τα πάντα στη σελίδα είναι κόμβοι DOM


 Το ίδιο το έγγραφο (document node)
 Οι ετικέτες (tags) της σελίδας (element node)
 Το περιεχόμενο των ετικετών (text nodes)
 Οι παράμετροι και οι τιμές τους (attribute node)
 Τα σχόλια (comment node)

Σημαντικοί κόμβοι (elements)

• Root (Document)
• Γείτονες ενός Node
– Parents
– Children
– Siblings
• Leaf nodes
– Κόμβοι χωρίς παιδιά
• Div, Span: ομαδοποιούν περιοχές με κοινό
περιεχόμενο
Σημαντικά attributes

 id
Μοναδικό σε όλο το έγγραφο
 class
Επαναλαμβάνεται σε κείμενα που έχουν
κοινή μορφοποίση

Εργασία

26
Χρήσιμοι σύνδεσμοι
 https://transport.opendata.ch/
 http://jsonviewer.stack.hu/
 https://code.google.com/archive/p/json-simple/
 http://www.tutorialspoint.com/json/json_java_example.ht
m
 http://www.mkyong.com/java/json-simple-example-read-
and-write-json/
 http://www.mkyong.com/java/how-to-send-http-request-
getpost-in-java/

27

JSON example
 “JSON” stands for “JavaScript Object Notation”
 Despite the name, JSON is a (mostly) language-independent way of
specifying objects as name-value pairs
 Example (http://secretgeek.net/json_3mins.asp):
 {"skillz": {
"web":[
{ "name": "html",
"years": 5
},
{ "name": "css",
"years": 3
}]
"database":[
{ "name": "sql",
"years": 7
}]
}}
JSON syntax, I
 An object is an unordered set of name/value pairs
 The pairs are enclosed within braces, { }
 There is a colon between the name and the value
 Pairs are separated by commas
 Example: { "name": "html", "years": 5 }
 An array is an ordered collection of values
 The values are enclosed within brackets, [ ]
 Values are separated by commas
 Example: [ "html", ”xml", "css" ]

JSON syntax, II
 A value can be: A string, a number, true, false, null, an
object, or an array
 Values can be nested
 Strings are enclosed in double quotes, and can contain
the usual assortment of escaped characters
 Numbers have the usual C/C++/Java syntax, including
exponential (E) notation
 All numbers are decimal--no octal or hexadecimal
 Whitespace can be used between any pair of tokens
Java project alternatives
 Δύο εναλλακτικές για τα project σας σε
Netbeans (και αλλού):
 Ant: Εσείς κατεβάζετε τα third party libraries
και τα αντιγράφετε στο project
 Maven: Αναζητάτε τα third party libraries
(dependencies) σε maven repositories.

31

Βήματα
 Δημιουργούμε ένα νέο Maven Project
 Δημιουργούμε το package basics με τις βασικές
κλάσεις
 Προσθέτουμε τα dependencies για jsoup και
json-simple
 Κάνουμε το request με java ή και με jsoup
 Επεξεργαζόμαστε την απάντηση με json-simple.

32
4. Διαχείριση εξαιρέσεων

Διαχείριση λαθών – Εξαιρέσεις


 Δημιουργία
 Ανίχνευση
 Διαχείριση
 Βασικοίτύποι εξαιρέσεων
 Δημιουργία τύπων εξαίρεσης

2
Αντιμετώπιση λαθών
 Υπάρχουν λάθη χρόνου εκτέλεσης (run time errors) τα
οποία δεν ανιχνεύονται στη μεταγλώττιση.
 Αναζήτηση στοιχείου έξω από τα όρια ενός πίνακα
 Άνοιγμα αρχείου που δεν υπάρχει
 Κλήση αναφοράς σε null
 Θα πρέπει να αντιμετωπίζονται όταν το πρόγραμμα
εκτελείται
 Ο κώδικας που δημιουργεί κάποιο λάθος μεταδίδει
πληροφορία στον κώδικα που καλείται να το
αντιμετωπίσει. Αυτό γίνεται με τις Εξαιρέσεις –
Exceptions
 Σηματοδοτούν εμφάνιση συνθηκών ιδιαίτερης
μεταχείρισης και διακόπτουν τη συνήθη ροή του κώδικα
3

Παραδείγματα
 Αναζήτηση στοιχείου έξω από τα όρια ενός πίνακα
ArrayList<String> messages = new ArrayList<String>();
messages.add(“Hello”);
messages.add(“How are you?”);
System.out.println(messages.get(0));
System.out.println(messages.get(2)); //ArrayIndexOutOfBoundsException
 Αναφορά σε null αντικείμενο
Human[] anthrwpoi = new Human[5];
anthrwpoi[0] = new Human(“Bill”,”Gates”,50);
anthrwpoi[2].setName(“George”); //NullPointerException
 Άνοιγμα αρχείου που δεν υπάρχει
FileReader fro = new FileReader( "myFile.txt" ); //FileNotFoundException

4
Οι εξαιρέσεις είναι αντικείμενα
 Αντί να ελέγχουμε στον κώδικα για κάποιο συγκεκριμένο
λάθος σε όσα σημεία μπορεί να εμφανιστεί, μπορούμε
να προσθέσουμε ένα μόνο μπλόκ κώδικα που
αποκαλείται διαχειριστής εξαίρεσης (Exception Handler)
 Αν συμβεί εξαίρεση, η ροή του προγράμματος στο
μπλοκ διακόπτεται και ο έλεγχος περνά στο διαχειριστή
εξαίρεσης
 Αυτός ανιχνεύει τον τύπο του αντικειμένου εξαίρεσης
 Αν κάποια εξαίρεση δεν τη διαχειριστούμε παίρνουμε
μήνυμα από το μεταγλωττιστή

Παράδειγμα
 Θέλουμε να δημιουργήσουμε μια μέθοδο που να αθροίζει όσους αριθμούς
δώσει ο χρήστης. Να συνεχίζει μέχρι ο χρήστης να δώσει το σύμβολο ‘=‘.
public static void main(String[] args) {
Main m=new Main();
double z=m.sumNumbers();
System.out.println("Sum is:"+z);
}
•Τι θα βάλω στη συνθήκη του
public double sumNumbers(){ while;
double sum=0; •Τι θα γίνει αν ο χρήστης
while(????) δώσει ‘=‘;
sum+=readDouble(); •Τι θα γίνει αν δώσει κάτι που
return sum; δεν είναι αριθμός;
}
public double readDouble(){
Scanner in =new Scanner(System.in);
return in.nextDouble();
} 6
Αναλυτικά με τις εξαιρέσεις
 Όταν εμφανίζεται μία εξαίρεση σταματά η εκτέλεση της μεθόδου
 Δεν υπάρχει η απαραίτητη πληροφορία στο scope της μεθόδου
 Ανεβαίνουμε και αντιμετωπίζουμε το πρόβλημα σε κάποιο
«υψηλότερο» scope. «Ρίχνουμε» μια εξαίρεση (throw)
 Ένα αντικείμενο εξαίρεσης (Exception object) δημιουργείται στον σωρο
(heap) με χρήση του τελεστή new όπως κάθε άλλο Java object
 Διακόπτεται η εκτέλεση της μεθόδου και κρατιέται μια αναφορά στο
Exception object σε κάποια περιοχή της μνήμης
 Αναλαμβάνει ο μηχανισμός διαχείρισης της εξαίρεσης (Exception
handling mechanism) που πρέπει να βρει το κατάλληλο μέρος για να
συνεχίσει να εκτελεί κώδικα

Αντικείμενα εξαιρέσεων
 To keyword throw προκαλεί τα ακόλουθα γεγονότα:
 εκτελεί την έκφραση new και δημιουργεί ένα αντικείμενο που δεν
θα υπήρχε κανονικά
 Το αντικείμενο αυτό επιστρέφεται στην ουσία από την μέθοδο ή
το block μέσα στο οποίο δημιουργήθηκε μολονότι η μέθοδος δεν
έχει δηλωθεί να επιστρέφει παραμέτρους αυτού του τύπου και τα
blocks δεν έχουν φυσικά παραμέτρους που να επιστρέφουν
 Το πρόγραμμα βγαίνει από τη μέθοδο ή το block.
 Τα αντικείμενα exception που «ρίχνονται» μπορεί να
είναι διάφορων τύπων, ανάλογα το είδος της εξαίρεσης
 Κάθε αντικείμενο κωδικοποιεί στα πεδία του όλη την
πληροφορία που αφορά την εξαίρεση, ώστε ο
μηχανισμός διαχείρισης εξαιρέσεων στα ψηλότερα
επίπεδα να μπορεί να πάρει τις κατάλληλες αποφάσεις
8
Προδιαγραφές εξαιρέσεων
 Αν κάποιος πρόκειται να χρησιμοποιήσει τον κώδικά μας τότε θα
πρέπει να ξέρει τις εξαιρέσεις που μπορεί να παράγονται
 Σε κάθε μέθοδο που ρίχνει εξαιρέσεις χρησιμοποιούμε τη δήλωση
throws
void f() throws tooBig, tooSmall, divZero {
// κώδικας της μεθόδου
}
 Αν κάποιος καλέσει στον κώδικά του τη μέθοδό μας θα πρέπει να τη
βάλει μέσα σε try block.
 Σε αντίθετη περίπτωση ο μεταγλωττιστής εκδίδει μηνύματα λάθους.
Αυτό εξασφαλίζει διαχείριση εξαιρέσεων κατά τη μεταγλώττιση.
 Τέτοιες προδιαγραφές υπάρχουν ήδη σε πολλές μεθόδους κλάσεων
της Java

Δημιουργία νέων τύπων εξαιρέσεων

 Κάθε τύπος εξαίρεσης που δημιουργούμε πρέπει να κληρονομεί


από κάποιο υπάρχουσα τάξη.
 Συνήθως αυτή που είναι νοηματικά κοντά. Αλλιώς από την
Exception
class MyException extends Exception {
public myException() {
// κενός κατασκευαστής
}
public myException(String ms) {
// κατασκευαστής με όρισμα
}
// specific fields or methods may exist
}

10
Παράδειγμα – έλεγχος εισόδου
 Στη μέθοδο readDouble() ελέγχουμε τι δίνει ο χρήστης
public double readDouble() throws Exception{
Scanner in =new Scanner(System.in);
if(in.hasNextDouble()){
return in.nextDouble();
}
else throw new Exception();
}
 Εναλλακτικά μπορούμε να περάσουμε ένα μήνυμα στην εξαίρεση
public double readDouble() throws Exception{
Scanner in =new Scanner(System.in);
if(in.hasNextDouble()){
return in.nextDouble();
}
else throw new Exception(“Not a number");
}

11

Παράδειγμα – έλεγχος εισόδου (2)


 Μπορούμε να χρησιμοποιήσουμε δική μας εξαίρεση;
 Στο αρχείο MySpecialException.java
public class MySpecialException extends Exception{

}
 Οπότε
public double readDouble() throws MySpecialException{
Scanner in =new Scanner(System.in);
if(in.hasNextDouble()){
return in.nextDouble();
}
else throw new MySpecialException();
}

12
Σύλληψη εξαίρεσης
 Όταν ρίχνουμε μία εξαίρεση πρέπει στα υψηλότερα
επίπεδα κάποιο μπλοκ κώδικα να την ανιχνεύσει και να
την διαχειριστεί.
 Προστατευόμενη περιοχή είναι ένα κομμάτι κώδικα
που μπορεί να ρίξει εξαιρέσεις και που ακολουθείται από
κώδικα που διαχειρίζεται αυτές τις εξαιρέσεις.
 Μια προστατευόμενη περιοχή μπορεί να ανιχνεύσει ένα
ή περισσότερους τύπους εξαιρέσεων και
 να τους διαχειριστεί ή
 να τους ρίξει ακόμη πιο πάνω (με νέο throw)

13

Παράδειγμα
 Μη διαχείριση σφάλματος εισόδου
public double sumNumbers() throws MySpecialException{
double sum=0;
sum+=readDouble();
return sum;
}
public static void main(String[] args) throws MySpecialException{
Main m=new Main();
double z=m.sumNumbers();
System.out.println("Sum is:"+z);
}

 Έτσι αποφεύγουμε να χειριστούμε την εξαίρεση

14
Προστατευόμενη περιοχή - try
 Ένα τέτοιο μπλοκ ονομάζεται try block αφού εκεί
δοκιμάζουμε να κάνουμε κλήσεις σε διάφορες
«επικίνδυνες μεθόδους»
 Το try block είναι ένα κανονικό scoper που περικλείεται
από την κωδική λέξη try
try {
// κώδικας που παράγει εξαιρέσεις
}
 Προστασία από εξαιρέσεις: Bάζουμε όλον τον
«επικίνδυνο» κώδικα σε ένα try block και πιάνουμε όλες
τις εξαιρέσεις στο ίδιο μέρος.

15

Διαχειριστές εξαιρέσεων - catch


 Κάθε εξαίρεση που ανιχνεύεται μέσα στο try καταλήγει στον
αντίστοιχο κώδικα (catch block) που θα την εξυπηρετήσει. Τα catch
ελέγχονται διαδοχικά.
 Παράδειγμα:
try {
// κώδικας που παράγει εξαιρέσεις
} catch (type1 id1) {
// χειρισμός εξαιρέσεων τύπου 1
} catch (type2 id2) {
// χειρισμός εξαιρέσεων τύπου 2
} catch (type3 id3) {
// χειρισμός εξαιρέσεων τύπου 3
}
 Αν πολλές μέθοδοι στο try ρίχνουν τον ίδιο τύπο εξαίρεσης, τότε
χρειαζόμαστε μόνο έναν exception handler για αυτόν τον τύπο.

16
Η τάξη Exception
 Ένας διαχειριστής εξαιρέσεων με όρισμα τύπου Exception
συλλαμβάνει όλες τις εξαιρέσεις.
catch(Exception e) {
System.out.println(“caught an exception”);
}
 Γι’ αυτό μπαίνει στο τελευταίο catch στη σειρά για να πιάσει κάθε
άλλη εξαίρεση.
 H Exception και η Throwable προσφέρουν τις ακόλουθες μεθόδους:
 String getMessage()
 String toString() //τυπώνει το όνομα της εξαίρεσης
 void printStackTrace() //τυπώνουν το σωρό
 void printStackTrace(PrintStream) //μεθόδων που κλήθηκαν

17

Παράδειγμα
 Διαχείριση σφάλματος εισόδου
public double sumNumbers(){
double sum=0;
try{
sum+=readDouble();
}
catch(MySpecialException ex){ //θα συμβεί αν ο χρήστης δεν δώσει αριθμό
System.err.println(ex.toString()); //τυπώνει το όνομα της κλάσης εξαίρεσης
}
catch(Exception ex){ //θα συμβεί σε οποιαδήποτε άλλη περίπτωση λάθους
System.err.println(ex.getMessage()); //τυπώνει το μήνυμα της εξαίρεσης
}
return sum;
}
 Η MySpecialException είναι ειδικότερη από την Exception

18
Το block finally
 Όταν υπάρχει κάποιο κομμάτι κώδικα που θα πρέπει να
εκτελεστεί είτε συμβαίνει ένα Exception σε ένα try μπλοκ
είτε όχι βάζουμε τον κώδικα σε ένα finally μπλοκ ώς
εξής:
static Switch sw = new Switch();
try {
sw.on();
…//επικίνδυνος κώδικας
} catch (A a) {
...
} catch (B b) {
...
} finally {
sw.off(); //κώδικας που τρέχει πάντοτε και κάνει reset
}

19

Τερματισμός ή ανάνηψη (συνέχιση)


 Τερματισμός: Θεωρούμε ότι τα λάθη είναι κρίσιμα και δε
συνεχίζουμε την εκτέλεση του κώδικα από το σημείο που ρίχθηκε η
εξαίρεση
 Ανάνηψη: Προσπαθούμε να συνεχίσουμε την εκτέλεση του
προγράμματος από εκεί που διακόπηκε
while (true) {
try {
//κώδικας που παράγει εξαιρέσεις
}
catch (Type1 id1) { //διορθώνουμε την εξαίρεση
continue;}
...
catch (TypeN idN) { // διορθώνουμε την εξαίρεση
continue;}
// κώδικας που εκτελείται αν δεν υπάρχει εξαίρεση
break;
}

20
Παράδειγμα
 Ας διαχωρίσουμε τις εξαιρέσεις
public double readDouble() throws MySpecialException, Exception {
Scanner in = new Scanner(System.in);
if (in.hasNextDouble()) {
return in.nextDouble();
} else if (in.hasNext() && in.next().equals("=")){
throw new MySpecialException(); // αν ο χρήστης δώσει ‘=‘
}
else{
throw new Exception("Not a number"); // αν ο χρήστης δώσει
οτιδήποτε άλλο
}
}
21

Παράδειγμα (2)
 Τερματισμός επανάληψης
public double sumNumbers() {
double sum = 0;
while (true) {
try {
sum += readDouble();
} catch (MySpecialException ex) {
break;
} catch (Exception ex) {
System.err.println(ex.getMessage());
}
}
return sum;
}

22
Ιεραρχία εξαιρέσεων
 H Java περιέχει την τάξη Τhrowable που περιγράφει
οτιδήποτε μπορεί να ριχθεί σαν Exception
 Άλλες εξαιρέσεις ορίζονται στα πακέτα util, net και io.

23

Παράδειγμα
public class ExceptionMethods {
public static void main(String args[]) {
try {
throw new Exception(“Here’s my Exception”);
} catch (Exception e) {
System.out.println(“Caught Exception”);
System.out.println( e.getMessage());
System.out.println( e.toString());
System.out.println( e.printStackTrace());
}
}
}
Η δύο τελευταίες κλήσεις τυπώνουν
java.lang.Exception: Here’s my Exception

java.lang.Exception: Here’s my Exception


at ExceptionMethods.main

24
Κληρονομικότητα και εξαιρέσεις
 Όταν σε μια απόγονη τάξη κάνουμε override μια μέθοδο της γονικής
τάξης, τότε η μέθοδος δεν μπορεί να ρίχνει επιπλέον εξαιρέσεις.
overridden method does
class Test {
String method (String s){
not throw
if (s==null) java.lang.Exception
throw new NullPointerException();
else
return s;}}

class SubTest extends Test{


String method (String s) throws Exception{
if (s==null)
throw new Exception();
else
return s;}}

25

Παράδειγμα 1
 Ανάγνωση από πληκτρολόγιο
 Δημιουργούμε ένα αντικείμενο με χρήση του ρεύματος εισόδου
in (τάξη InputStream).
BufferedReader stdin=new BufferedReader(new
InputStreamReader(System.in));
 Και καλούμε τη μέθοδο ανάγνωσης γραμμής
try{
line=stdin.readLine();
}
catch (IOException e){
line=“”; //σε περίπτωση αποτυχίας γίνεται κενό
}

26
Παράδειγμα 2
 Μετατροπή String σε int
try {
x= Integer.parseInt(line);
}
catch(NumberFormatException e) {
x=0; //σε περίπτωση αποτυχίας γίνεται 0
}

27

5. Διαχείριση αρχείων
Ρεύματα
 Όταν ένα πρόγραμμα επικοινωνεί με την οθόνη, το πληκτρολόγιο,
ένα αρχείο κλπ., χρησιμοποιεί ρεύματα χαρακτήρων (streams) για
να στείλει ή να πάρει δεδομένα.
 Τρία προκαθορισμένα ρεύματα στη Java:
 System.in: Διαβάζει bytes εξ ορισμού από το πληκτρολόγιο.
 System.out: Στέλνει bytes εξ ορισμού στην οθόνη.
 System.err: Στέλνει μηνύματα λάθους εξ ορισμού στην οθόνη.
 «συνήθως». Μπορεί όμως να συνδεθεί με άλλη πηγή με τις
μεθόδους setIn, setOut, setErr της System
 π.χ. FileOutputStream f = new FileOutputStream("file.txt");
System.setOut(new PrintStream(f));

Προσωρινή αποθήκευση (buffering)


 Κάθε byte που διαβάζουμε από το αρχείο (ή το πληκτρολόγιο)
τοποθετείται σε μια προσωρινή μνήμη. Μόλις συγκεντρωθούν
«αρκετά» bytes τα χειριζόμαστε ανάλογα (π.χ. τα εμφανίζουμε στην
οθόνη, τα μετατρέπουμε στον κατάλληλο τύπο δεδομένων κλπ)
 Με buffer: γραφή και ανάγνωση σε τμήματα (“chunks”)
 Καθυστερεί ο χειρισμός ορισμένων bytes (καθώς περιμένουν να γεμίσει
ο buffer) π.χ. σε ένα 16-byte buffer, μπορεί να περιμένουμε να
διαβαστούν όλα τα bytes πριν χρησιμοποιήσουμε τα 4 πρώτα για έναν
int ή δεν γράφουμε τον ακέραιο στο αρχείο, μέχρι να γεμίσει ο buffer,
οπότε γράφουμε 4 int μαζί
 Λιγότερος επιπλέον φόρτος πρόσβασης στο δίσκος (I/O overhead)
 Χωρίς buffer: επεξεργαζόμαστε κάθε byte μόλις έρθει στη μνήμη
 Μικρότερη καθυστέρηση για το χειρισμό του ενός byte
 Μεγάλος επιπλέον φόρτος γραφής και ανάγνωσης από το δίσκο
Ρεύματα για bytes (Java 1.0)
 Όλα τα ρεύματα που θα δούμε βρίσκονται στο πακέτο io.
 Βρίσκονται κάτω από τις abstract τάξεις InputStream και
OutputStream οι οποίες περιέχουν τις βασικές μεθόδους
για είσοδο και έξοδο bytes.
 int read(): διαβάζει το επόμενο byte
 int read(byte[] b): διαβάζει τα επόμενα b.length bytes στον πίνακα
b
 long skip(long n): αγνοεί τα επόμενα n bytes
 int available(): επιστρέφει τον αριθμό των διαθέσιμων bytes
 void mark(int readlimit): σημαδεύει τη συγκεκριμένη θέση στο
αρχείο
 void reset(): επαναφέρει το δείκτη στην αρχή του αρχείο ή στο
τελευταίο σημάδι
 void close(): κλείνει το αρχείο

Υποκλάσεις των Input/Output


Streams
 Προσθέτουν περισσότερες λειτουργίες στα ρεύματα
 π.χ οι FilterInputStream και FilterOutputStream.
 Κατασκευαστής: FilterInputStream(InputStream in)
 Πεδία: in το InputStream με το οποίο συνδέεται

 AudioInputStream, ByteArrayInputStream,
 FileInputStream,
 FilterInputStream,
 ObjectInputStream,
 PipedInputStream,
 SequenceInputStream,
 StringBufferInputStream
5
Ρεύματα για bytes (2)
 Τάξεις που τις κληρονομούν είναι οι PrintStream (π.χ. η
System.out), οι BufferedInputStream και
BufferedOutputStream που έχουν κάποιο buffer,
 Κατασκευαστής: BufferedInputStream(InputStream in)
 Πεδία: buf : ένα byte[] που αποθηκεύει τα δεδομένα
count: το πλήθος των bytes στο buffer
 οι DataInputStream και DataOutputStream που
διαβάζουν βασικούς τύπους υλοποιώντας αντίστοιχα
interfaces (DataInput και DataOutput).
 Κατασκευαστής: DataInputStream(InputStream in)
 Μέθοδοι: readFloat(), διαβάζει 4 bytes και επιστρέφει float

Ρεύματα για bytes (3)

 Για ανταλλαγή δεδομένων όταν έχουμε πολλά threads υπάρχουν οι


PipedInputStream / PipedOutputStream
 Κατασκευαστής: PipedInputStream()
PipedOutputStream(PipedInputStream src)
 Μέθοδοι: connect(PipedInputStream snk)
write(byte[] b, int off, int len)
 Για αρχεία υπάρχουν οι FileInputStream και FileOutputStream.
 Κατασκευαστής: FileInputStream(String filename)
throws FileNotFoundException
Ιεραρχία

Συνδυασμός ρευμάτων bytes


float, String, κλπ.

DataInputStream
bytes

FilterInputStream ή
BufferedInputStream

bytes

FileInputStream
InputStream

bytes
Αρχείο
Ρεύματα για χαρακτήρες (Java 1.1)
 Για τη διαχείριση ρευμάτων 16-bit (Unicode) χαρακτήρων
υπάρχουν οι abstract τάξεις Reader και Writer με αντίστοιχες
ιεραρχίες

Βασικές μέθοδοι
 Οι Reader/Writer έχουν μεθόδους για χαρακτήρες
int read()
// ο ακέραιος αντιστοιχεί σε κάποιο char με δεδομένο charset
// -1 όταν το ρεύμα είναι άδειο (π.χ. EOF)
int read(char cbuf[])
int read(char cbuf[], int offset, int length)
int write(int c)
 Οι InputStream/OutputStream αντίστοιχα για bytes
π.χ. int write(byte b[], int offset, int length)
 Οι InputStreamReader και OutpuStreamWriter μπορούν να
χρησιμοποιηθούν ως γέφυρες
 Κατασκευαστής: InputStreamReader(InputStream in)
Ρεύματα για χαρακτήρες (2)
 LineNumberReader
 Κατασκευαστής: LineNumberReader(Reader in)
 Μέθοδοι: readLine() : διαβάζει μια γραμμή σε String
getLineNumber(): επιστρέφει τον αριθμό γραμμής
 PrintWriter
 Κατασκευαστές: PrintWriter(File file)
PrintWriter(OutputStream out)
PrintWriter(String fileName)
 Μέθοδοι: print(float f), print(String s), println(Object o)
write(String s)
ΠΡΟΣΟΧΗ: Όταν δε χρειαζόμαστε πλέον ένα stream, ένα reader ή
writer τον κλείνουμε με τη μέθοδο close()

Συνδυασμός ρευμάτων
χαρακτήρων char/String

LineNumberReader

char/String

FileReader
InputStreamReader

bytes

byte

File
InputStream
Ρεύματα και αρχεία

H κλάση File
 Είναι η βασική κλάση για αρχεία και φακέλους
 Μέθοδοι της File
 exists: ελέγχει αν υπάρχει το αρχείο
 canRead: ελέγχει αν μπορούμε να διαβάσουμε από το αρχείο
 canWrite: ελέγχει αν μπορούμε να γράψουμε στο αρχείο
 delete: διαγράφει το αρχείο και επιστρέφει true (αν πετύχει)
 length: επιστρέφει το μέγεθος του αρχείου σε bytes
 getName: επιστρέφει το όνομα του αρχείου (μόνο)
 getPath: επιστρέφει το πλήρες μονοπάτι του αρχείου

File numFile = new File(“numbers.txt”);


if (numFile.exists())
System.out.println(numfile.length());
Αρχεία Text και Binary
 Αρχεία Text: περιέχουν τα δεδομένα σε μορφή
εκτυπώσιμων χαρακτήρων
 Ένα byte για κάθε χαρακτήρα (για την κωδικοποίηση ASCII)
 Δύο bytes για κάθε χαρακτήρα (character) (για την
κωδικοποίηση Unicode, και για πολλές γλώσσες)
 Μπορούμε να διαβάσουμε τα αρχεία από ένα "text editor"
 Αρχεία Binary: περιέχουν κωδικοποιημένα δεδομένα,
όπως εντολές προς εκτέλεση ή αριθμητικά δεδομένα
 Δεν είναι κατάλληλα για εκτύπωση
 Μπορούν να διαβαστούν από υπολογιστές αλλά όχι από
ανθρώπους
 Είναι πιο εύκολο για ένα πρόγραμμα να τα χειριστεί.

Ρεύματα εισόδου/εξόδου για κείμενο

 Κλάσεις για έξοδο (σε αρχείο):


 PrintWriter
 FileOutputStream [ή FileWriter]
 Κλάσεις για είσοδο (από αρχείο):
 BufferedReader
 FileReader
 Η FileOutputStream και η FileReader δέχονται ως
όρισμα ένα όνομα αρχείου
 Η PrintWriter και η BufferedReader έχουν χρήσιμες
μεθόδους για γραφή και ανάγνωση
Ρεύματα αρχείων

Παράδειγμα
File smileyFile = new File(“smiley.txt”);

FileInputStream smileyInStream = new


FileInputStream(smileyFile);

FileDescriptor fileID = smileyFile.getFD();

FileInputStream anotherFile = new FileInputStream


(fileID);

if (smileyFile.canRead()){

}

19
Διάβασμα από αρχεία
 Η τάξη File (στο πακέτο java.io.*) αντιπροσωπεύει:
 Ένα αρχείο:
File arxeio = new File("c:\\1.txt");
 Ένα κατάλογο:
File katalogos = new File(".");
String path=katalogos.getAbsolutePath();
File[] files=katalogos.listFiles();
 Η τάξη FileReader (FileWriter) δημιουργεί ένα ρεύμα
εισόδου (εξόδου) από αρχείο:
 FileReader arxeio = new FileReader("c:\\1.txt"));

Ανάγνωση - Εγγραφή
 Ανάγνωση: Όπως και με το πληκτρολόγιο συνδέουμε το
πρόγραμμά μας με το αρχείο με έναν BufferedReader
BufferedReader eisodos = new BufferedReader(new
FileReader("c:\\1.txt"));
 Εγγραφή: Συνδέουμε το πρόγραμμά μας με το αρχείο με
ένα BufferedWriter
PrintWriter exodos =new PrintWriter(new BufferedWriter(new
FileWriter(“c:\\copy.txt")));
String s;
while((s = eisodos.readLine()) != null )
exodos.println(lineCount++ + ": " + s);
exodos.close();
Παράδειγμα - Αντιγραφή
import java.io.*;
class test{
public static void main(String args[]){
try{
BufferedReader eisodos = new BufferedReader(new
FileReader("c:\\autoexec.bat"));
PrintWriter exodos =new PrintWriter(new BufferedWriter(new
FileWriter(“c:\\copy.txt")));
String s;
while((s = eisodos.readLine()) != null )
exodos.println(s);
exodos.close();
}
catch (Exception ex){ System.out.println(ex);}
}
}

Binary αρχεία
Σειριακή μεταφορά αντικειμένων
 Όταν θέλουμε να στείλουμε ολόκληρα αντικείμενα σε ένα
ρεύμα χρησιμοποιούμε τις τάξεις ObjectInputStream και
ObjectOutputStream
 Απεικονίζουμε το αντικείμενο με σειριακή μορφή ώστε να
μπορούμε να το ανακτήσουμε (serialization)
 Κατασκευαστής: ObjectOutputStream(OutputStream out)
 Μέθοδοι: writeInt(int val), writeObject(Object o), flush()
 Κατασκευαστής: ObjectInputStream(InputStream in)
 Μέθοδοι: int readInt(), Object writeObject(), flush()

 Η κλάση του αντικειμένου πρέπει να υλοποιεί το


Serializable interface

Παράδειγμα
try{
FileOutputStream out = new FileOutputStream(“output.dat");
ObjectOutputStream s = new ObjectOutputStream(out);
s.writeObject("Today");
s.writeObject(new Date());
s.flush();
s.close();
FileInputStream in = new FileInputStream("output.dat");
ObjectInputStream t=new ObjectInputStream(in);
String today = (String)t.readObject();
Date date = (Date)t.readObject();
t.close();
System.out.println(today+”\n”+date);
}
catch (Exception e){
e.printStackTrace();
}
Serializable Interface
 Ένα αντικείμενο είναι serializable αν η κλάση του
υλοποιεί το java.io.Serializable interface.
 Το interface δεν έχει επιπλέον μεθόδους για να
υλοποιήσουμε. Είναι marker interface.
 Με τη δήλωση επιτρέπουμε στην Java να
αυτοματοποιήσει το μηχανισμό αποθήκευσης
των αντικειμένων από/σε αρχεία
 Μπορούμε επίσης να καθορίζουμε τι θα
αποθηκεύεται και τι όχι
26

Προσοχή
 Τι γίνεται αν το αντικείμενο περιέχει γνωρίσματα μη
σειριοποιήσιμα;
 Δεν σειριοποιείται.
 Όμοια και ένας πίνακας αντικειμένων
 Μπορούμε να σειριοποιήσουμε τα υπόλοιπα
γνωρίσματα δηλώνονται ως transient αυτά που θα
αγνοηθούν
public class Foo implements java.io.Serializable {
private int v1; // σειριοποιείται
private static double v2;
private transient A v3 = new A();
}
27
Αρχεία τυχαίας πρόσβασης
 Η τάξη RandomAccessFile δημιουργεί αρχεία στα οποία
η ανάγνωση και γραφή δε γίνεται σειριακά αλλά σε
οποιαδήποτε θέση.
 Κατασκευαστής:
RandomAccessFile(String name, String mode)
RandomAccessFile(File file, String mode)
mode: “r” μόνο για ανάγνωση, “rw” για ανάγνωση/εγγραφή
 Μέθοδοι:
skipBytes(int n) //προχωρά το δείκτη κατά n bytes
seek(long pos) //πάει το δείκτη στη θέση pos του αρχείου
long getFilePointer() //επιστρέφει τη θέση του δείκτη

Πώς ελέγχω το τέλος του αρχείου;


 Βάζω έναν ειδικό χαρακτήρα και σταματώ μόλις
τον διαβάσω
 Ψάχνω για έναν ειδικό χαρακτήρα στο τέλος του
αρχείου (τα text αρχεία έχουν τέτοιο χαρακτήρα)
 Χρησιμοποιώ την κλάση Scanner
while (inFile.hasNext())
while (inFile.next()!=null)
 Πυροδοτώ μια εξαίρεση τέλους-αρχείου και την
ανιχνεύω στον κώδικά μου
Java 7

30

Νέο πακέτο java.nio.file


 Περιέχει κλάσεις και interfaces όπως οι Path, Paths, Files,
DirectoryStream, WatchService κλπ.
 Παράδειγμα: αντιγραφή αρχείου:
Path src = Paths.get("/home/fred/readme.txt");
Path dst = Paths.get("/home/fred/copy_readme.txt");
Files.copy(src, dst,
StandardCopyOption.COPY_ATTRIBUTES,
StandardCopyOption.REPLACE_EXISTING);

http://cs.brown.edu/courses/cs161/papers/j-nio-ltr.pdf 31
java.nio.channels
 java.nio.Channel  Stream
 Read & Write  Read or write
 Read & Write asynchronously
 Πάντα επικοινωνούμε μέσω ενός Buffer αντικειμένου
 Implementations
 FileChannel για αρχεία
 DatagramChannel για συνδέσεις UDP.
 SocketChannel για συνδέσεις TCP
 ServerSocketChannel για ακροατές εισερχόμενων TCP συνδέσεων (web server).
Κάθε σύνδεση δημιουργεί ένα SocketChannel

32

java.nio.Buffer

 Abstract class
 Αναλαμβάνει την επικοινωνία με ένα channel
 Implementations
 ByteBuffer, MappedByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer,
LongBuffer, ShortBuffer
 Methods
 flip(): switches a Buffer from writing mode to reading mode.
 rewind() sets the position back to 0, so you can reread all the data in the buffer
 clear() the position is set back to 0 and the limit to capacity
 compact() copies all unread data to the beginning of the Buffer
 Buffer.mark() marks a given position in a Buffer.
 You can reset to that position by calling the Buffer.reset()

33
Παράδειγμα - Read
RandomAccessFile fin = new RandomAccessFile( "readbytes.txt“, “rw” );
FileChannel fc = fin.getChannel();
ByteBuffer buffer = ByteBuffer.allocate( 1024 );
int bytesRead = inChannel.read(buf); //write from channel to buffer
while (bytesRead != -1) {
System.out.println("Read " + bytesRead);
buf.flip(); //prepare buffer for read
while(buf.hasRemaining()){
System.out.print((char) buf.get());
}
buf.clear();
bytesRead = inChannel.read(buf);
}
fin.close();
34

Παράδειγμα - Write
//WRITE
FileOutputStream fout = new FileOutputStream("writebytes.txt" );
FileChannel fc = fout.getChannel();
ByteBuffer buffer = ByteBuffer.allocate( 1024 );
for (int i=0; i<message.length; i++) {
buffer.put( message[i] );
}
buffer.flip(); //prepare buffer for read
fc.write( buffer ); //read from buffer to channel

35
Java 7

36

Αυτόματη διαχείριση πόρων


try-with-resources
public void oldTry() { public void newTry() {
try { try (
fos = new FileOutputStream(“a.txt"); FileOutputStream fos = new
dos = new DataOutputStream(fos);
dos.writeUTF("Java 6"); FileOutputStream(“a.txt");
} catch (IOException e) { DataOutputStream dos = new
e.printStackTrace(); DataOutputStream(fos)
} finally { ){
try { dos.writeUTF("Java 7");
fos.close(); }
dos.close(); catch (IOException e) {
} catch (IOException e) { // log the exception
// log the exception
} }
} }
}

37
Ο τελεστής <>
 diamond operator
 Αντί για
HashMap<String, Stack<String>> map =
new HashMap<String, Stack<String>>();
 Μπορώ να γράψω:
HashMap<String, Stack<String>> map =
new HashMap<>;

38

Strings στη switch


 Αντί για  Γράφουμε

if (input.equals(“yes”)) {
return true; switch(input) {
} else if (input.equals(“no”)) { case “yes”: return true;
return false; case “no”: return false;
} else { default: askAgain();
askAgain(); }
}

39
Διαχωριστικά χιλιάδων
 Αντί για
int million = 1000000;
γράφουμε
int million = 1_000_000;

40

Multi-catch
 public void newMultiMultiCatch() {
try {
methodThatThrowsThreeExceptions();
} catch (ExceptionOne e) {
// deal with ExceptionOne
} catch (ExceptionTwo | ExceptionThree e) {
// deal with ExceptionTwo and ExceptionThree
}
}

41
6. Διαχείριση δεδομένων

Σχεσιακές Βάσεις Δεδομένων


 Τα δεδομένα μας οργανώνονται σε ένα ή περισσότερους
πίνακες: σε στήλες και σειρές
 Κάθε πίνακας έχει ένα όνομα και αποτελείται από στήλες
(πεδία). Κάθε πεδίο έχει συγκεκριμένο τύπο και
αποθηκεύει τιμές αυτού του τύπου
 Κάθε εγγραφή (π.χ. τα στοιχεία ενός προϊόντος)
αποθηκεύεται σε μια γραμμή (πλειάδα) του πίνακα.
Film
code title director … year
1150 The Godfather Francis Ford Coppola 1972

1151 The Shawshank Frank Darabont 1994


Redemption
Συστήματα διαχείρισης ΒΔ
 Η βάση δεδομένων μπορεί να είναι ένα αρχείο ή ένα
σύνολο αρχείων που το διαχειριζόμαστε μόνο με το
κατάλληλο σύστημα (π.χ. MS Access, Oracle, SQL
Server)
 Εκτός από το να αποθηκεύει τα δεδομένα, το ΣΔΒΔ μας
επιτρέπει να υποβάλλουμε ερωτήσεις προς αυτά
π.χ. φέρε μου τους τίτλους για τις ταινίες που βγήκαν το 1995
 Για την υποβολή ερωτήσεων χρησιμοποιούμε τη
γλώσσα SQL (Structured Query Language)
 Κάθε ερώτηση σε SQL μας επιστρέφει ως απάντηση μια
λίστα με πλειάδες (recordset – σύνολο εγγραφών)

Java και ΒΔ
 Για να επικοινωνήσει η εφαρμογή μας με μια βάση
δεδομένων θα πρέπει:
 Να συνδεθούμε με το ΣΔΒΔ (όπως θα ανοίγαμε ένα ρεύμα
εισόδου/εξόδου προς ένα αρχείο)
 Να συνδεθούμε με τη συγκεκριμένη ΒΔ (αν το σύστημα διατηρεί
ταυτόχρονα πολλές ΒΔ).
 Να υποβάλλουμε ερωτήσεις SQL και
 Να διαχειριστούμε τη λίστα των εγγραφών που παίρνουμε ως
απάντηση
ερωτήσεις SQL
Java Application Σύνδεση ΒΔ
λίστα εγγραφών
Java Database Connectivity
 Το JDBC επιτρέπει στις εφαρμογές Java να
συνδεθούν και να "ρωτήσουν" μια ΒΔ.
 Οι ερωτήσεις υποβάλλονται σε μια κοινή μορφή
και μεταφράζονται στη μορφή που υποστηρίζει
κάθε ΣΔΒΔ.
 Δεν υποστηρίζει ειδικές λειτουργίες του κάθε
ΣΔΒΔ
 Το πακέτο java.sql περιέχει τις τάξεις για το JDBC 1.0
 Το πακέτο javax.sql υποστηρίζει τα JDBC 2.0 και 3.0

Java Database Connectivity API (1)


Υπάρχουν 4 κατηγορίες JDBC οδηγών:
 JDBC-ODBC bridge
 Native κώδικας και JDBC
 Γενικός JDBC driver γραμμένος σε Java
 JDBC driver σε Java
Στον πρώτο τρόπο ο οδηγός έρχεται με το
SDK.
Στους άλλους τρεις ο οδηγός διατίθεται από το
δημιουργό του ΣΔΒΔ ή κάποιον τρίτο.
JDBC-ODBC Bridge
• To Open DataBase Connectivity (ODBC) είναι ένα πρότυπο που
ανέπτυξε η Microsoft για τα Windows.
• Κάθε ΣΔΒΔ που εγκαθιστούμε στα windows εγκαθιστά τον
αντίστοιχο ODBC οδηγό. Οι ερωτήσεις προς τον οδηγό
μετατρέπονται σε κλήσεις στο ΣΔΒΔ.
• Ο JDBC-ODBC οδηγός είναι ο μόνος τρόπος για να συνδεθούμε
με μια ΒΔ σε Access.
• Ο ευκολότερος αλλά και πιο αργός τρόπος.

Java application application process Data source

ODBC process

JDBC API JDBC-ODBC Bridge ODBC API ODBC Layer

Μικτός κώδικας (Java και Native)


• O οδηγός JDBC έχει κώδικα java αλλά και κώδικα σε C
(συνήθως) και μιλά απευθείας με το ΣΔΒΔ
• Πρέπει όποιος θέλει να συνδεθεί με τη ΒΔ να κατεβάσει το
σωστό JDBC οδηγό
• Πιο αποτελεσματικό και γρήγορο από το JDBC-ODBC bridge

Java application application process Data source

JDBC Driver
JDBC API (part Java, Vendor-specific
part native code) API
Χρήση ενδιάμεσου Server για την πρόσβαση
• Ένας ξεχωριστός server δίνει πρόσβαση στο ΣΔΒΔ. Ιδανική λύση
για εσωτερικά δίκτυα (intranets).
• Οι δημιουργοί των ΣΔΒΔ παρέχουν τους επιπλέον servers που
μιλούν με τις βάσεις τους και καταλαβαίνουν κλήσεις σε JDBC
• O οδηγός JDBC στον client μιλά με το JDBC server με κάποιο
βασικό πρωτόκολλο
• Ο JDBC server μιλά με χρήση native οδηγού με τη βάση.
• Πολύ γρήγορη πρόσβαση

Java application application process Data source

network
JDBC Driver Native
JDBC API JDBC Driver Server Driver
Intermediate data
access server:
Gateway for multiple
database server

Καθαρός οδηγός Java


• Οι κλήσεις στον οδηγό JDBC μεταφράζονται σε κλήσεις στη
βάση
• Απαιτεί από τον client να φορτώσει τον κατάλληλο οδηγό.
• Απλή αρχιτεκτονική και γρήγορη
• Οι δημιουργοί των ΣΔΒΔ παρέχουν τους pure java drivers

Java application application process Data source

network
JDBC API JDBC Driver
O διαχειριστής των οδηγών
 Μια εφαρμογή μιλά ταυτόχρονα
σε πολλές ΒΔ
 Με διαφορετικό τύπο οδηγού
στην κάθε μια
 Για το λόγο αυτό υπάρχει ο
JDBC Driver Manager
 O DriverManager είναι μια τάξη
που περιέχεται στο βασικό
πακέτο java.sql
 Έχει τη μέθοδο getConnection
για να δημιουργούμε μια
σύνδεση σε μια ΒΔ

Το μοντέλο του JDBC – Τάξεις


 DriverManager, διαχειρίζεται συνδέσεις σε ένα ή περισσότερα ΣΔΒΔ
 Connection, προσδιορίζει μία σύνδεση σε μια συγκεκριμένη ΒΔ
 Statement, περιέχει μια ερώτηση SQL που στέλνεται για εκτέλεση στη
ΒΔ
 ResultSet, περιέχει τα αποτελέσματα εκτέλεσης της ερώτησης SQL
(έχει τη μορφή πίνακα με μία ή περισσότερες εγγραφές-records)

Driver Manager Database


ResultSet
Connection
SQL Statement

Database
ResultSet
Connection
SQL Statement
Βήματα χρήσης JDBC
1. Φορτώνουμε τον Driver. Class
2. Συνδεόμαστε με τη ΒΔ. Φτιάχνουμε ένα forName
αντικείμενο Connection
3. Φτιάχνουμε μια δήλωση SQL (Statement)
προς τη σύνδεση αυτή. DriverManager
4. Εκτελούμε διαδοχικά (μια ή περισσότερες) getConnection
ερωτήσεις SQL στο αντικείμενο Statement.
Με χρήση της executeQuery ή
executeUpdate Connection
5. Επεξεργαζόμαστε το αντικείμενο ResultSet createStatement
που φτιάχνεται όταν κάνουμε ερωτήσεις
επιλογής στο βήμα 4
6. Κλείνουμε τα Statement και Connection
αντικείμενα. Statement

Βήματα χρήσης JDBC


Σε ένα αντικείμενο Statement στέλνουμε SQL ερωτήσεις και
ενημερώσεις προς τη βάση. Οι ερωτήσεις επιστρέφουν είτε ένα
αντικείμενο ResultSet είτε το πλήθος εγγραφών που ενημερώθηκαν.

Statement
SQL
executeQuery ResultSet
“Select ...”

Statement
SQL
executeUpdate int
“Delete ...”
Παράδειγμα
 Έστω ότι έχω εγκαταστήσει το ΣΔΒΔ Oracle στο
μηχάνημα με IP διεύθυνση 10.100.51.123
 Η Oracle δέχεται κλήσεις στο port 1521
 Στο ΣΔΒΔ έχω φτιάξει μια δική μου βάση
δεδομένων που λέγεται test
 Για να συνδεθώ στη βάση χρησιμοποιώ
όνομα/κωδικό: test/test
 Στη βάση αυτή υπάρχει ο πίνακα Film που
εμφάνισα σε προηγούμενη διαφάνεια.

1. Σύνδεση με τη βάση
 Jdbc:<subprotocol>:<subname>
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
String url ="jdbc:oracle:thin:@//10.100.51.123:1521/orcl";
Connection con = DriverManager.getConnection(url,“test", “test");
...
}
Πρέπει ο client να έχει τον αντίστοιχο οδηγό
 Αν έχω Windows και θέλω να χρησιμοποιήσω τον πρώτο
τύπο driver, φτιάχνω ένα νέο όνομα πηγής δεδομένων στο
OBDC των Windows (έστω με όνομα dsn) και φορτώνω τον
αντίστοιχο οδηγό.
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url ="jdbc:odbc:dsn";
jdbc:odbc:dsn

Όνομα: διεύθυνση του


Πρωτόκολλο: Υπο-πρωτόκολλο: database server, port,
πάντα JDBC ορίζει το ΣΔΒΔ όνομα βάσης. Η σύνταξη
εξαρτάται από τον οδηγό

jdbc:oracle:thin:@//10.100.51.123:1521:orcl

2. Διαμόρφωση SQL ερωτήσεων


try{...
Statement stmt = con.createStatement();
String sqlselect = "SELECT Title, Director,Year FROM
Film";
ResultSet rs = stmt.executeQuery(sqlselect);
int rowschanged = stmt.executeUpdate("UPDATE Film
set Year=1971 WHERE Title='Birds' ");
...}
 Όλη η επικοινωνία με τη ΒΔ γίνεται μέσα σε ένα
βρόχο try που ακολουθείται από διαδικασίες
ανίχνευσης λάθους (SQLException κλπ.)
Διαχείριση αποτελεσμάτων
• Το ResultSet έχει ένα εσωτερικό δείκτη που μπορεί να μετακινηθεί
μπρος/πίσω.
• Κάθε φορά μπορούμε να πάρουμε τις τιμές της τρέχουσας εγγραφής
• Μέθοδοι: next(), previous(), first(), last(). Μετακινούν το δείκτη
και επιστρέφουν true αν υπάρχει εγγραφή εκεί που πάει ο
δείκτης. π.χ. αν ο δείκτης είναι στην αρχή η Previous()
επιστρέφει false κ.ο.κ.
• Οι isLast() και isFirst() ελέγχουν την τρέχουσα θέση του δείκτη

Εσωτερικός δείκτης ResultSet

Record 1 Record 2 Record 3 Record 4

3. Εμφάνιση αποτελεσμάτων
try {…
ResultSet rs = stmt.executeQuery(sqlselect);
while(rs.next()){
title = rs.getString(1);
director = rs.getString(2);
year = rs.getInt(3);
row+=title+” “ +director+” “+year+”\n”;
}
stmt.close(); //κλείσιμο της δήλωσης
con.close(); //κλείσιμο της σύνδεσης
}
catch(Exception e) {…}
Ακύρωση και υποβολή
ερώτησης
 Εξ ορισμού κάθε ερώτηση που γίνεται στη ΒΔ
υποβάλλεται (γίνεται και commit)
 Αν θέλουμε να κάνουμε πολλαπλές
ερωτήσεις/ενημερώσεις και στο τέλος να υποβάλλουμε
τα αποτελέσματα:
 απενεργοποιούμε την αυτόματη υποβολή.
connection.setAutoCommit(false)
 και καλούμε
connection.commit() για να εφαρμόσουμε τις αλλαγές
connection.rollback() για να ακυρώσουμε τις αλλαγές
ως την τελευταία εφαρμογή

Τεχνικές
πρόσβασης στη ΒΔ

22
Παράδειγμα: JDBC
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.SQLException;
 //... try {
 Connection conn =
DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=some");
 // Do something with the Connection // ...
 } catch (SQLException ex) {
 / / handle any errors
 System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " +
ex.getSQLState()); System.out.println("VendorError: " + ex.getErrorCode());
 //...

MySQL Connector/J Documentation

Παράδειγμα: JDBC (συνέχ.)


 ResultSet rs = null;
 try { stmt = conn.createStatement();
 rs = stmt.executeQuery("SELECT foo FROM bar");
 // or alternatively, if you don't know ahead of time that // the query will be a SELECT...
 if (stmt.execute("SELECT foo FROM bar")) {
 rs = stmt.getResultSet(); }
 // Now do something with the ResultSet ....
 } catch (SQLException sqe) {
 // it is a good idea to release
 }
Πλαίσια απεικόνισης αντικειμένων σε
σχεσιακό

 Τι προσφέρουν
− Διαφανή υποστήριξη «παραμενόντων
αντικειμένων» (transparent persistence)
− Caching
− Διαχείριση δοσοληψιών (Transaction
management)
 Που θα βρω πληροφορίες
− https://docs.oracle.com/javaee/7/tutorial/partp
ersist.htm#BNBPY

Ένα παράδειγμα με το Hibernate

 Δύο κλάσεις του πεδίου εφαρμογής:


− Book
− Author
− Με σχέση πολλά προς πολλά.
Η κλάση Book
package example;
@Entity
public class Book {

@Id
@GeneratedValue
private Integer id;
private String title;
private String subtitle;

@ManyToMany
private Set<Author> authors = new HashSet<Author>();

private Date publicationDate;

public Book() {
}

// standard getters/setters follow here


...
}

Η κλάση Author
package example;
@Entity
public class Author {

@Id
@GeneratedValue
private Integer id;
private String name;
public Author() {
}
// standard getters/setters follow here
...
}
Η κλάση Book Manager
class BookManager {
private void createAndStoreBook(String title, Date theDate) {
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();

Book aBook = new Book();


aBook.setTitle(“Introduction to Software Engineering”);
//...
session.save(theBook);
tx.commit();
HibernateUtil.closeSession();
}
}

7. Συλλογές δεδομένων
Συλλογές και ενέργειες
 ArrayList
 Αναζήτηση συγκεκριμένου στοιχείου
 Αναζήτηση ελαχίστου/μεγίστου
 Συνάθροιση

 Πίνακας
 Εισαγωγή
 Εισαγωγή με έλεγχο διπλοτύπων

Παράδειγμα
ArrayList<Department> allDeps = new ArrayList<Department>();
allDeps.add(new Department(101,”Informatics”,40));
allDeps.add(new Department(102,”Geography”,100));
allDeps.add(new Department(105,”Physics”,200));
allDeps.add(new Department(103,”Dietetics”,80));
allDeps.add(new Department(104,”Ecology”,80));

Department[] allDepsArray=new Department[10];


allDepsArray[0]=new Department(101,”Informatics”,40);
allDepsArray[1]=new Department(102,”Geography”,100);
allDepsArray[5]=new Department(105,”Physics”,200);
allDepsArray[3]=new Department(103,”Dietetics”,80);
allDepsArray[4]=new Department(104,”Ecology”,80);

Πώς διαγράφω το τμήμα Physics; 

3
Διαγραφή μέσω αναζήτησης (ArrayList)

 Ψάχνω να βρω σε ποια θέση υπάρχει το τμήμα Physics.


Αναζήτηση
for (int i=0;i<allDeps.size();i++){
if (allDeps.get(i).getName().equals(“Physics”)){
allDeps.remove(i); //και διαγραφή
break; //σταματώ την επανάληψη
}
}
Η χρήση ArrayList δεν αφήνει κενές θέσεις (null) αλλά
μεταθέτει τα αντικείμενα
4

Διαγραφή μέσω αναζήτησης (Array)

 Ψάχνω να βρω σε ποια θέση υπάρχει το τμήμα Physics.


Αναζήτηση
for (int i=0;i<allDepsArray.length;i++){
if ( allDepsArray[i]!=null &&
allDepsArray[i].getName().equals(“Physics”)) {
allDepsArray[i]=null; //και διαγραφή
break; //σταματώ την επανάληψη
}
}
Η χρήση πίνακα αφήνει κενές θέσεις (null)
5
Αναζήτηση μεγίστου/ελαχίστου
int maxnum= Integer.MIN_VALUE;
for (int i=0;i<allDeps.size();i++){
if (allDeps.get(i).getNumStudents()>maxnum){
maxnum=allDeps.get(i).getNumStudents();
}
}
----------------------------------------------------------------------------------
int minnum= Integer.MΑΧ_VALUE;
for (int i=0;i<allDepsArray.length;i++){
if (allDepsArray[i]!=null && allDepsArray[i].getNumStudents()>minnum){
minnum=allDepsArray[i].getNumStudents();
}
}

Εισαγωγή σε πίνακα
boolean inserted=false;
for (int i=0;i<allDepsArray.length;i++){
if ( allDepsArray[i]==null) //αν υπάρχει κενό
allDepsArray[i]=new Department(106,”Maths”,200);
inserted=true;
break; //σταματώ την επανάληψη
}
}

Εισαγωγή σε ArrayList
allDeps.add(new Department(106,”Maths”,200));

7
Εισαγωγή με έλεγχο διπλοτύπων
 Η εισαγωγή με έλεγχο διπλοτύπων θα γίνει σε δύο φάσεις:
 Αναζήτηση για το αν υπάρχει ή όχι το αντικείμενο στον πίνακα ή τη
λίστα
 Εισαγωγή – στο τέλος ή σε κενή θέση - σε περίπτωση που δεν υπάρχει
 Υπάρχουν πιο γρήγορες λύσεις;
 Η ArrayList διαθέτει μεθόδους:
 int indexOf(Object elem): επιστρέφει τη θέση πρώτης εμφάνισης του
elem στη λίστα
 int lastIndexOf(Object elem)
 boolean contains(Object elem) : επιστρέφει true αν η λίστα περιέχει το
elem
 Object remove(int index) : διαγράφει το στοιχείο στη θέση index της
λίστας και μας το επιστρέφει

Σύγκριση: Η μέθοδος equals


 Για να δουλέψουν οι προηγούμενοι μέθοδοι για λίστες με αντικείμενα
δικών μας κλάσεων πρέπει στις κλάσεις μας να έχουμε μια μέθοδο
equals π.χ.
public boolean equals(Object o){
Department d=(Department)o; // πιθανό να παράγει
//ClassCastException
if (this.id==d.getId() && this.name.equals(d.getName()) &&
this.numStudents==d.getNumStudents())
return true;
else
return false;
}
9
Ταξινόμηση
 Με ποιο τρόπο μπορώ να ταξινομήσω τα στοιχεία ενός πίνακα ή μιας
λίστας; BubbleSort:
public void bubbleSort(int[] unsortedArray, int length) {
int temp, counter, index;
for(counter=0; counter<length-1; counter++) {
for(index=0; index<length-1-counter; index++) {
if(unsortedArray[index] > unsortedArray[index+1]) {
temp = unsortedArray[index];
unsortedArray[index] = unsortedArray[index+1];
unsortedArray[index+1] = temp;
}
}
}
}
10

Διάταξη
 Η διάταξη στους ακεραίους είναι δεδομένη
 Τι γίνεται όμως με τις δικές μας κλάσεις;
 Πώς μπορούμε να ορίσουμε διάταξη στα αντικείμενά
τους;

Comparable
public interface Comparable
{
int compareTo(Object o);
}
Department

11
public class Department implements Comparator{

public int compareTo(Object o){
Department d=(Department)o; // πιθανό να παράγει
//ClassCastException
if (this.numStudents>d.getNumStudents())
return 1;
else if (this.numStudents<d.getNumStudents())
return -1;
else
return 0;
}
}
12

Ταξινόμηση

Collections.sort(allDeps);

Ταξινομεί τα τμήματα με βάση τον αριθμό


σπουδαστών που έχουν
Χρησιμοποιεί την QuickSort

13
Δομή δεδομένων σε Java
 Μπορώ να υλοποιήσω μια δομή δεδομένων σε
Java; π.χ. Queue
public class DepQueue{
private int N; // number of elements on queue
private Node first; // beginning of queue
Node last; // end of queue
private class Node {
private Department dep;
private Node next;
}

14

public DepQueue() { public boolean isEmpty() { return first == null; }


public int length() { return N; }
first = null;
public int size() { return N; }
last = null;
}
public void enqueue(Department dep) {
Node x = new Node();
x.dep = dep;
if (isEmpty()) { first = x; last = x; }
else { last.next = x; last = x; }
N++;
}
public Item dequeue() {
if (isEmpty())
throw new RuntimeException("Queue is empty");
Department dep = first.dep;
first = first.next;
N--;
return dep;
}
15
Πλαίσιο συλλογών

Collections Framework

Πλαίσιο γενικότερα
 Ως πλαίσιο ορίζεται το σύνολο των τάξεων που καθορίζει
το σχεδιασμό λύσης για μια οικογένεια προβλημάτων
 Περιλαμβάνει κάποιες βασικές τάξεις αλλά μπορεί να
επεκταθεί
 Καθορίζει την αρχιτεκτονική μιας εφαρμογής: τις τάξεις,
τα αντικείμενα, τις μεταξύ τους συνεργασίες και τον
έλεγχο των νηματικών διεργασιών
 Ταυτόχρονα προσφέρει και έτοιμες υλοποιήσεις που
μπορούμε να χρησιμοποιήσουμε
Πλαίσιο διαχείρισης συλλογών
 Το πρόβλημα είναι η διαχείριση συλλογών
αντικειμένων
 Το πλαίσιο καθορίζει τις τάξεις για τους
διάφορους τύπους συλλογών και τις μεθόδους
που απαιτεί η διαχείριση μιας συλλογής
 Γενικότερα μια συλλογή (collection) είναι ένα
αντικείμενο που περιλαμβάνει περισσότερα
αντικείμενα
 Σε μια συλλογή θέλουμε να αποθηκεύουμε, να
ανακτούμε και να διαχειριζόμαστε αντικείμενα.

Συγκεκριμένα
 Να προσθέτουμε ένα αντικείμενο
 Να βγάζουμε ένα αντικείμενο
 Να εντοπίζουμε ένα αντικείμενο
 Αν υπάρχει συλλογή
 Πόσες φορές
 Αν κάποιο ισοδύναμό του υπάρχει στη συλλογή
 Να δίνουμε κάποια τιμή κλειδί και να ανακτούμε
το αντικείμενο
 Να διασχίζουμε όλη τη συλλογή
 Πώς υλοποιούνται όλα αυτά;
Java Collections Framework
 Το πλαίσιο συλλογών της Java περιλαμβάνει
βασικές συλλογές αντικειμένων (object
containers)
 Διεπαφές: αφηρημένοι τύποι που αντιστοιχούν σε
τύπους συλλογών (interfaces και abstract classes)
 Υλοποιήσεις: των προηγούμενων διεπαφών
 Αλγορίθμους: μεθόδους που κάνουν συγκεκριμένες
λειτουργίες όπως αναζήτηση, ταξινόμηση κλπ σε
αντικείμενα της συλλογής

Διεπαφές και υλοποιήσεις


 Βασικές διεπαφές: Collection, Set, List, Map, SortedSet,
SortedMap
 Λειτουργικές διεπαφές: Comparator, Iterator
 Λειτουργικές τάξεις: Collections, Arrays
 Τύποι συλλογών:

Με σειρά Χωρίς σειρά


Επιτρέπει List Multiset (Bag)
διπλότυπα
Δεν επιτρέπει Hashtable Set
Βασικές διεπαφές
 Το Collection είναι η βασικότερη συλλογή,
επιτρέπει διπλότυπα, δεν έχει σειρά
 Σεμια συλλογή μπορούμε να προσθέσουμε
αφαιρέσουμε στοιχεία να τη διασχίσουμε και να
αναζητήσουμε στοιχεία.
 Το Set δεν επιτρέπει διπλότυπα
 Είναιαπόγονος του Collection και μπορεί να
επεκταθεί για να κάνει ταξινόμηση
 Το List επιτρέπει διπλότυπα αλλά διατηρεί σειρά

Συλλογές με ευρετήρια
 Το Map επιτρέπει την εισαγωγή στοιχείων με
ταυτόχρονη εισαγωγή ενός κλειδιού.
 Το ζεύγος key-value συνδέει το σύνολο των κλειδιών
με τη συλλογή των τιμών.
 Αυτό σημαίνει ότι τα κλειδιά δεν επιτρέπουν
διπλοεγγραφές ενώ οι τιμές επιτρέπουν
 Η διάσχιση του map γίνεται με διάσχιση του key-set
και ανάκτηση κάθε value.
Βασικές υλοποιήσεις

Set και List


 Ένα Set
 δεν περιέχει διπλότυπα: π.χ. e1.equals(e2)
 περιέχει το πολύ ένα στοιχείο null
 Έχει ένα Iterator για τη διάσχιση
 π.χ. Τα γράμματα ‘Α’ ως ‘Ζ’, το {} κλπ.

 Μια List
 Τα στοιχεία της είναι σε διάταξη
 Επιτρέπει διπλότυπα
 Και συνεπώς πολλά null αντικείμενα
 Έχει μεθόδους get και set με δείκτη θέσης
ArrayList και LinkedList
 Μια ArrayList
 Περικλείει στην ουσία ένα array
 Υλοποιεί τα πάντα μέσω array γι’ αυτό και μια εισαγωγή στην
αρχή σημαίνει μετακίνηση όλων των περιεχομένων της λίστας
 Προσφέρει iterator για τη διάσχιση και μεθόδους get και set με
δείκτη θέσης
 Μια LinkedList
 Είναι μια διπλά συνδεδεμένη λίστα
 Προσφέρει υλοποιήσεις remove και insert πιο γρήγορες από την
ArrayList
 Έχει πιο αργή διάσχιση (τα στοιχεία δεν είναι σε συνεχόμενες
θέσεις μνήμης) και υλοποίηση της get.

Δέντρα
 Τα Trees προσφέρουν οργάνωση αντικειμένων σε δύο
διαστάσεις
 TreeSet: Δυαδικά δέντρα αναζήτησης - δυαδικά δέντρα με σειρά
στα στοιχεία τους
 TreeMap: υλοποίηση του Map με τα κλειδιά να αποθηκεύονται σε
TreeSet
 Γρήγορη διάσχιση και
αναζήτηση
 Αργά remove/insert γιατί
προξενούν αναδιοργάνωση
του δέντρου. Πάντως πιο
γρήγορα από το ArrayList.
Κατακερματισμος
 Hash: Στον κατακερματισμό ένα κλειδί μετατρέπεται με
χρήση κατάλληλης συνάρτησης (hash function) σε μια
θέση πίνακα (ευρετήριο)
 HashSet: Tα στοιχεία του set μπαίνουν σε θέσεις του πίνακα με
χρήση μιας συνάρτησης: θέση=func(στοιχείο)
 HashMap: υλοποίηση του Map με τα κλειδιά να αποθηκεύονται
σε HashSet

 Αργή διάσχιση (απαιτεί συνεχείς o1 func 51


κλήσεις της func)
 Γρήγορα get/set γιατί καλεί μια φορά
o1
τη func και εντοπίζει τη θέση
 Τι γίνεται αν μια θέση είναι γεμάτη; 50 51 52

Διεπαφή Collection
 Μέθοδοι διαχείρισης:
 size(), isEmpty(), add(Object), remove(Object),
contains(Object), iterator()
 Μέθοδοι μαζικής διαχείρισης
 containsAll(Collection), addAll(Collection),
removeAll(Collection), retainAll(Collecton),
clear():void
 Μέθοδοι μεταφοράς σε πίνακα
 toArray():Object[], toArray(Type[]):Type[]
Διεπαφή Set
 Έχει τις ίδιες μεθόδους με το Collection
 Δεν επιτρέπει διπλότυπα
 Δύο Set είναι ίσα αν περιέχουν τα ίδια στοιχεία
 s1.containsAll(s2): true αν s2 υποσύνολο
του s1
 s1.addAll(s2): s1 γίνεται η ένωση των s1 και
s2
 s1.retainAll(s2): s1 γίνεται η τομή των s1 και
s2

Διεπαφή List
 Συλλογή με σειρά (ordered collection ή και ακολουθία)
και επιτρέπει διπλότυπα
 Επιπλέον μέθοδοι:
 πρόσβασης σε θέση
 get(int), set(int,Object), add(int,Object), remove(int index),
addAll(int, Collection)
 αναζήτησης
 indexOf(Object), lastIndexOf(Object)
 διάσχισης
 listIterator():ListIterator;
 listIterator(int):ListIterator;
 Υποσυνόλου
 subList(int, int):List;
Διεπαφή Map
 Αντιστοιχεί κλειδιά σε τιμές (key-value)
 Δεν εγγυάται σειρά αλλά μπορεί να εμφανιστεί σε
υλοποιήσεις
 Μέθοδοι διαχείρισης
 put(Object, Object),get(Object), remove(Object),
containsKey(Object), containsValue(Object), size(), isEmpty()
 Μέθοδοι μαζικής διαχείρισης
 putAll(Map t), clear()
 Μέθοδοι ανάκτησης
 keySet():Set, values():Collection, entrySet():Set
 Μέθοδοι χειρισμού εγγραφής (interface Map.Entry)
 getKey(), getValue(), setValue(Object);

Διεπαφή Iterator
 Χρησιμοποιείται για τη διάσχιση των συλλογών
 Επιτρέπει
 Τον έλεγχο για την ύπαρξη επόμενου: hasNext():boolean
 Τη μετάβαση στο επόμενο στοιχείο: next():Object
 Τη διαγραφή του τρέχοντος στοιχείου: remove():void
 Χρησιμοποιούνται για να αντικαταστήσουν τα for:
Iterator i = collection.iterator();
while(i.hasNext()) {
Object value = i.next();
....
}
Διεπαφή ListIterator
 Κληρονομεί την Iterator
 Προσφέρει μεθόδους:
 Διάσχισης της λίστας σε κάθε κατεύθυνση
 Τροποποίησης της λίστας κατά τη διάσχιση
 hasPrevious(), previous(), nextIndex(), previousIndex(),
set(Object), add(Object)
 Παράδειγμα:
ListIterator i = list.getListIterator();
while ( i.hasNext() )
{ if ( object.compareTo(i.next()) < 0 )
{ break;} }
i.add(object);

Αφηρημένες τάξεις
 AbstractCollection
 Υλοποιεί τις: containsAll(Collection c), contains(Object
o), removeAll(Collection c), remove(Object o),
retainAll(Collection c) και
 Ορίζει τις add(Object obj), iterator();

 AbstractSet
 Υλοποιεί τις: equals(Object) και hashCode()
 Ορίζει τις: size() και iterator()

 AbstractList
 Υλοποιεί τις: indexOf(Object) και lastIndexOf(Object)
 Ορίζει τις: add() και listIterator()
Διεπαφές – υλοποιήσεις και παρελθόν
Διεπαφή Υλοποιήσεις Παλιότερες
υλοποιήσεις
Set HashSet TreeSet

List ArrayList LinkedList Vector


Stack

Map HashMap TreeMap HashTable


Properties

Μια τάξη υλοποίησης μπορεί να μην υλοποιεί μια συγκεκριμένη μέθοδο


του interface (κάποιες μέθοδοι είναι προεραιτικές)
Στην περίπτωση αυτή παράγει UnsupportedOperationException

Υλοποιήσεις
Υλοποιήσεις

 WeakHashMap
είναι μια
υλοποίηση του
Map που καλεί
τον garbage
collector όταν
ένα κλειδί δε
χρησιμοπείται
πλέον

Δικές μας υλοποιήσεις των


Collections
 Πρέπει να ορίζουν σωστά τις
 equals()
 hashCode()
 Και compareTo() ή compare()
 Στα Map να μη χρησιμοποιούνται πολυμορφικά
αντικείμενα
 Στα Map η hashCode() πρέπει:
 να επιστρέφει πάντα ίδια τιμή για το ίδιο αντικείμενο
 να επιστρέφει ίδια τιμή για ίσα αντικείμενα
 μπορεί να επιστρέφει ίδια τιμή για άνισα αντικείμεναh
Ταξινόμηση και Σύγκριση
 Η διεπαφή Comparable πρέπει
 Να υλοποιείται από όλα τα στοιχεία του SortedSet
 Να υλοποιείται από όλα τα κλειδιά του SortedMap
 Να έχει τη μέθοδο: int compareTo(Object o)
 Να ορίζει τη φυσική σειρά των στοιχείων

 H διεπαφή Comparator
 Συγκρίνει δύο αντικείμενα
 Ορίζει δικό της τρόπο ταξινόμησης
 Έχει τη μέθοδο: int compare(Object o1,Object o2)
 Έχει τη μέθοδο: boolean equals(Object o)

Η τάξη Collections
 Περιέχει ένα σύνολο στατικών μεθόδων για το
χειρισμό συλλογών (κυρίως Lists).
 Ενσωματώνει:
 Μεθόδους που υλοποιούν αλγορίθμους (sort(List),
binarySearch(List, Object), reverse(List), shuffle(List),
fill(List, Object), copy(List dest, List src),
min(Collection), max(Collection))
 Μεθόδους μετατροπής του τύπου μιας συλλογής
(toArray())
 Μεθόδους για δημιουργία συγχρονισμένων συλλογών
και συλλογών μόνο για ανάγνωση
Ταξινόμηση
 Παράδειγμα:
public static void main (String args[]){
List l= Arrays.asList( args );
Collections.sort( l );
}
 Η υλοποίηση της sort μπορεί να γίνει με ένα προσωρινό
array
public static void sort(List list, Comparator c){
Object a[] = list.toArray();
Arrays.sort(a, c); //Αλγόριθμος merge sort
ListIterator i =list.listIterator();
for (int j=0;j<a.length; j++) {i.next(); i.set(a[j]);}
}

Μια άλλη κατηγοριοποίηση


συλλογών
 Τροποποιήσιμες / Μη τροποποιήσιμες: Ανάλογα
με το αν υποστηρίζουν μεθόδους τροποποίησης:
add(), remove(), clear()
 Σταθερές/ασταθείς (mutable): Ανάλογα με το αν
επιτρέπουν αλλαγές κατά τη διάσχιση: iterator(),
size(), contains()
 Σταθερού/μεταβλητού μεγέθους: Ανάλογα με το
αν διατηρούν το μέγεθός τους ανεξάρτητα με την
προσθήκη στοιχείων
Πώς επιλέγουμε τύπο συλλογής
 Πώς θέλουμε να εντοπίζουμε αντικείμενα;
 Με κλειδί  Map
 Με θέση  ArrayList (ή array)

 Ποια σειρά μας ενδιαφέρει στη διάσχιση;


 Τα στοιχεία να είναι ταξινομημένα TreeSet
 Να διατηρείται η σειρά εισαγωγής List

 Τι θέλουμε να γίνεται γρήγορα;


 Προσθήκη και αφαίρεση στοιχείων LinkedList
 Αναζήτηση Set

Tree ή Hash
 Αν o hashCode είναι συνεπής της equals και δεν
ενδιαφέρει η σειρά διάσχισης
 Χρησιμοποιούμε hash υλοποίηση
 Αλλιώς tree
 Αν έχουμε και τις δύο υλοποιήσεις (Hash και
Tree) η Hash είναι συνήθως πιο γρήγορη
 Για Tree υλοποιήσεις ελέγχουμε αν:
 Έχει υλοποιηθεί η διεπαφή Comparable ή αν έχει
οριστεί ο Comparator (στα αντικείμενα του Set, ή στα
κλειδιά του Map)
8. Γραφικές Διεπαφές

Περιεχόμενα
 Γραφικά περιβάλλοντα (GUI)
 Abstract Windowing Toolkit (AWT)
 Containers
 Components
 Layout managers
 (Listeners)
 Swing
 Αρχιτεκτονική Model-View-Controller
 Διάφορα στοιχεία του Swing
 Παράθυρα και μενού
 Περιγράμματα
 Τοποθέτηση στοιχείων στο παράθυρο
 Διαχειριστές τοποθέτησης
 Βασικά interfaces
 Τάξεις
Περιεχόμενα
 Στοιχεία
 Περιοχές κειμένου
 Κουμπιά
 Λίστες επιλογών
 Παράθυρα διαλόγου
 Παράθυρα επιβεβαίωσης
 Παράθυρο επιλογής αρχείου
 Παράθυρο επιλογής χρώματος

Τα μέρη ενός γραφικού περιβάλλοντος


GUI Σύνθεση τάξεων

JFrame JFrame
JPanel containers

JPanel
JButton

JButton JLabel
JLabel

components
Abstract Windowing Toolkit (AWT)
 Εμφανίστηκε στην αρχική έκδοση της Java αλλά
υποστηρίζεται μέχρι σήμερα
 java.awt.*, java.awt.event.*
 Περιλαμβάνει τάξεις για τη σχεδίαση ενός βασικού
γραφικού περιβάλλοντος:
 Παράθυρα (Containers): Frame, Window, Panel, Applet
 Στοιχεία (Components): Button, Checkbox, Label, Scrollbar,
TextField, TextArea
 Διαχειριστές (LayoutManagers): FlowLayout, BorderLayout,
GridLayout
 Διεπαφές για ακρόαση γεγονότων (Listener interfaces):
ActionListener, TextListener κλπ.

Παράδειγμα - Containers
Container (Applet)
Containers (Panels)

Component (Canvas)

Components (Buttons)

Components (TextFields)
Components (Labels)
Παράδειγμα - Components
Checkbox
Label Button

Choice Scrollbar

TextField List TextArea

Button

Checkbox CheckboxGroup

Παράδειγμα - Layout Managers

Flow Layout B orderLayout


Swing
 Επεκτείνει το AWT με περισσότερα στοιχεία
(components)
 Τα στοιχεία είναι 100% υλοποιημένα σε Java
javax.swing.*
 Τα στοιχεία είναι "ελαφρά" δεν επικοινωνούν απευθείας
με το γραφικό περιβάλλον του λειτουργικού, παρά μόνο
μέσω των βασικών παραθύρων
 Η τάξη JFrame (του Swing) κληρονομεί την Frame και
αυτή την Window (του AWT) συνδέοντας έτσι το JFrame
με το λειτουργικό σύστημα
 Προσφέρει τη δυνατότητα για διαφορετική εμφάνιση του
GUI (look and feel)
 Μπορεί να συνδυαστεί με το AWT αλλά θέλει προσοχή

Model-View-Controller
 O controller ανιχνεύει γεγονότα, ενημερώνει το model που αποθηκεύει την
κατάσταση του στοιχείου.
π.χ. Όταν επιλέξουμε ένα checkbox, ο controller ενημερώνει το model
ώστε να ξέρει ότι το checkbox “είναι επιλεγμένο” και αυτό στέλνει ένα
μήνυμα στο view ώστε το checkbox να “φαίνεται επιλεγμένο” πλέον.
3
Νέα εμφάνιση
Αλλαγή 2
κατάστασης 1
Γεγονός

 Μπορούμε έτσι να έχουμε για την ίδια λογική (Model) πάνω από διαφορετικά
look (View) και feel (Controller)
Με ποια σειρά φτιάχνουμε το
GUI Listener
 Δημιουργούμε
 Το JFrame
 Το JPanel JLabel JButton
 Τα Components (JButton, JLabel)
 To Listener για το JButton
 Προσθέτουμε (μέθοδος add) JPanel
 Τον Listener στo JButton
 Τα components στο Jpanel
 To JPanel στο JFrame
 Εμφανίζουμε
 Το JFrame (μέθοδος show) JFrame

JFrame
 Το βασικό container του swing
 Αποτελείται εξ’ ορισμού από ένα container JRootPane
 Το JRootPane αποτελείται από το διάφανο glassPane
και το ορατό layeredPane
 Το layeredPane περιέχει προαιρετικά ένα menuBar και
το contentPane πάνω στο οποίο προστίθενται όλα τα
υπόλοιπα στοιχεία.
 Συνεπώς, αφού φτιάξουμε το JFrame προσθέτουμε στο
contentPane τα διάφορα components
JFrame f=new JFrame(“title”);
f.getContentPane().add(myComponent);
Αντικείμενα - Τάξεις
Frame J Frame
menuBar J MenuBar
(προαιρετική)

J P anel
contentPane

layeredPane J LayeredPane
glassPane J Panel

Παράδειγμα
import javax.swing.*;

JFrame f = new JFrame(“title”);
JButton b = new JButton(“press me”);
f.getContentPane().add(b);
f.show();
press me
 Παρόμοια
JFrame f = new JFrame(“title”);
JPanel p = new JPanel( );
JButton b = new JButton(“press me”);
p.add(b);
f.setContentPane(p);
f.show();
Το JMenuBar
 Η μπάρα μενού δεν είναι υποχρεωτική για
ένα JFrame
 Μπορούμε να την προσθέσουμε
φτιάχνοντας ένα JMenuBar αντικείμενο
JMenuBar menu = new JMenuBar();
 και αναθέτοντάς το στο JFrame
f.setJMenuBar(menu);

Άλλες παράμετροι ενός JFrame


 Εικόνα
ImageIcon image = new ImageIcon("spiral.gif");
f.setIconImage(image.getImage());
 Αρχικό μέγεθος
f.setSize(100,100);
 Θέση εξ ορισμού (0,0) = πάνω αριστερά στην οθόνη
f.setLocation(50, 100);
 Μέγεθος και Θέση
f.setBounds(120,120,300,300);
 Ανάλυση οθόνης
Dimension dim = f.getToolkit().getScreenSize();
int screenwidth=dim.width;
int screenlegthn=dim.length;
Πώς κλείνουμε ένα Frame
 Τι θα γίνεται όταν πατήσουμε το ;
 Ο πιο απλός τρόπο είναι να χρησιμοποιήσουμε τη μέθοδο
setDefaultCloseOperation(int) της JFrame με όρισμα:
 WindowConstants.DISPOSE_ON_CLOSE – κλείνει το frame
 WindowConstants.ΕΧΙΤ_ON_CLOSE – κλείνει την εφαρμογή
 WindowConstants.DO_NOTHING_ON_CLOSE – δεν κάνει τίποτε,
οπότε ανιχνεύουμε διαφορετικά το γεγονός
 WindowConstants.HIDE_ON_CLOSE – κρύβει το frame χωρίς να το
καταστρέφει
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
H WindowConstants είναι ένα interface που υλοποιεί η JFrame

JPanel
 To JPanel είναι το βασικότερο container μέσα σε ένα
JFrame.
 Ένα JPanel μπορεί να περιέχει components ή άλλα
JPanel επιτρέποντας έτσι την καλύτερη οργάνωση των
στοιχείων στο παράθυρο.
 Κάθε JPanel έχει ένα διαχειριστή τοποθέτησης στοιχείων
(LayoutManager). Ο βασικός διαχειριστής προσθέτει τα
στοιχεία στη σειρά το ένα δίπλα στο άλλο.
 Στα JPanel αλλά και στα υπόλοιπα components
μπορούμε να ορίσουμε ένα τύπο περιγράμματος
(Border)
Περιγράμματα - Borders
 Οι αντίστοιχες τάξεις βρίσκονται στο πακέτο javax.swing.border
 BevelBorder (υπερυψωμένο ή βυθισμένο), CompoundBorder
(διπλό) EmptyBorder (διάφανο), TitledBorder κ.ά.
Panel p=new Panel();
BevelBorder bb = new BevelBorder (BevelBorder.RAISED);
p.setBorder(bb);

Τοποθέτηση components στο JPanel

 Οι Layout Managers είναι τάξεις που


διαχειρίζονται τον τρόπο τοποθέτησης των
στοιχείων ενός παραθύρου
 Υλοποιούν δύο βασικά interfaces τα
LayoutManager και LayoutManager2
 Κάποιοι περιέχονται στο java.awt ενώ κάποιοι
άλλοι στο javax.swing
 Πρώτα ορίζουμε το layout σε ένα container και
μετά προσθέτουμε στοιχεία.
Ορισμός Layouts
 Κάθε παράθυρο (container) έχει ένα
προκαθορισμένο τρόπο τοποθέτησης στοιχείων
(components)
 Τα JPanel έχουν προκαθορισμένα FlowLayout
 Για κάθε παράθυρο ορίζουμε ένα layout με τη
μέθοδο setLayout
myPanel.setLayout(new BorderLayout());
ή
this.getContentPane().setLayout(new
GridLayout(2,2));

Ενδεικτικά layouts
FlowLayout GridLayout BorderLayout
n

Αριστερά προς δεξιά w c e


Πάνω προς κάτω

CardLayout GridBagLayout

Το ένα πάνω στο άλλο JButton


Βασικές τάξεις τοποθέτησης
 FlowLayout(), τοποθετεί τα στοιχεία στη
σειρά
myPanel.setLayout(new
FlowLayout(FlowLayout.CENTER));
myPanel.add(new JButton(“1”));
 GridLayout(int rows, int columns)
myPanel.setLayout(new GridLayout(2,2));
myPanel.add(new JButton(“1”));
 BorderLayout()
myPanel.setLayout(new BorderLayout());
add(new JButton(“1"), BorderLayout.NORTH);

Βασικές τάξεις τοποθέτησης


 CardLayout(), τοποθετεί το ένα στοιχείο πίσω από το
άλλο. Ορατό είναι αυτό που προσθέτουμε πρώτο.
myPanel.setLayout(new CardLayout());
myPanel.add(new JButton(“1”),”first”);
myPanel.add(new JButton(“2”),”second”);
Με τις μεθόδους first, last, next, previous, show
φέρνουμε στην επιφάνεια μια κάρτα
 GridBagLayout(), τοποθετεί τα στοιχεία σε θέσεις ενός
πλέγματος, ώστε να γεμίζουν τη θέση ή να
καταλαμβάνουν πάνω από ένα κελιά στο πλέγμα
GridBagLayout gbl=new GridBagLayout();
myPanel.setLayout(gbl);
GridBagConstraints c = new GridBagConstraints();
c.fill=GridBagConstraints.BOTH;
c.weightx=1.0; c.weighty=1.0;
c.gridx=0; x.gridy=0;
c.gridheight=2;
myPanel.add(new JButton(“one”,c);
Τάξεις στο πακέτο swing
 BoxLayout, τοποθετεί τα στοιχεία σε μια σειρά (ή
στήλη) χωρίς αναδίπλωση. Χρησιμοποιείται κυρίως για
μπάρες εργαλείων.
 Συνδυάζεται με την τάξη Box που είναι Container
Container toolbar = Box.createHorizontalBox( );
toolbar.add(new JButton(“1”));
myPanel.add(toolbar);
 SpringLayout, καθορίζει την απόσταση κάθε
στοιχείου από τα γειτονικά στοιχεία
 OverlayLayout, ScrollPaneLayout

Ειδικά πλαίσια (Panels)


 JScrollPane: Περιέχει ένα στοιχείο μόνο
 Εμφανίζει αυτόματα μπάρες κύλισης αν το στοιχείο δεν
χωρά στο πλαίσιο
JScrollPane sp=new JScrollPane(new JButton(“A button with a long
label on it”));
myPanel.add(sp);
 JSplitPane: Περιέχει δύο στοιχεία με ένα διαχωριστικό
που μετακινείται.
JSplitPane split =new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT, button1, button2);
myPanel.add(split);
Ειδικά πλαίσια (Panels)
 JTabbedPane: Τοποθετεί κάθε στοιχείο πίσω
από τα υπόλοιπα με τη μορφή καρτελών
 Κάθε καρτέλα έχει ένα όνομα και ένα στοιχείο ή
πλαίσιο
JPanel config=new JPanel();
JPanel options=new JPanel();

JTabbedPane tabby = new JTabbedPane( );
tabby.addTab(“Configuration”, config);
tabby.addTab(“Options”, options);
myPanel.add(tabby);

Εσωτερικά παράθυρα
 Η τάξη JDesktopPane μας επιτρέπει να εμφανίσουμε ολόκληρα
παράθυρα (JInternalFrame) μέσα σε ένα JFrame
 Τα εσωτερικά παράθυρα μπορεί να είναι resizable, closable,
maximizable, iconifiable, όπως ακριβώς συμβαίνει με τα παράθυρα
των Windows
JDesktopPane desktop = new JDesktopPane( );
JInternalFrame internal =
new JInternalFrame("Frame 1", true, true, true, true);
internal.setSize(180, 180);
internal.setLocation(20,20);
internal.setVisible(true);
desktop.add(internal);
f.setContentPane(desktop);
Συνδυασμοί panels και layouts
JButton JButton
f: JFrame
NORTH
p1: JPanelFlowLayout
contentPane: JPanel
BorderLayout

CENTER t: JTextArea

Συνδυασμός
JFrame f = new JFrame(“Frame1”);

JPanel p1 = new JPanel( );


JButton b1 = new JButton(“OK”);
JButton b2 = new JButton(“Cancel”);
p1.add(b1);
p1.add(b2);
JTextArea t=new JTextArea("");
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(p1,BorderLayout.NORTH);
f.getContentPane().add(t,BorderLayout.CENTER);
Στοιχεία του Swing

BUTTONS
MENUS

Άλλα COMPONENTS

JApplet Border Interface

JComboBox JColorChooser

ImageIcon

JInternalFrame
JDialog
JFileChooser
Άλλα COMPONENTS

JScrollBar
JLabel JList

JScrollPane JOptionPane JSlider

JSplitPane
JTabbedPane

Άλλα COMPONENTS

JTable
JTextArea

JTextField

JToolBar

JToolTip

JTree
JComponent
 Κάθε JComponent είναι αντικείμενο μιας τάξης.
Συνεπώς:
 Έχει κατάσταση (ιδιότητες)
(π.χ. ενεργό, ορατό, επιλεγμένο, JButton
θέση,κείμενο, εικόνα κλπ.)
 Έχει μεθόδους
(π.χ. Όρισε κείμενο/εικόνα, φόντο)
 Ανταποκρίνεται σε γεγονότα
(π.χ. mouseClicked, mouseEntered, keyTyped, componentMoved)

Πώς χρησιμοποιούμε ένα


Component
1. Το δημιουργούμε
 JButton b = new JButton(“press me”);
2. Το ρυθμίζουμε
 Ιδιότητες: b.text = “press me”;
 Μέθοδοι: b.setText(“press me”);.
3. Του προσθέτουμε components (αν είναι container)
4. Τα προσθέτουμε σε ένα container (εκτός αν είναι
JFrame)
 panel.add(b);
5. Παρακολουθούμε τα γεγονότα σ’ αυτό
 Events: Listeners
Ετικέτες
JLabel label1 = new JLabel(“JLabel");
JLabel label2 = new JLabel("JLabel",SwingConstants.CENTER);
label2.setOpaque(true); label2.setBackground(Color.white);

JLabel label3 = new JLabel("JLabel",SwingConstants.CENTER);


label3.setFont(new Font("Helvetica", Font.BOLD, 18));
label3.setOpaque(true); label3.setBackground(Color.white);

ImageIcon icon = new ImageIcon("image.gif");


JLabel label4 = new JLabel("JLabel",image, SwingConstants.RIGHT);
label4.setVerticalTextPosition(SwingConstants.TOP);
label4.setOpaque(true); label4.setBackground(Color.white);

myPanel.add(label); myPanel.add(label2);
myPanel.add(label3); myPanel.add(label4);

Περιοχές κειμένου
JTextField tf1 = new JTextField();
JTextField tf2 = new JTextField(“text”);
JTextField tf3 = new JTextField(“more text”,40);
tf2.getText();
tf1.setText(“empty”);
JTextArea ta= new TextArea();
ta.append(“text”); ta.append(“\nline2”);
JPasswordField pf=new JPasswordField(“hidden”);
Περιοχές κειμένου
public class TestFrame extends JFrame {
JTextField tf; JTextArea ta;
JPasswordField pf; JScrollPane jsp;
public TestFrame() {
tf = new JTextField(); ta = new JTextArea();
ta.setText("Your Text will appear");
ta.append("\nhere:\n");
pf = new JPasswordField("hidden");
jsp = new JScrollPane();
jsp.getViewport().add(ta);
this.setLayout(new GridLayout(3, 3));
this.getContentPane().add(tf);
this.getContentPane().add(jsp);
this.getContentPane().add(pf);
String password=pf.getText();
ta.append(password);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}

Κουμπιά
….
ta.append(password);
clearButton=new JButton("Clear");
copyButton = new JButton("Copy");
this.getContentPane().add(new JPanel());
this.getContentPane().add(clearButton);
this.getContentPane().add(copyButton);

this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
Κουμπιά – Ομάδες κουμπιών
JButton b= new JButton(“OK”);
JToggleButton tb1= new JToggleButton(“ON”);
JToggleButton tb2= new JToggleButton(“OFF”);
ButtonGroup buttonGroup = new ButtonGroup();
tb1.setMnemonic(‘n’); // Ενεργοποιείται με ALT+n
tb1.setToolTipText(“This is the ON button”);
tb2.setMnemonic(‘f’); // Ενεργοποιείται με ALT+f
tb1.setToolTipText(“This is the OFF button”);
buttonGroup.add(tb1);
buttonGroup.add(tb2);
myPanel.add(tb1);
Ενεργοποιούνται εναλλάξ
myPanel.add(tb2);
myPanel.add(b);

JCheckBox και JRadioButton


 Τα JCheckBox λειτουργούν ανεξάρτητα και μπορούν να
επιλεγούν όλα μαζί
myPanel.add(new JCheckBox("case 1"));
myPanel.add(new JCheckBox("case 2"));
Τα JRadioButton λειτουργούν σε ομάδες και μόνο ένα επιλέγεται
κάθε φορά.
ButtonGroup options = new ButtonGroup( );
JRadioButton rb1= new JRadioButton("Option 1");
JRadioButton rb2= new JRadioButton("Option 2");
options.add(rb1); options.add(rb2);
myPanel.add(rb1); myPanel.add(rb2);
Λίστες επιλογών
 JComboBox: Περιέχει ένα πίνακα από επιλογές, εμφανίζει στο
χρήστη μόνο μία και επιτρέπει μονές ή πολλαπλές επιλογές.
String [] items = { "uno", "due", "tre", "quattro", "cinque", "sei", "sette",
"otto", "nove", "deici", "undici" };
JComboBox comboBox = new JComboBox(items);
comboBox.addItem("dodici");
comboBox.getSelectedItem() //επιστρέφει Object
comboBox.getSelectedObjects() //επιστρέφει Object[]
 JList: Περιέχει ένα πίνακα από επιλογές, εμφανίζει στο χρήστη
ορισμένες από αυτές (ανάλογα με το ύψος της) και επιτρέπει μονές
ή πολλαπλές επιλογές.
JList list = new JList(comboBox.getModel( ));
list.getSelectedValues() //επιστρέφει Object[]
 Mοιράζονται το ίδιο μοντέλο δεδομένων

Παράδειγμα
public class Human {
String name;
String surname;
int age;
String address;
public Human(String name, String surname, int age, String address) {
this.name = name;
this.surname = surname;
this.age = age;
this.address = address;
}
@Override
public String toString() {
return this.name+" "+this.surname;
}
}
Μοντέλα Δεδομένων για Λίστες
dlm = new DefaultListModel();
dlm.addElement(new Human("George", "Brown", 22, "6th Avenue"));
dlm.addElement(new Human("Mary", "Jones", 18, "5th Avenue"));
dlm.addElement(new Human("Bill", "Murray", 19, "Madison Avenue"));
students = new JList(dlm);
this.getContentPane().add(students);
this.getContentPane().add(clearButton);
this.getContentPane().add(copyButton);

- Φαίνεται ότι επιστρέφει η toString()


- Επιστρέφει όλο το Object
Object[] selected=students.getSelectedValues();
for (int i=0;i<selected.length;i++)
Human h=(Human)selected[i];

Πίνακες - JTable
String[] columnNames = {"First Name", "Last Name", "Age", "Address"};
Object[][] data = {{"George", "Brown", new Integer(22), "6th Avenue"},
{"Mary", "Jones", new Integer(18), "5th Avenue"},
{"Bill", "Murray", new Integer(19), "Madison Avenue"}};
dtm = new DefaultTableModel(data,columnNames);
studentsTable=new JTable(dtm);
JScrollPane jsp2 = new JScrollPane();
jsp2.getViewport().add(studentsTable);
this.getContentPane().add(jsp2);

JTable(Object[][] rowData, Object[] columnNames);


JTable(Vector rowData, Vector columnNames);
JTable(DefaultTableModel dtm);
Μενού επιλογών
JMenu file = new JMenu(“File");
file.add(new JMenuItem(“Open"));
file.add(new JMenuItem(“Close"));
JMenu edit = new JMenu(“Edit");
edit.add(new JMenuItem(“Copy"));
edit.add(new JMenuItem(“Paste"));
JMenu check = new JMenu(“Check");
check.add(new JCheckBoxMenuItem(“Option 1"));
check.add(new JSeparator());
check.add(new JCheckBoxMenuItem(“Option 2", true));
MenuBar mb = new MenuBar();
mb.add(file);
mb.add(edit);
mb.add(check);
myFrame.setJMenuBar(mb);

Μελέτη Περίπτωσης
Μελέτη Περίπτωσης

Παράθυρα διαλόγου

52
Παράθυρα διαλόγου
 Τα παράθυρα διαλόγου χρησιμοποιούνται για να
συλλέξουμε πληροφορίες από το χρήστη
 Τραβούν το ενδιαφέρον του χρήστη καθώς
εμφανίζονται πάνω από την εφαρμογή (π.χ. εισαγωγή
κωδικού)
 Απαιτούν εισαγωγή δεδομένων από το χρήστη και
αποδοχή της επιλογής
 Επιτρέπουν στο χρήστη να κάνει σύνθετες επιλογές
και επιστρέφουν στην εφαρμογή το αποτέλεσμα της
επιλογής (π.χ. επιλογή μιας ομάδας αρχείων και τις
δράσης σε αυτά, επιλογή ενός χρώματος για το φόντο
ενός πλαισίου κλπ)

Το παράθυρο JDialog
 Συμπεριφέρεται όπως και το JFrame
JDialog dialog = new JDialog(myFrame, "Dialog Frame");
JLabel label = new JLabel("This is a message“);
dialog.getContentPane().add(label);
dialog.setVisible(true);

 Μπορεί να μπλοκάρει τη συνέχιση του


προγράμματος (modal) ή όχι (non-modal)
JDialog dialog1 = new JDialog(myFrame, "This is modal", true);
JDialog dialog2 = new JDialog(myFrame, "This is non modal", false);
Έτοιμα πλαίσια διαλόγου
 Φτιάχνονται με κλήση των static μεθόδων της JOptionPane
 int n = JOptionPane.showConfirmDialog(myFrame, “Is it OK?",
“ConfirmDialog", JOptionPane.YES_NO_OPTION);
 String s = (String)JOptionPane.showInputDialog(myFrame, "Name?");
 JOptionPane.showMessageDialog(myFrame, "Hi!");

 Object[] options = {"Yes, please", "No way!"};


int n = JOptionPane.showOptionDialog(myFrame, "Choose", "Choices",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
null, options,options[0]);

Παράθυρο επιλογής αρχείου


 Δημιουργία ενός JFileChooser:
JFileChooser fc = new JFileChooser();
 Εμφάνισή του (π.χ. με το πάτημα ενός JButton)
int returnVal = fc.showOpenDialog(aComponent);
Παράθυρο επιλογής αρχείου
 Στη συνέχεια μπορούμε να διαβάσουμε τις ενέργειες
του χρήστη στο παράθυρο:
if (returnVal == JFileChooser.APPROVE_OPTION) {
// αν ο χρήστης επέλεξε Open
File file = fc.getSelectedFile(); //το αρχείο που επέλεξε
log.append("Opening: " + file.getName() + "." + newline);
}
else {
log.append("Open command cancelled by user." + newline);
}
 fc.showDialog(aComponent, "Save");
//αλλάζει το open button σε Save

Παράθυρο επιλογής χρώματος


 Δημιουργία και χρήση ενός JColorChooser
Color c = JColorChooser.showDialog(myFrame, "Choose a
color", myFrame.getContentPane().getBackground( ));
if (c != null) myFrame.getContentPane().setBackground(c);
Διαχείριση γεγονότων

Περιεχόμενα
 Διαχείριση γεγονότων
 Δημιουργία γεγονότος
 Ακρόαση (ανίχνευση) γεγονότος
 Δημιουργία ακροατή – Κατηγορίες ακροατών
 Σύνδεση ακροατή με στοιχείο
 Πρακτικές χρήσης ακροατών
Διαχείριση γεγονότων
 Το στοιχείο του GUI (π.χ. ένα JButton)
 Παράγει γεγονότα σε συγκεκριμένες συνθήκες
 Ανάλογα με τις δραστηριότητες του χρήστη
 Το γεγονός (π.χ. ένα MouseEvent)
 Ένα αντικείμενο που περιέχει πληροφορίες για το γεγονός
 Ποιος το προκάλεσε, τι ακριβώς προκάλεσε, σε ποιο στοιχείο
του GUI, κλπ
 Οι ακροατές (π.χ. ένας MouseListener)
 Καταλαβαίνουν ένα γεγονός
 Έχουν μεθόδους που παίρνουν γεγονότα ως όρισμα
 Διάφορες κατηγορίες ακροατών (για γεγονότα σχετικά με τα
mouse, keyboard, window, components κλπ)

Δημιουργία γεγονότων
 Τα αντικείμενα επικοινωνούν μεταξύ τους
δημιουργώντας γεγονότα
 Τα γεγονότα είναι αντικείμενα της τάξης
java.util.EventObject και των απογόνων της (π.χ.
AWTEvent)
 Μεταφέρουν πληροφορία για το είδος του γεγονότος,
τη δράση που το προκάλεσε κλπ. Για παράδειγμα
 ένα MouseEvent παράγεται από ένα στοιχείο, όταν ο χρήστης
κινήσει το ποντίκι στην περιοχή του στοιχείου (π.χ. ενός
JButton). Το αντικείμενο MouseEvent περιλαμβάνει
πληροφορία για τις συντεταγμένες του ποντικιού (x,y), για την
κατάσταση των κουμπιών του κλπ.
 Ένα ActionEvent μπορεί να παράγεται από το ίδιο στοιχείο
(π.χ. JButton) ενημερώνοντας ότι κάτι συνέβη με το στοιχείο
 Δεν παράγουν όλα τα στοιχεία τα ίδια γεγονότα
Ακρόαση γεγονότων
 Το πάτημα ενός JButton δημιουργεί ένα γεγονός (αντικείμενο
ActionEvent).
 Για να το χειριστούμε, θα πρέπει στο JButton να προσθέσουμε
ένα τρόπο διαχείρισης γεγονότων.
 Οι μέθοδοι που διαχειρίζονται κάθε γεγονός περιέχονται στο
αντίστοιχο interface. Τα interfaces αυτά ονομάζονται ακροατές –
listeners.
public interface ActionListener extends java.util.EventListener {
public void actionPerformed( ActionEvent e );
}
 Ένα στοιχείο μπορεί να έχει πολλούς ακροατές. Κάθε ακροατής
μπορεί να παρακολουθεί πολλά στοιχεία.
 Συνοψίζοντας: α) Φτιάχνουμε την τάξη που υλοποιεί το
κατάλληλο interface ακροατή, β) προσθέτουμε στο στοιχείο ένα
αντικείμενο της τάξης αυτής.

Α) Δημιουργία ακροατή
 Τα listener interfaces έχουν ένα κοινό πρόγονο το interface
java.util.EventListener που δεν δηλώνει καμία μέθοδο.
 Ένα γεγονός έχει μοναδική πηγή αλλά μπορεί να ανιχνευτεί από
πολλούς ακροατές (π.χ. ο ακροατής του στοιχείου, ο ακροατής
του component που περιέχει το στοιχείο κλπ)
 Κάθε τάξη ακροατής γεγονότων θα πρέπει να υλοποιεί ένα ή
περισσότερα listener interfaces.
public class myActionListener implements ActionListener{
public void actionPerformed( ActionEvent e ){
myTextArea.append(“Something happened”);
}
}
 Εκτός από τα Listener interfaces υπάρχουν και οι αντίστοιχες
Adapter τάξεις (είναι abstract)
public class myMouseListener implements MouseListener
public class myMouseListener extends MouseAdapter
Τύποι ακροατών
Ακροατής Μέθοδοι
ActionListener actionPerformed(ActionEvent)
MouseListener mouseClicked(MouseEvent)
MouseAdapter mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mousePressed(MouseEvent)
mouseReleased(MouseEvent)
MouseMotionListener mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
KeyListener keyPressed(KeyEvent)
keyReleased(KeyEvent)
keyTyped(KeyEvent)
ItemListener itemStateChanged(ItemEvent)

Τύποι ακροατών
ComponentListener componentHidden(ComponentEvent)
ComponentAdapter componentShown(ComponentEvent)
componentMoved(ComponentEvent)
componentResized(ComponentEvent)
ContainerListener componentAdded(ContainerEvent)
ContainerAdapter componentRemoved(ContainerEvent)
FocusListener focusGained(FocusEvent)
FocusAdapter focusLost(FocusEvent)
WindowListener windowActivated(WindowEvent) , windowClosed
WindowAdapter windowClosing, windowDeactivated,
windowDeiconified, windowGainedFocus
windowIconified, windowLostFocus
windowOpened, windowStateChanged
Παράδειγμα - actionListener
υποχρεωτικά
public class CopyButtonActionListener implements ActionListener {
TestFrame targetFrame;
public CopyButtonActionListener(TestFrame targetFrame) {
this.targetFrame=targetFrame;
}
public void actionPerformed(ActionEvent e) {
String password = targetFrame.pf.getText();
targetFrame.ta.append(password);
}
}

Και στην TestFrame …


copyButton.addActionListener(new CopyButtonActionListener(this));

Παράδειγμα - mouseListener
υποχρεωτικά
public class myMouseListener implements MouseListener {
public void mousePressed(MouseEvent e) {
textArea.append ("Mouse pressed: # of clicks: “
+ e.getClickCount(), " detected at position “ + e.getX()+ “,”
+ e.getY() + “ of component”
+ e.getComponent().getClass().getName() + ".\n");
}
public void mouseReleased(MouseEvent e) {…}
public void mouseClicked(MouseEvent e) { …}
public void mouseEntered(MouseEvent e) {
textArea.append ("Mouse entered detected on "
+ e.getComponent().getClass().getName() + ".\n");
}
public void mouseExited(MouseEvent e) { …}
}
Β) Ανίχνευση γεγονότων
 Για να μπορεί ένα στοιχείο να ανιχνεύει γεγονότα θα
πρέπει να του προσθέσουμε τον αντίστοιχο ακροατή
button1.addActionListener(new myActionListener());
//έτσι θα ανιχνεύουμε πάτημα του κουμπιού
button1.addMouseListener(new myMouseListener());
//έτσι θα ανιχνεύουμε κινήσεις του ποντικιού πάνω στο κουμπί
 Τα FocusEvent, KeyEvent, MouseEvent,
ComponentEvent είναι γεγονότα που προκαλούνται
από όλα τα components του swing
 Το ContainerEvent προκαλείται από όλα τα containers
του Swing

Γεγονότα - Στοιχεία που τα παράγουν


ActionEvent J Button, J CheckBoxMenuItem,
J ComboBox,
J FileChooser, J List,
RadioButtonMenuItem,
J TextField, J ToggleButton
ListSelectionEve J List, ListSelectionModel
nt
ItemEvent J CheckBoxMenuItem, ItemListener,
J ComboBox, J RadioButtonMenuItem,
J ToggleButton
MenuEvent J Menu
MenuKeyEvent J MenuItem
WindowEvent J Dialog, J Frame, J Window
Πρακτικές δήλωσης και χρήσης
ακροατών

Υλοποίηση με interface
 Υλοποίηση με interface
 Η τάξη μας είναι απόγονος της JFrame (περιέχει
components κλπ)
 Μπορεί να υλοποιεί όλα τα interfaces που χρειάζεται για να
ανιχνεύει γεγονότα
 Θα πρέπει να δηλώνει όλες τις μεθόδους, όλων των
interfaces, ακόμη και αν υλοποιεί ορισμένες μόνο από αυτές.
 Με τον τρόπο αυτό έχουμε ένα μόνο ακροατή για όλα τα
στοιχεία που βάζουμε στο πλαίσιο.
 Υλοποίηση με inner class και adapter
 Η τάξη κληρονομεί μόνο έναν adapter και ορίζει μόνο τις
μεθόδους που σχετίζονται με τα γεγονότα που ανιχνεύει
 Θα πρέπει να δηλωθεί ως εσωτερική τάξη ώστε να έχει
πρόσβαση στα μέλη της κύριας τάξης που είναι απόγονος
της JFrame
 Έχουμε έτσι ένα ακροατή για κάθε στοιχείο στο πλαίσιο.
Παράδειγμα χρήσης interface
import javax.swing.*;
import java.awt.event.*;
public class MyClass extends JFrame implements MouseListener {
JButton button1;
void init(){
button1=new JButton("OK");
this.add(button1); //είναι ταυτόχρονα πλαίσιο
button1.addMouseListener(this); //και ακροατής
this.setSize(200,200);
}
public void mouseClicked(MouseEvent e) { }
//παρόμοια οι mousePressed και mouseReleased
public void mouseExited(MouseEvent e) { button1.setText("OFF");}
public void mouseEntered(MouseEvent e) { button1.setText("ON");}
public static void main(String args[]){
MyClass m=new MyClass();
m.init();
m.show();
}}

Χρήση ανώνυμης εσωτερικής


τάξης
 Αν η λειτουργικότητα αφορά ένα μόνο component είναι
προτιμότερο να χρησιμοποιήσουμε ανώνυμη εσωτερική τάξη
public class MyClass extends JFrame {
JButton button1;
void init(){
button1=new JButton("OK");
this.add(button1);
button1.addMouseListener(new MouseAdapter(){
public void mouseExited(MouseEvent e) { button1.setText("OFF");}
public void mouseEntered(MouseEvent e) { button1.setText("ON");}
});
this.setSize(200,200);
}
public static void main(String args[]){ …}
}
Περισσότερα για τους ακροατές
 ActionListener
 Ορίζειτη μέθοδο
void actionPerformed(ActionEvent)
 Το ActionEvent έχει δύο χρήσιμες μεθόδους
 String getActionCommand()
Δίνει ένα μήνυμα που περιγράφει το γεγονός
 int getModifiers()
Μας ενημερώνει αν όταν συνέβη το γεγονός (π.χ.
Mouse click) είχε πατηθεί κάποιο από τα πλήκτρα
SHIFT, CTRL ή ALT

Περισσότερα για τους ακροατές


 ComponentListener
 voidcomponentHidden(ComponentEvent)
 void componentShown(ComponentEvent)
 void componentMoved(ComponentEvent)
 void componentResized(ComponentEvent)
Ανάλογα με το αν το στοιχείο κρύφτηκε, εμφανίστηκε,
μετακινήθηκε ως προς το πλαίσιο στο οποίο ανήκει,
κλπ
 Το ComponentEvent έχει τη μέθοδο
 Component getComponent()
Επιστρέφει το στοιχείο που προκάλεσε το γεγονός
Περισσότερα για τους ακροατές
 ItemListener: Συνδέεται με μενού, checkboxes
 void itemStateChanged(ItemEvent)
 To ItemEvent έχει τις εξής μεθόδους
 Object getItem()
Συνήθως ένα String με το κείμενο του στοιχείου
 ItemSelectable getItemSelectable()
Επιστρέφει το στοιχείο που προκάλεσε το γεγονός
 int getStateChange()
Αν το αντικείμενο επιλέχθηκε ή όχι

Περισσότερα για τους ακροατές


 KeyListener: Ανιχνεύει πατήματα πλήκτρων
 void keyTyped(KeyEvent) // για Unicode characters
 void keyPressed(KeyEvent) // για πλήκτρα
 void keyReleased(KeyEvent)
 To KeyEvent έχει τις εξής μεθόδους
 int getKeyChar() , void setKeyChar(int)
Συνδέει το event με κάποιο Unicode character
 int getKeyCode() , void setKeyCode(int)
Επιστρέφει τον κωδικό του πλήκτρου που προκάλεσε το
γεγονός
Περισσότερα για τους ακροατές
 WindowListener
 void windowOpened(WindowEvent)
 void windowClosing(WindowEvent)
 void windowClosed(WindowEvent)
 void windowIconified(WindowEvent),
void windowDeiconified(WindowEvent)
 void windowActivated(WindowEvent)
void windowDeactivated(WindowEvent)
 To WindowEvent έχει τη μέθοδο
 Window getWindow()
Που επιστρέφει το παράθυρο που προκάλεσε το γεγονός
 Περισσότερα:
http://java.sun.com/docs/books/tutorial/uiswing/

Παράδειγμα
 Στο κατάστημα με τους υπολογιστές θέλουμε να
δημιουργήσουμε μια φόρμα που θα κάνει τα
ακόλουθα
 Θα διαβάζει από αρχείο όλους τους υπολογιστές και
θα τους εμφανίζει σε μια λίστα, τυπώνοντας μόνο το
μοντέλο του υπολογιστή
 Θα επιτρέπει να επιλέξουμε ένα μόνο υπολογιστή και
 Αν πατήσουμε το κουμπί Details θα μας δείχνει σε
ξεχωριστό παράθυρο τις λεπτομέρειες του
υπολογιστή.
Πόσες φόρμες χρειαζόμαστε
MainFrame OrderFrame ProductFrame

createOrder addProduct

setVisible(true) setVisible(true)

Τι ξέρει ArrayList<Order> orderList


η κάθε
φόρμα; ArrayList<Product> productList

Τι
δημιουργεί Order o = new Order() Product p = new Product()
κάθε
φόρμα;

Μια φόρμα δεν μπορεί να επιστρέψει δεδομένα


Γι' αυτό πρέπει να της περάσουμε μια αναφορά στην αντίστοιχη δομή
Λύση
 Στον κατασκευαστή της OrderFrame και της
ProductFrame περνάμε την orderList και την
ProductList αντίστοιχα
 Στο κουμπί "Καταχώρηση…", δημιουργούμε το
αντίστοιχο αντικείμενο και το προσθέτουμε στη
λίστα που έχουμε περάσει στη φόρμα.
 Έτσι ενημερώνουμε έμμεσα (μέσω αναφοράς)
την αρχική λίστα και μπορούμε πλέον άφοβα να
κλείσουμε τη φόρμα
 Η φόρμα κλείνει με τη μέθοδο dispose()

8-9. Γραφικές Διεπαφές


Περιεχόμενα
 Γραφικά περιβάλλοντα (GUI)
 Abstract Windowing Toolkit (AWT)
 Containers
 Components
 Layout managers
 (Listeners)
 Swing
 Αρχιτεκτονική Model-View-Controller
 Διάφορα στοιχεία του Swing
 Παράθυρα και μενού
 Περιγράμματα
 Τοποθέτηση στοιχείων στο παράθυρο
 Διαχειριστές τοποθέτησης
 Βασικά interfaces
 Τάξεις

Περιεχόμενα
 Στοιχεία
 Περιοχές κειμένου
 Κουμπιά
 Λίστες επιλογών
 Παράθυρα διαλόγου
 Παράθυρα επιβεβαίωσης
 Παράθυρο επιλογής αρχείου
 Παράθυρο επιλογής χρώματος
Τα μέρη ενός γραφικού περιβάλλοντος
GUI Σύνθεση τάξεων

JFrame JFrame
JPanel containers

JPanel
JButton

JButton JLabel
JLabel

components

Abstract Windowing Toolkit (AWT)


 Εμφανίστηκε στην αρχική έκδοση της Java αλλά
υποστηρίζεται μέχρι σήμερα
 java.awt.*, java.awt.event.*
 Περιλαμβάνει τάξεις για τη σχεδίαση ενός βασικού
γραφικού περιβάλλοντος:
 Παράθυρα (Containers): Frame, Window, Panel, Applet
 Στοιχεία (Components): Button, Checkbox, Label, Scrollbar,
TextField, TextArea
 Διαχειριστές (LayoutManagers): FlowLayout, BorderLayout,
GridLayout
 Διεπαφές για ακρόαση γεγονότων (Listener interfaces):
ActionListener, TextListener κλπ.
Παράδειγμα - Containers
Container (Applet)
Containers (Panels)

Component (Canvas)

Components (Buttons)

Components (TextFields)
Components (Labels)

Παράδειγμα - Components
Checkbox
Label Button

Choice Scrollbar

TextField List TextArea

Button

Checkbox
CheckboxGroup
Παράδειγμα - Layout Managers

Flow Layout BorderLayout

Swing
 Επεκτείνει το AWT με περισσότερα στοιχεία
(components)
 Τα στοιχεία είναι 100% υλοποιημένα σε Java
javax.swing.*
 Τα στοιχεία είναι "ελαφρά" δεν επικοινωνούν απευθείας
με το γραφικό περιβάλλον του λειτουργικού, παρά μόνο
μέσω των βασικών παραθύρων
 Η τάξη JFrame (του Swing) κληρονομεί την Frame και
αυτή την Window (του AWT) συνδέοντας έτσι το JFrame
με το λειτουργικό σύστημα
 Προσφέρει τη δυνατότητα για διαφορετική εμφάνιση του
GUI (look and feel)
 Μπορεί να συνδυαστεί με το AWT αλλά θέλει προσοχή
Model-View-Controller
 O controller ανιχνεύει γεγονότα, ενημερώνει το model που αποθηκεύει την
κατάσταση του στοιχείου.
π.χ. Όταν επιλέξουμε ένα checkbox, ο controller ενημερώνει το model
ώστε να ξέρει ότι το checkbox “είναι επιλεγμένο” και αυτό στέλνει ένα
μήνυμα στο view ώστε το checkbox να “φαίνεται επιλεγμένο” πλέον.
3
Νέα εμφάνιση
Αλλαγή 2
κατάστασης 1
Γεγονός

 Μπορούμε έτσι να έχουμε για την ίδια λογική (Model) πάνω από διαφορετικά
look (View) και feel (Controller)

Με ποια σειρά φτιάχνουμε το


GUI Listener
 Δημιουργούμε
 Το JFrame
 Το JPanel JLabel JButton
 Τα Components (JButton, JLabel)
 To Listener για το JButton
 Προσθέτουμε (μέθοδος add) JPanel
 Τον Listener στo JButton
 Τα components στο Jpanel
 To JPanel στο JFrame
 Εμφανίζουμε
 Το JFrame (μέθοδος show) JFrame
JFrame
 Το βασικό container του swing
 Αποτελείται εξ’ ορισμού από ένα container JRootPane
 Το JRootPane αποτελείται από το διάφανο glassPane
και το ορατό layeredPane
 Το layeredPane περιέχει προαιρετικά ένα menuBar και
το contentPane πάνω στο οποίο προστίθενται όλα τα
υπόλοιπα στοιχεία.
 Συνεπώς, αφού φτιάξουμε το JFrame προσθέτουμε στο
contentPane τα διάφορα components
JFrame f=new JFrame(“title”);
f.getContentPane().add(myComponent);

Αντικείμενα - Τάξεις
Frame JFrame
menuBar JMenuBar
(προαιρετική)

JP anel
contentPane

layeredPane JLayeredPane
glassPane JPanel
Παράδειγμα
import javax.swing.*;

JFrame f = new JFrame(“title”);
JButton b = new JButton(“press me”);
f.getContentPane().add(b);
f.show();
press me
 Παρόμοια
JFrame f = new JFrame(“title”);
JPanel p = new JPanel( );
JButton b = new JButton(“press me”);
p.add(b);
f.setContentPane(p);
f.show();

Το JMenuBar
 Η μπάρα μενού δεν είναι υποχρεωτική για
ένα JFrame
 Μπορούμε να την προσθέσουμε
φτιάχνοντας ένα JMenuBar αντικείμενο
JMenuBar menu = new JMenuBar();
 και αναθέτοντάς το στο JFrame
f.setJMenuBar(menu);
Άλλες παράμετροι ενός JFrame
 Εικόνα
ImageIcon image = new ImageIcon("spiral.gif");
f.setIconImage(image.getImage());
 Αρχικό μέγεθος
f.setSize(100,100);
 Θέση εξ ορισμού (0,0) = πάνω αριστερά στην οθόνη
f.setLocation(50, 100);
 Μέγεθος και Θέση
f.setBounds(120,120,300,300);
 Ανάλυση οθόνης
Dimension dim = f.getToolkit().getScreenSize();
int screenwidth=dim.width;
int screenlegthn=dim.length;

Πώς κλείνουμε ένα Frame


 Τι θα γίνεται όταν πατήσουμε το ;
 Ο πιο απλός τρόπο είναι να χρησιμοποιήσουμε τη μέθοδο
setDefaultCloseOperation(int) της JFrame με όρισμα:
 WindowConstants.DISPOSE_ON_CLOSE – κλείνει το frame
 WindowConstants.ΕΧΙΤ_ON_CLOSE – κλείνει την εφαρμογή
 WindowConstants.DO_NOTHING_ON_CLOSE – δεν κάνει τίποτε,
οπότε ανιχνεύουμε διαφορετικά το γεγονός
 WindowConstants.HIDE_ON_CLOSE – κρύβει το frame χωρίς να το
καταστρέφει
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
H WindowConstants είναι ένα interface που υλοποιεί η JFrame
JPanel
 To JPanel είναι το βασικότερο container μέσα σε ένα
JFrame.
 Ένα JPanel μπορεί να περιέχει components ή άλλα
JPanel επιτρέποντας έτσι την καλύτερη οργάνωση των
στοιχείων στο παράθυρο.
 Κάθε JPanel έχει ένα διαχειριστή τοποθέτησης στοιχείων
(LayoutManager). Ο βασικός διαχειριστής προσθέτει τα
στοιχεία στη σειρά το ένα δίπλα στο άλλο.
 Στα JPanel αλλά και στα υπόλοιπα components
μπορούμε να ορίσουμε ένα τύπο περιγράμματος
(Border)

Περιγράμματα - Borders
 Οι αντίστοιχες τάξεις βρίσκονται στο πακέτο javax.swing.border
 BevelBorder (υπερυψωμένο ή βυθισμένο), CompoundBorder
(διπλό) EmptyBorder (διάφανο), TitledBorder κ.ά.
Panel p=new Panel();
BevelBorder bb = new BevelBorder (BevelBorder.RAISED);
p.setBorder(bb);
Τοποθέτηση components στο JPanel

 Οι Layout Managers είναι τάξεις που


διαχειρίζονται τον τρόπο τοποθέτησης των
στοιχείων ενός παραθύρου
 Υλοποιούν δύο βασικά interfaces τα
LayoutManager και LayoutManager2
 Κάποιοι περιέχονται στο java.awt ενώ κάποιοι
άλλοι στο javax.swing
 Πρώτα ορίζουμε το layout σε ένα container και
μετά προσθέτουμε στοιχεία.

Ορισμός Layouts
 Κάθε παράθυρο (container) έχει ένα
προκαθορισμένο τρόπο τοποθέτησης στοιχείων
(components)
 Τα JPanel έχουν προκαθορισμένα FlowLayout
 Για κάθε παράθυρο ορίζουμε ένα layout με τη
μέθοδο setLayout
myPanel.setLayout(new BorderLayout());
ή
this.getContentPane().setLayout(new
GridLayout(2,2));
Ενδεικτικά layouts
FlowLayout GridLayout BorderLayout
n

Αριστερά προς δεξιά w c e


Πάνω προς κάτω

CardLayout GridBagLayout

Το ένα πάνω στο άλλο JButton

Βασικές τάξεις τοποθέτησης


 FlowLayout(), τοποθετεί τα στοιχεία στη
σειρά
myPanel.setLayout(new
FlowLayout(FlowLayout.CENTER));
myPanel.add(new JButton(“1”));
 GridLayout(int rows, int columns)
myPanel.setLayout(new GridLayout(2,2));
myPanel.add(new JButton(“1”));
 BorderLayout()
myPanel.setLayout(new BorderLayout());
add(new JButton(“1"), BorderLayout.NORTH);
Βασικές τάξεις τοποθέτησης
 CardLayout(), τοποθετεί το ένα στοιχείο πίσω από το
άλλο. Ορατό είναι αυτό που προσθέτουμε πρώτο.
myPanel.setLayout(new CardLayout());
myPanel.add(new JButton(“1”),”first”);
myPanel.add(new JButton(“2”),”second”);
Με τις μεθόδους first, last, next, previous, show
φέρνουμε στην επιφάνεια μια κάρτα
 GridBagLayout(), τοποθετεί τα στοιχεία σε θέσεις ενός
πλέγματος, ώστε να γεμίζουν τη θέση ή να
καταλαμβάνουν πάνω από ένα κελιά στο πλέγμα
GridBagLayout gbl=new GridBagLayout();
myPanel.setLayout(gbl);
GridBagConstraints c = new GridBagConstraints();
c.fill=GridBagConstraints.BOTH;
c.weightx=1.0; c.weighty=1.0;
c.gridx=0; x.gridy=0;
c.gridheight=2;
myPanel.add(new JButton(“one”,c);

Τάξεις στο πακέτο swing


 BoxLayout, τοποθετεί τα στοιχεία σε μια σειρά (ή
στήλη) χωρίς αναδίπλωση. Χρησιμοποιείται κυρίως για
μπάρες εργαλείων.
 Συνδυάζεται με την τάξη Box που είναι Container
Container toolbar = Box.createHorizontalBox( );
toolbar.add(new JButton(“1”));
myPanel.add(toolbar);
 SpringLayout, καθορίζει την απόσταση κάθε
στοιχείου από τα γειτονικά στοιχεία
 OverlayLayout, ScrollPaneLayout
Ειδικά πλαίσια (Panels)
 JScrollPane: Περιέχει ένα στοιχείο μόνο
 Εμφανίζει αυτόματα μπάρες κύλισης αν το στοιχείο δεν
χωρά στο πλαίσιο
JScrollPane sp=new JScrollPane(new JButton(“A button with a long
label on it”));
myPanel.add(sp);
 JSplitPane: Περιέχει δύο στοιχεία με ένα διαχωριστικό
που μετακινείται.
JSplitPane split =new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT, button1, button2);
myPanel.add(split);

Ειδικά πλαίσια (Panels)


 JTabbedPane: Τοποθετεί κάθε στοιχείο πίσω
από τα υπόλοιπα με τη μορφή καρτελών
 Κάθε καρτέλα έχει ένα όνομα και ένα στοιχείο ή
πλαίσιο
JPanel config=new JPanel();
JPanel options=new JPanel();

JTabbedPane tabby = new JTabbedPane( );
tabby.addTab(“Configuration”, config);
tabby.addTab(“Options”, options);
myPanel.add(tabby);
Εσωτερικά παράθυρα
 Η τάξη JDesktopPane μας επιτρέπει να εμφανίσουμε ολόκληρα
παράθυρα (JInternalFrame) μέσα σε ένα JFrame
 Τα εσωτερικά παράθυρα μπορεί να είναι resizable, closable,
maximizable, iconifiable, όπως ακριβώς συμβαίνει με τα παράθυρα
των Windows
JDesktopPane desktop = new JDesktopPane( );
JInternalFrame internal =
new JInternalFrame("Frame 1", true, true, true, true);
internal.setSize(180, 180);
internal.setLocation(20,20);
internal.setVisible(true);
desktop.add(internal);
f.setContentPane(desktop);

Συνδυασμοί panels και layouts


JButton JButton
f: JFrame

NORTH
p1: JPanelFlowLayout
contentPane: JPanel
BorderLayout

CENTER t: JTextArea
Συνδυασμός
JFrame f = new JFrame(“Frame1”);

JPanel p1 = new JPanel( );


JButton b1 = new JButton(“OK”);
JButton b2 = new JButton(“Cancel”);
p1.add(b1);
p1.add(b2);
JTextArea t=new JTextArea("");
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(p1,BorderLayout.NORTH);
f.getContentPane().add(t,BorderLayout.CENTER);

Στοιχεία του Swing


BUTTONS

MENUS
Άλλα COMPONENTS

JApplet Border Interface

JComboBox JColorChooser

ImageIcon

JInternalFrame
JDialog
JFileChooser

Άλλα COMPONENTS

JScrollBar
JLabel JList

JScrollPane JOptionPane JSlider

JSplitPane
JTabbedPane
Άλλα COMPONENTS

JTable
JTextArea

JTextField

JToolBar

JToolTip

JTree

JComponent
 Κάθε JComponent είναι αντικείμενο μιας τάξης.
Συνεπώς:
 Έχει κατάσταση (ιδιότητες)
(π.χ. ενεργό, ορατό, επιλεγμένο, JButton
θέση,κείμενο, εικόνα κλπ.)
 Έχει μεθόδους
(π.χ. Όρισε κείμενο/εικόνα, φόντο)
 Ανταποκρίνεται σε γεγονότα
(π.χ. mouseClicked, mouseEntered, keyTyped, componentMoved)
Πώς χρησιμοποιούμε ένα
Component
1. Το δημιουργούμε
 JButton b = new JButton(“press me”);
2. Το ρυθμίζουμε
 Ιδιότητες: b.text = “press me”;
 Μέθοδοι: b.setText(“press me”);.
3. Του προσθέτουμε components (αν είναι container)
4. Τα προσθέτουμε σε ένα container (εκτός αν είναι
JFrame)
 panel.add(b);
5. Παρακολουθούμε τα γεγονότα σ’ αυτό
 Events: Listeners

Ετικέτες
JLabel label1 = new JLabel(“JLabel");
JLabel label2 = new JLabel("JLabel",SwingConstants.CENTER);
label2.setOpaque(true); label2.setBackground(Color.white);

JLabel label3 = new JLabel("JLabel",SwingConstants.CENTER);


label3.setFont(new Font("Helvetica", Font.BOLD, 18));
label3.setOpaque(true); label3.setBackground(Color.white);

ImageIcon icon = new ImageIcon("image.gif");


JLabel label4 = new JLabel("JLabel",image, SwingConstants.RIGHT);
label4.setVerticalTextPosition(SwingConstants.TOP);
label4.setOpaque(true); label4.setBackground(Color.white);

myPanel.add(label); myPanel.add(label2);
myPanel.add(label3); myPanel.add(label4);
Περιοχές κειμένου
JTextField tf1 = new JTextField();
JTextField tf2 = new JTextField(“text”);
JTextField tf3 = new JTextField(“more text”,40);
tf2.getText();
tf1.setText(“empty”);
JTextArea ta= new TextArea();
ta.append(“text”); ta.append(“\nline2”);
JPasswordField pf=new JPasswordField(“hidden”);

Περιοχές κειμένου
public class TestFrame extends JFrame {
JTextField tf; JTextArea ta;
JPasswordField pf; JScrollPane jsp;
public TestFrame() {
tf = new JTextField(); ta = new JTextArea();
ta.setText("Your Text will appear");
ta.append("\nhere:\n");
pf = new JPasswordField("hidden");
jsp = new JScrollPane();
jsp.getViewport().add(ta);
this.setLayout(new GridLayout(3, 3));
this.getContentPane().add(tf);
this.getContentPane().add(jsp);
this.getContentPane().add(pf);
String password=pf.getText();
ta.append(password);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}
Κουμπιά
….
ta.append(password);
clearButton=new JButton("Clear");
copyButton = new JButton("Copy");
this.getContentPane().add(new JPanel());
this.getContentPane().add(clearButton);
this.getContentPane().add(copyButton);

this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}

Κουμπιά – Ομάδες κουμπιών


JButton b= new JButton(“OK”);
JToggleButton tb1= new JToggleButton(“ON”);
JToggleButton tb2= new JToggleButton(“OFF”);
ButtonGroup buttonGroup = new ButtonGroup();
tb1.setMnemonic(‘n’); // Ενεργοποιείται με ALT+n
tb1.setToolTipText(“This is the ON button”);
tb2.setMnemonic(‘f’); // Ενεργοποιείται με ALT+f
tb1.setToolTipText(“This is the OFF button”);
buttonGroup.add(tb1);
buttonGroup.add(tb2);
myPanel.add(tb1);
Ενεργοποιούνται εναλλάξ
myPanel.add(tb2);
myPanel.add(b);
JCheckBox και JRadioButton
 Τα JCheckBox λειτουργούν ανεξάρτητα και μπορούν να
επιλεγούν όλα μαζί
myPanel.add(new JCheckBox("case 1"));
myPanel.add(new JCheckBox("case 2"));
Τα JRadioButton λειτουργούν σε ομάδες και μόνο ένα επιλέγεται
κάθε φορά.
ButtonGroup options = new ButtonGroup( );
JRadioButton rb1= new JRadioButton("Option 1");
JRadioButton rb2= new JRadioButton("Option 2");
options.add(rb1); options.add(rb2);
myPanel.add(rb1); myPanel.add(rb2);

Λίστες επιλογών
 JComboBox: Περιέχει ένα πίνακα από επιλογές, εμφανίζει στο
χρήστη μόνο μία και επιτρέπει μονές ή πολλαπλές επιλογές.
String [] items = { "uno", "due", "tre", "quattro", "cinque", "sei", "sette",
"otto", "nove", "deici", "undici" };
JComboBox comboBox = new JComboBox(items);
comboBox.addItem("dodici");
comboBox.getSelectedItem() //επιστρέφει Object
comboBox.getSelectedObjects() //επιστρέφει Object[]
 JList: Περιέχει ένα πίνακα από επιλογές, εμφανίζει στο χρήστη
ορισμένες από αυτές (ανάλογα με το ύψος της) και επιτρέπει μονές
ή πολλαπλές επιλογές.
JList list = new JList(comboBox.getModel( ));
list.getSelectedValues() //επιστρέφει Object[]
 Mοιράζονται το ίδιο μοντέλο δεδομένων
Παράδειγμα
public class Human {
String name;
String surname;
int age;
String address;
public Human(String name, String surname, int age, String address) {
this.name = name;
this.surname = surname;
this.age = age;
this.address = address;
}
@Override
public String toString() {
return this.name+" "+this.surname;
}
}

Μοντέλα Δεδομένων για Λίστες


dlm = new DefaultListModel();
dlm.addElement(new Human("George", "Brown", 22, "6th Avenue"));
dlm.addElement(new Human("Mary", "Jones", 18, "5th Avenue"));
dlm.addElement(new Human("Bill", "Murray", 19, "Madison Avenue"));
students = new JList(dlm);
this.getContentPane().add(students);
this.getContentPane().add(clearButton);
this.getContentPane().add(copyButton);

- Φαίνεται ότι επιστρέφει η toString()


- Επιστρέφει όλο το Object
Object[] selected=students.getSelectedValues();
for (int i=0;i<selected.length;i++)
Human h=(Human)selected[i];
Πίνακες - JTable
String[] columnNames = {"First Name", "Last Name", "Age", "Address"};
Object[][] data = {{"George", "Brown", new Integer(22), "6th Avenue"},
{"Mary", "Jones", new Integer(18), "5th Avenue"},
{"Bill", "Murray", new Integer(19), "Madison Avenue"}};
dtm = new DefaultTableModel(data,columnNames);
studentsTable=new JTable(dtm);
JScrollPane jsp2 = new JScrollPane();
jsp2.getViewport().add(studentsTable);
this.getContentPane().add(jsp2);

JTable(Object[][] rowData, Object[] columnNames);


JTable(Vector rowData, Vector columnNames);
JTable(DefaultTableModel dtm);

Μενού επιλογών
JMenu file = new JMenu(“File");
file.add(new JMenuItem(“Open"));
file.add(new JMenuItem(“Close"));
JMenu edit = new JMenu(“Edit");
edit.add(new JMenuItem(“Copy"));
edit.add(new JMenuItem(“Paste"));
JMenu check = new JMenu(“Check");
check.add(new JCheckBoxMenuItem(“Option 1"));
check.add(new JSeparator());
check.add(new JCheckBoxMenuItem(“Option 2", true));
MenuBar mb = new MenuBar();
mb.add(file);
mb.add(edit);
mb.add(check);
myFrame.setJMenuBar(mb);
Μελέτη Περίπτωσης

Μελέτη Περίπτωσης
Παράθυρα διαλόγου

52

Παράθυρα διαλόγου
 Τα παράθυρα διαλόγου χρησιμοποιούνται για να
συλλέξουμε πληροφορίες από το χρήστη
 Τραβούν το ενδιαφέρον του χρήστη καθώς
εμφανίζονται πάνω από την εφαρμογή (π.χ. εισαγωγή
κωδικού)
 Απαιτούν εισαγωγή δεδομένων από το χρήστη και
αποδοχή της επιλογής
 Επιτρέπουν στο χρήστη να κάνει σύνθετες επιλογές
και επιστρέφουν στην εφαρμογή το αποτέλεσμα της
επιλογής (π.χ. επιλογή μιας ομάδας αρχείων και τις
δράσης σε αυτά, επιλογή ενός χρώματος για το φόντο
ενός πλαισίου κλπ)
Το παράθυρο JDialog
 Συμπεριφέρεται όπως και το JFrame
JDialog dialog = new JDialog(myFrame, "Dialog Frame");
JLabel label = new JLabel("This is a message“);
dialog.getContentPane().add(label);
dialog.setVisible(true);

 Μπορεί να μπλοκάρει τη συνέχιση του


προγράμματος (modal) ή όχι (non-modal)
JDialog dialog1 = new JDialog(myFrame, "This is modal", true);
JDialog dialog2 = new JDialog(myFrame, "This is non modal", false);

Έτοιμα πλαίσια διαλόγου


 Φτιάχνονται με κλήση των static μεθόδων της JOptionPane
 int n = JOptionPane.showConfirmDialog(myFrame, “Is it OK?",
“ConfirmDialog", JOptionPane.YES_NO_OPTION);
 String s = (String)JOptionPane.showInputDialog(myFrame, "Name?");
 JOptionPane.showMessageDialog(myFrame, "Hi!");

 Object[] options = {"Yes, please", "No way!"};


int n = JOptionPane.showOptionDialog(myFrame, "Choose", "Choices",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
null, options,options[0]);
Παράθυρο επιλογής αρχείου
 Δημιουργία ενός JFileChooser:
JFileChooser fc = new JFileChooser();
 Εμφάνισή του (π.χ. με το πάτημα ενός JButton)
int returnVal = fc.showOpenDialog(aComponent);

Παράθυρο επιλογής αρχείου


 Στη συνέχεια μπορούμε να διαβάσουμε τις ενέργειες
του χρήστη στο παράθυρο:
if (returnVal == JFileChooser.APPROVE_OPTION) {
// αν ο χρήστης επέλεξε Open
File file = fc.getSelectedFile(); //το αρχείο που επέλεξε
log.append("Opening: " + file.getName() + "." + newline);
}
else {
log.append("Open command cancelled by user." + newline);
}
 fc.showDialog(aComponent, "Save");
//αλλάζει το open button σε Save
Παράθυρο επιλογής χρώματος
 Δημιουργία και χρήση ενός JColorChooser
Color c = JColorChooser.showDialog(myFrame, "Choose a
color", myFrame.getContentPane().getBackground( ));
if (c != null) myFrame.getContentPane().setBackground(c);

Διαχείριση γεγονότων
Περιεχόμενα
 Διαχείριση γεγονότων
 Δημιουργία γεγονότος
 Ακρόαση (ανίχνευση) γεγονότος
 Δημιουργία ακροατή – Κατηγορίες ακροατών
 Σύνδεση ακροατή με στοιχείο
 Πρακτικές χρήσης ακροατών

Διαχείριση γεγονότων
 Το στοιχείο του GUI (π.χ. ένα JButton)
 Παράγει γεγονότα σε συγκεκριμένες συνθήκες
 Ανάλογα με τις δραστηριότητες του χρήστη
 Το γεγονός (π.χ. ένα MouseEvent)
 Ένα αντικείμενο που περιέχει πληροφορίες για το γεγονός
 Ποιος το προκάλεσε, τι ακριβώς προκάλεσε, σε ποιο στοιχείο
του GUI, κλπ
 Οι ακροατές (π.χ. ένας MouseListener)
 Καταλαβαίνουν ένα γεγονός
 Έχουν μεθόδους που παίρνουν γεγονότα ως όρισμα
 Διάφορες κατηγορίες ακροατών (για γεγονότα σχετικά με τα
mouse, keyboard, window, components κλπ)
Δημιουργία γεγονότων
 Τα αντικείμενα επικοινωνούν μεταξύ τους
δημιουργώντας γεγονότα
 Τα γεγονότα είναι αντικείμενα της τάξης
java.util.EventObject και των απογόνων της (π.χ.
AWTEvent)
 Μεταφέρουν πληροφορία για το είδος του γεγονότος,
τη δράση που το προκάλεσε κλπ. Για παράδειγμα
 ένα MouseEvent παράγεται από ένα στοιχείο, όταν ο χρήστης
κινήσει το ποντίκι στην περιοχή του στοιχείου (π.χ. ενός
JButton). Το αντικείμενο MouseEvent περιλαμβάνει
πληροφορία για τις συντεταγμένες του ποντικιού (x,y), για την
κατάσταση των κουμπιών του κλπ.
 Ένα ActionEvent μπορεί να παράγεται από το ίδιο στοιχείο
(π.χ. JButton) ενημερώνοντας ότι κάτι συνέβη με το στοιχείο
 Δεν παράγουν όλα τα στοιχεία τα ίδια γεγονότα

Ακρόαση γεγονότων
 Το πάτημα ενός JButton δημιουργεί ένα γεγονός (αντικείμενο
ActionEvent).
 Για να το χειριστούμε, θα πρέπει στο JButton να προσθέσουμε
ένα τρόπο διαχείρισης γεγονότων.
 Οι μέθοδοι που διαχειρίζονται κάθε γεγονός περιέχονται στο
αντίστοιχο interface. Τα interfaces αυτά ονομάζονται ακροατές –
listeners.
public interface ActionListener extends java.util.EventListener {
public void actionPerformed( ActionEvent e );
}
 Ένα στοιχείο μπορεί να έχει πολλούς ακροατές. Κάθε ακροατής
μπορεί να παρακολουθεί πολλά στοιχεία.
 Συνοψίζοντας: α) Φτιάχνουμε την τάξη που υλοποιεί το
κατάλληλο interface ακροατή, β) προσθέτουμε στο στοιχείο ένα
αντικείμενο της τάξης αυτής.
Α) Δημιουργία ακροατή
 Τα listener interfaces έχουν ένα κοινό πρόγονο το interface
java.util.EventListener που δεν δηλώνει καμία μέθοδο.
 Ένα γεγονός έχει μοναδική πηγή αλλά μπορεί να ανιχνευτεί από
πολλούς ακροατές (π.χ. ο ακροατής του στοιχείου, ο ακροατής
του component που περιέχει το στοιχείο κλπ)
 Κάθε τάξη ακροατής γεγονότων θα πρέπει να υλοποιεί ένα ή
περισσότερα listener interfaces.
public class myActionListener implements ActionListener{
public void actionPerformed( ActionEvent e ){
myTextArea.append(“Something happened”);
}
}
 Εκτός από τα Listener interfaces υπάρχουν και οι αντίστοιχες
Adapter τάξεις (είναι abstract)
public class myMouseListener implements MouseListener
public class myMouseListener extends MouseAdapter

Τύποι ακροατών
Ακροατής Μέθοδοι
ActionListener actionPerformed(ActionEvent)
MouseListener mouseClicked(MouseEvent)
MouseAdapter mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mousePressed(MouseEvent)
mouseReleased(MouseEvent)
MouseMotionListener mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
KeyListener keyPressed(KeyEvent)
keyReleased(KeyEvent)
keyTyped(KeyEvent)
ItemListener itemStateChanged(ItemEvent)
Τύποι ακροατών
ComponentListener componentHidden(ComponentEvent)
ComponentAdapter componentShown(ComponentEvent)
componentMoved(ComponentEvent)
componentResized(ComponentEvent)
ContainerListener componentAdded(ContainerEvent)
ContainerAdapter componentRemoved(ContainerEvent)
FocusListener focusGained(FocusEvent)
FocusAdapter focusLost(FocusEvent)
WindowListener windowActivated(WindowEvent) , windowClosed
WindowAdapter windowClosing, windowDeactivated,
windowDeiconified, windowGainedFocus
windowIconified, windowLostFocus
windowOpened, windowStateChanged

Παράδειγμα - actionListener
υποχρεωτικά
public class CopyButtonActionListener implements ActionListener {
TestFrame targetFrame;
public CopyButtonActionListener(TestFrame targetFrame) {
this.targetFrame=targetFrame;
}
public void actionPerformed(ActionEvent e) {
String password = targetFrame.pf.getText();
targetFrame.ta.append(password);
}
}

Και στην TestFrame …


copyButton.addActionListener(new CopyButtonActionListener(this));
Παράδειγμα - mouseListener
υποχρεωτικά
public class myMouseListener implements MouseListener {
public void mousePressed(MouseEvent e) {
textArea.append ("Mouse pressed: # of clicks: “
+ e.getClickCount(), " detected at position “ + e.getX()+ “,”
+ e.getY() + “ of component”
+ e.getComponent().getClass().getName() + ".\n");
}
public void mouseReleased(MouseEvent e) {…}
public void mouseClicked(MouseEvent e) { …}
public void mouseEntered(MouseEvent e) {
textArea.append ("Mouse entered detected on "
+ e.getComponent().getClass().getName() + ".\n");
}
public void mouseExited(MouseEvent e) { …}
}

Β) Ανίχνευση γεγονότων
 Για να μπορεί ένα στοιχείο να ανιχνεύει γεγονότα θα
πρέπει να του προσθέσουμε τον αντίστοιχο ακροατή
button1.addActionListener(new myActionListener());
//έτσι θα ανιχνεύουμε πάτημα του κουμπιού
button1.addMouseListener(new myMouseListener());
//έτσι θα ανιχνεύουμε κινήσεις του ποντικιού πάνω στο κουμπί
 Τα FocusEvent, KeyEvent, MouseEvent,
ComponentEvent είναι γεγονότα που προκαλούνται
από όλα τα components του swing
 Το ContainerEvent προκαλείται από όλα τα containers
του Swing
Γεγονότα - Στοιχεία που τα παράγουν
ActionEvent JButton, JCheckBoxMenuItem,
JComboBox,
JFileChooser, JList,
RadioButtonMenuItem,
JTextField, JToggleButton
ListSelectionEve JList, ListSelectionModel
nt
ItemEvent JCheckBoxMenuItem, ItemListener,
JComboBox, JRadioButtonMenuItem,
JToggleButton
MenuEvent JMenu
MenuKeyEvent JMenuItem
WindowEvent JDialog, JFrame, JWindow

Πρακτικές δήλωσης και χρήσης


ακροατών
Υλοποίηση με interface
 Υλοποίηση με interface
 Η τάξη μας είναι απόγονος της JFrame (περιέχει
components κλπ)
 Μπορεί να υλοποιεί όλα τα interfaces που χρειάζεται για να
ανιχνεύει γεγονότα
 Θα πρέπει να δηλώνει όλες τις μεθόδους, όλων των
interfaces, ακόμη και αν υλοποιεί ορισμένες μόνο από αυτές.
 Με τον τρόπο αυτό έχουμε ένα μόνο ακροατή για όλα τα
στοιχεία που βάζουμε στο πλαίσιο.
 Υλοποίηση με inner class και adapter
 Η τάξη κληρονομεί μόνο έναν adapter και ορίζει μόνο τις
μεθόδους που σχετίζονται με τα γεγονότα που ανιχνεύει
 Θα πρέπει να δηλωθεί ως εσωτερική τάξη ώστε να έχει
πρόσβαση στα μέλη της κύριας τάξης που είναι απόγονος
της JFrame
 Έχουμε έτσι ένα ακροατή για κάθε στοιχείο στο πλαίσιο.

Παράδειγμα χρήσης interface


import javax.swing.*;
import java.awt.event.*;
public class MyClass extends JFrame implements MouseListener {
JButton button1;
void init(){
button1=new JButton("OK");
this.add(button1); //είναι ταυτόχρονα πλαίσιο
button1.addMouseListener(this); //και ακροατής
this.setSize(200,200);
}
public void mouseClicked(MouseEvent e) { }
//παρόμοια οι mousePressed και mouseReleased
public void mouseExited(MouseEvent e) { button1.setText("OFF");}
public void mouseEntered(MouseEvent e) { button1.setText("ON");}
public static void main(String args[]){
MyClass m=new MyClass();
m.init();
m.show();
}}
Χρήση ανώνυμης εσωτερικής
τάξης
 Αν η λειτουργικότητα αφορά ένα μόνο component είναι
προτιμότερο να χρησιμοποιήσουμε ανώνυμη εσωτερική τάξη
public class MyClass extends JFrame {
JButton button1;
void init(){
button1=new JButton("OK");
this.add(button1);
button1.addMouseListener(new MouseAdapter(){
public void mouseExited(MouseEvent e) { button1.setText("OFF");}
public void mouseEntered(MouseEvent e) { button1.setText("ON");}
});
this.setSize(200,200);
}
public static void main(String args[]){ …}
}

Περισσότερα για τους ακροατές


 ActionListener
 Ορίζειτη μέθοδο
void actionPerformed(ActionEvent)
 Το ActionEvent έχει δύο χρήσιμες μεθόδους
 String getActionCommand()
Δίνει ένα μήνυμα που περιγράφει το γεγονός
 int getModifiers()
Μας ενημερώνει αν όταν συνέβη το γεγονός (π.χ.
Mouse click) είχε πατηθεί κάποιο από τα πλήκτρα
SHIFT, CTRL ή ALT
Περισσότερα για τους ακροατές
 ComponentListener
 voidcomponentHidden(ComponentEvent)
 void componentShown(ComponentEvent)
 void componentMoved(ComponentEvent)
 void componentResized(ComponentEvent)
Ανάλογα με το αν το στοιχείο κρύφτηκε, εμφανίστηκε,
μετακινήθηκε ως προς το πλαίσιο στο οποίο ανήκει,
κλπ
 Το ComponentEvent έχει τη μέθοδο
 Component getComponent()
Επιστρέφει το στοιχείο που προκάλεσε το γεγονός

Περισσότερα για τους ακροατές


 ItemListener: Συνδέεται με μενού, checkboxes
 void itemStateChanged(ItemEvent)
 To ItemEvent έχει τις εξής μεθόδους
 Object getItem()
Συνήθως ένα String με το κείμενο του στοιχείου
 ItemSelectable getItemSelectable()
Επιστρέφει το στοιχείο που προκάλεσε το γεγονός
 int getStateChange()
Αν το αντικείμενο επιλέχθηκε ή όχι
Περισσότερα για τους ακροατές
 KeyListener: Ανιχνεύει πατήματα πλήκτρων
 void keyTyped(KeyEvent) // για Unicode characters
 void keyPressed(KeyEvent) // για πλήκτρα
 void keyReleased(KeyEvent)
 To KeyEvent έχει τις εξής μεθόδους
 int getKeyChar() , void setKeyChar(int)
Συνδέει το event με κάποιο Unicode character
 int getKeyCode() , void setKeyCode(int)
Επιστρέφει τον κωδικό του πλήκτρου που προκάλεσε το
γεγονός

Περισσότερα για τους ακροατές


 WindowListener
 void windowOpened(WindowEvent)
 void windowClosing(WindowEvent)
 void windowClosed(WindowEvent)
 void windowIconified(WindowEvent),
void windowDeiconified(WindowEvent)
 void windowActivated(WindowEvent)
void windowDeactivated(WindowEvent)
 To WindowEvent έχει τη μέθοδο
 Window getWindow()
Που επιστρέφει το παράθυρο που προκάλεσε το γεγονός
 Περισσότερα:
http://java.sun.com/docs/books/tutorial/uiswing/
Παράδειγμα
 Στο κατάστημα με τους υπολογιστές θέλουμε να
δημιουργήσουμε μια φόρμα που θα κάνει τα
ακόλουθα
 Θα διαβάζει από αρχείο όλους τους υπολογιστές και
θα τους εμφανίζει σε μια λίστα, τυπώνοντας μόνο το
μοντέλο του υπολογιστή
 Θα επιτρέπει να επιλέξουμε ένα μόνο υπολογιστή και
 Αν πατήσουμε το κουμπί Details θα μας δείχνει σε
ξεχωριστό παράθυρο τις λεπτομέρειες του
υπολογιστή.
Πόσες φόρμες χρειαζόμαστε
MainFrame OrderFrame ProductFrame

createOrder addProduct

setVisible(true) setVisible(true)

Τι ξέρει ArrayList<Order> orderList


η κάθε
φόρμα; ArrayList<Product> productList

Τι
δημιουργεί Order o = new Order() Product p = new Product()
κάθε
φόρμα;

Μια φόρμα δεν μπορεί να επιστρέψει δεδομένα


Γι' αυτό πρέπει να της περάσουμε μια αναφορά στην αντίστοιχη δομή

Λύση
 Στον κατασκευαστή της OrderFrame και της
ProductFrame περνάμε την orderList και την
ProductList αντίστοιχα
 Στο κουμπί "Καταχώρηση…", δημιουργούμε το
αντίστοιχο αντικείμενο και το προσθέτουμε στη
λίστα που έχουμε περάσει στη φόρμα.
 Έτσι ενημερώνουμε έμμεσα (μέσω αναφοράς)
την αρχική λίστα και μπορούμε πλέον άφοβα να
κλείσουμε τη φόρμα
 Η φόρμα κλείνει με τη μέθοδο dispose()
10. Πολυνηματικές εφαρμογές –
Τεκμηρίωση κώδικα

Multithreading
 Μulti-processing
 Πολλές διεργασίες ταυτόχρονα
 Κάθε διεργασία έχει το δικό της χώρο μνήμης ή ενδέχεται όλες
να μοιράζονται και κάποιο χώρο μνήμης
 Ουσιαστικά μία διεργασία εκτελείται κάθε φορά
 Το λειτουργικό αναλαμβάνει τη διαχείριση
 Multithreading
 Multiple points of execution (threads) within the same memory
space

2
Threads - Νήματα
 Τα threads επιτρέπουν εργασίες να τρέχουν παράλληλα
με την κύρια εφαρμογή
 Είναι διεργασίες που τρέχουν στον ίδιο χώρο
διευθύνσεων: μοιράζονται τις μεταβλητές στιγμιοτύπων,
αλλά διατηρούν και τοπικές μεταβλητές
 Χρησιμοποιούνται από το JVM σε συγκεκριμένες
περιπτώσεις
 Όταν φορτώνουμε μια εικόνα ή ένα ήχο μέσα από ένα applet.
 Όταν καλούμε την update του αντικειμένου graphics
 Μπορούμε να δηλώσουμε και να χρησιμοποιήσουμε
δικά μας νήματα.

Γιατί χρειάζομαι threads


 Single threaded application:
 Ένα νήμα κάνει τα πάντα
 Αν υπάρχουν ενέργειες να εκτελεστούν, θα περιμένουν τη σειρά τους
 Αν μια ενέργεια θέλει χρόνο για να ολοκληρωθεί, η εφαρμογή θα
φαίνεται ότι έχει κολλήσει
 Multithreaded application:
 Ένα νήμα για κάθε εργασία
 Αν ένα νήμα έχει αναλάβει μια αργή ενέργεια, τα υπόλοιπα νήματα θα
συνεχίσουν να εκτελούνται
 Αν η εφαρμογή τρέχει σε σύστημα με πολλούς επεξεργαστές, το
λειτουργικό θα στείλει κάθε νήμα σε άλλο επεξεργαστή.

4
Πότε χρειάζομαι threads
 Όταν η εφαρμογή μου έχει GUI
 Τα νήματα που αφορούν το GUI διαχειρίζονται τις ενέργειες του χρήστη
και αναθέτουν τις εργασίες σε άλλα νήματα
 Το GUI συνεχίζει να αποκρίνεται στις ενέργειες του χρήστη ακόμη κι αν
τρέχουν άλλα νήματα
 Όταν η εφαρμογή μου πρέπει να αποκρίνεται ασύγχρονα (π.χ.
Network based applications)
 Τα δεδομένα που έρχονται από το δίκτυο μπορεί να έρχονται χωρίς
ομαλή ροή
 Ένα νήμα μπορεί να ελέγχει την πόρτα εισόδου δεδομένων
 Όποτε έρθουν δεδομένα το νήμα ολοκληρώνει τη διαχείρισή τους ή την
αναθέτει σε άλλο νήμα
 Η εφαρμογή μας τρέχει σε άλλο νήμα

Πώς λειτουργεί ο μηχανισμός;


 Κάθε νήμα έχει το δικό του χώρο (virtual registers και calling stack)
 Ο "scheduler" αποφασίζει ποιο νήμα εκτελείται και πότε
 Το VM μπορεί να έχει το δικό του scheduler ή να χρησιμοποιεί το scheduler
του λειτουργικού (το JVM έχει δικό του)
 Ο scheduler έχει μια λίστα με τα threads που είναι έτοιμα να τρέξουν (run
queue) και μια λίστα με τα threads που περιμένου είσοδο (wait queue)
 Κάθε νήμα έχει μια προτεραιότητα. Τα threads υψηλής προτεραιότητας
επιλέγονται κάθε φορά από την run queue
 Δεν μπορούμε να υποθέσουμε από πριν με ποια σειρά θα
χρονοπρογραμματιστούν τα threads.

6
Καταστάσεις ενός thread

yield(), or Running
time out run() returns
Thread created start()
New Ready run() join() Finished

interrupt() sleep()
Target wait()
finished

Wait for target Wait for time Wait to be


to finish out notified
Time out notify() or
notifyAll()
Blocked
Interrupted()

Πώς τρέχει ένα thread


 Ξεκινά με τη μέθοδο run() που περιέχει το βασικό σύνολο εντολών
του νήματος
 Ενεργοποιείται με το start()
 Τερματίζει όταν ολοκληρωθεί η run()
 Αν θέλουμε να μην ολοκληρωθεί το νήμα, πρέπει να μπλοκάρουμε τη
run (π.χ. με endless loop)
 Ένα thread καλεί κάποιο άλλο με την κλήση της start()

Thread1 start() Thread2

Thread Object

run()

8
Ένα Thread για κάθε Task
 Ένα Thread μπορεί να είναι αντικείμενο της κλάσης
Thread ή δικών μας κλάσεων που κληρονομούν τη
Thread
 Συχνά οι δικές μας κλάσεις μπορεί να έχουν δική τους
κληρονομικότητα, και ταυτόχρονα να θέλουμε να είναι
threads
 Τότε χρησιμοποιούμε το Runnable interface
 Ένα interface με μοναδική μέθοδο την run()
 Χρειαζόμαστε και κάποιον (ένα dummy Thread object)
να φτιάξει και να ξεκινήσει το νήμα μας

Τρόποι δήλωσης (1/2)


 Επέκταση της Thread
public class HelloThread extends Thread {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new HelloThread()).start();
}
}
Τρόποι δήλωσης (2/2)
 Υλοποίηση της Runnable
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
Thread1 start() Thread2

Thread Object Runnable Object

run() run()

Μέθοδοι
 Thread.yield(): όποτε καλείται δίνει προτεραιότητα στα υπόλοιπα
threads εις βάρος του τρέχοντος.
 Thread.sleep(long x): σταματά προσωρινά (για x milliseconds) την
εκτέλεση του νήματος
 final void otherThread.join(): διακόπτει το τρέχον νήμα μέχρι να
τελειώσει το otherThread
 isAlive(): επιστρέφει true για Ready, Blocked, or Running state
 interrupt(): αν το thread είναι Ready or Running, σταματά. Αν είναι
blocked ξυπνά και γίνεται Ready ενώ πετά μια
java.io.InterruptedException
 isInterrupt(): ελέγχει αν το νήμα εξακολουθεί να είναι σταματημένο ή
ξαναξεκίνησε
Πώς τερματίζω ένα thread
 Στη Java 1.1. η κλάση Thread είχε μέθοδο stop()
 Ένα thread σταματούσε ένα άλλο thread καλώντας τη stop()
 Είχε και suspend() και resume()
 Αυτό όμως οδηγούσε σε αμοιβαίους αποκλεισμούς (deadlocks)
 Πλέον δε χρησιμοποιούνται (deprecated)

 Αν θέλουμε να τερματίσουμε το thread περιμένουμε να τελειώσει η


run
 Αν θέσω ένα boolean γνώρισμα στο thread και φροντίζω να ελέγχω την
τιμή του εντός της run, μπορώ να ελέγξω πότε θα τελειώσει
 Μέσω μιας μεθόδου set αλλάζω την τιμή στο γνώρισμα (από άλλο νήμα
που τρέχει) και τερματίζω τη run() βγαίνοντας από το infinite loop

13

Κοινή χρήση;
 Υπάρχουν θέματα συγχρονισμού (ταυτόχρονης
πρόσβασης στον κοινόχρηστο χώρο) που πρέπει να
ληφθούν υπόψη.
 Για να αντιληφθούμε καλύτερα τα νήματα θεωρούμε δύο
μόνο αντικείμενα που μοιράζονται τον κοινό χώρο: Το
αντικείμενο Thread της Java που ελέγχει το χώρο
(ελεγκτής) και ένα αντικείμενο που περιέχει τη μέθοδο
που θα εκτελέσουμε παράλληλα (νήμα).
 Το αντικείμενο νήμα έχει μια μέθοδο run η οποία:
 πρέπει να είναι public, να μην παίρνει ορίσματα, να μην
επιστρέφει τιμές και να μην παράγει εξαιρέσεις.
 Το αντικείμενο ελεγκτής φτιάχνει το νήμα, το ξεκινά
(καλώντας τη run) και το καταστρέφει μόλις τελειώσει.
Δήλωση μιας τάξης νήματος
 Μια τάξη νήμα υλοποιεί τη διεπαφή Runnable (ορίζει μια
μέθοδο run).
 Περιέχει μια σημαία (flag) επιτυχούς ολοκλήρωσης της
διεργασίας.
 Μέσα στη run υλοποιεί την παράλληλη διεργασία και στο
τέλος της ενημερώνει τη σημαία.
class Animation implements Runnable {
boolean finished;
public void run( ) {
...
finished=true;
}
}

Έλεγχος ενός νήματος


 Στην κυρίως εφαρμογή φτιάχνουμε το αντικείμενο νήμα
Animation happy = new Animation();
 Φτιάχνουμε το αντικείμενο ελεγκτή και του αναθέτουμε
να παρακολουθεί το νήμα
Thread myThread = new Thread( happy );
 Ο ελεγκτής ξεκινά το νήμα
myThread.start( );
 Η τελευταία εντολή εκτελεί τη run του αντικειμένου happy
(νήμα)
 Για να ξεκινήσουμε ένα δεύτερο νήμα (οποιασδήποτε
τάξης) ο ελεγκτής συνδέεται με αυτό και το ξεκινά
myThread = new Thread( new anotherThreadClass() );
myThread.start( );
Παύση και επανεκκίνηση νήματος
 Η μέθοδος sleep( ) σταματά το νήμα για κάποια
milliseconds, δημιουργώντας ένα InterruptedException
αν το νήμα είναι ήδη σταματημένο
 Η μέθοδος interrupt( ) ξαναξεκινά ένα νήμα που ήταν
αδρανές
try {
sleep( 500 ); // περιμένει 0,5"
}
catch ( InterruptedException e ) {
// αν κάποιος καλέσει την interrupt για το νήμα
}
 Οι μέθοδοι wait() και notify( ) συντονίζουν την εκτέλεση
δύο ή περισσοτέρων νημάτων

Τερματισμός του Thread


 Πρέπει να μπλοκάρουμε τη public void stopThread(){
run() σε ένα loop this.stopThread=true;
 Πρέπει να φροντίσουμε να }
μπορεί να επιστρέψει public void run( ) {
βγαίνοντας από το loop
….
while (true) {

if (stopThread)
return;

}
}
Παράδειγμα
 Δημιουργήστε ένα GUI με 3 buttons και
ένα text field
 Με το start: θα ξεκινά ένα thread που θα
τυπώνει την τρέχουσα ώρα και
ημερομηνία στο text field κάθε 1 sec.
 Με το stop: το thread θα σταματά
 Με το reset: θα καθαρίζει το text field

Ταυτόχρονη πρόσβαση σε δεδομένα

 Δύο threads επιχειρούν να ενημερώσουν τα ίδια δεδομένα (π.χ. να


προσθέσουν/διαγράψουν/διαβάσουν αντικείμενα από μια συλλογή)
 Το τελικό αποτέλεσμα εξαρτάται απόλυτα από τον scheduler και δεν
μπορούμε να το προκαθορίσουμε
 Όσο το ένα thread γράφει κάτι στα δεδομένα, μπορεί να τα
«κλειδώσει» μέχρι να τελειώσει
 Κανείς εκτός από το thread δεν μπορεί να δει τα κλειδωμένα
δεδομένα
 Ο μηχανισμός αυτός στην Java λέγεται synchronization

20
Συγχρονισμός νημάτων
 Έστω ένας τραπεζικός λογαριασμός με ένα αρχικό ποσό, ένα νήμα
που κάνει κατάθεση και δύο νήματα που κάνουν ανάληψη

Parent 1000 Child1

public class SavingsAccount SavingsAccount


{ Child2
private float balance;
public synchronized void withdraw(float anAmount)
{
if ((anAmount>0.0) && (anAmount<=balance))
balance = balance - anAmount;
}
public synchronized void deposit(float anAmount)
{
if (anAmount>0.0)
balance = balance + anAmount;
}
}

Παράδειγμα
 Ο Parent καταθέτει χρήματα κάθε 5" καλώντας την deposit
 Τα Child αφαιρούν χρήματα κάθε 3" καλώντας την withdraw
class Parent implements Runnable { class Child implements Runnable {
SavingsAccount account; SavingsAccount account;
String name; String name;
boolean bankrupted = false; boolean foundajob= false;
public Parent(String n, SavingsAccount s) { public Child(String n, SavingsAccount s) {
this.name = n; this.name = n;
this.account = s; this.account = s;
} }
public void run() { public void run() {
while (true) { while (true) {
try { try {
Thread.sleep(5000); Thread.sleep(3000);
} catch (InterruptedException ex) {…} } catch (InterruptedException ex) {…}
account.deposit(this.name, 1000); account.withdraw(this.name, 200);
if (bankrupted) { if (foundajob) {
return; return;
} }
} }
} }
Η main
 Φτιάχνει
 το λογαριασμό
 τον Parent
 τα Child
 Ξεκινά τα νήματα

Συγχρονισμένες μέθοδοι
Συνεπώς
 Έχουμε withdraw κλήσεις από τα Child που
εξυπηρετούνται όσο υπάρχει υπόλοιπο
 Μόλις αδειάσει ο λογαριασμός η τελευταία κλήση της
withdraw παγώνει (wait)
 Μια κλήση της deposit από τον parent καλεί τη notify και
ξεπαγώνει τη συγχρονισμένη μέθοδο withdraw
 Πότε παγώνει η deposit και πως βγαίνουμε από την
κατάσταση αυτή;

Thread Pools
 Αν ξεκινάμε ένα thread για κάθε task είναι δαπανηρό.
 Θέλουμε μια δεξαμενή με threads, που να μας δίνει ένα thread αν
αυτό έχει τελειώσει την προηγούμενη εργασία
 Η υλοποίηση προσφέρεται μέσα από το Executor interface το οποίο
ελέγχει τα Runnable αντικείμενα σε ένα thread pool
 Το ExecutorService είναι ένα subinterface του Executor
«interface»
java.util.concurrent.Executor
+execute(Runnable object): void Executes the runnable task.

«interface»
java.util.concurrent.ExecutorService
+shutdown(): void Shuts down the executor, but allows the tasks in the executor to
complete. Once shutdown, it cannot accept new tasks.
+shutdownNow(): List<Runnable> Shuts down the executor immediately even though there are
unfinished threads in the pool. Returns a list of unfinished
tasks.
+isShutdown(): boolean Returns true if the executor has been shutdown.
+isTerminated(): boolean Returns true if all tasks in the pool are terminated.
26
Δημιουργία εκτελεστή (Executor)

 Φτιάχνουμε Executor αντικείμενα μέσα


από static methods της Executors

java.util.concurrent.Executors
+newFixedThreadPool(numberOfThreads: Creates a thread pool with a fixed number of threads executing
int): ExecutorService concurrently. A thread may be reused to execute another task
after its current task is finished.
+newCachedThreadPool(): Creates a thread pool that creates new threads as needed, but
ExecutorService will reuse previously constructed threads when they are
available.

27

ExecutorService executor = Executors.newFixedThreadPool(5);


Runnable worker = new MyClassThatImplementsRunnable();
executor.execute(worker);

public class MyClassThatImplementsRunnable implements Runnable {


public void run() {
System.out.println(Thread.currentThread().getName() + " Start.");
processCommand();
System.out.println(Thread.currentThread().getName() + " End.");
}
}

28
Τεκμηρίωση κώδικα

javadoc

29

Σχόλια (Comments)
 Σχόλια είναι σημειώσεις σε φυσική γλώσσα
και όχι source code.
 Τα Comments χρησιμοποιούνται για να:
 Τεκμηριώνουμε: τον σκοπό και τους στόχους του
προγράμματος, τον author, ιστορικά στοιχεία για
τις αναθεωρημένες εκδώσεις του code (revision
history), copyright notices, κτλ.
 Περιγράφουμε: fields, constructors, και methods
 Την επεξήγηση μη καθαρών σημείων του code
 Προσωρινός σχολιασμός μέρους του code, σαν
υπενθύμιση για μελλοντική χρήση
Μορφές Σχολίων

 Ένα “block” σχόλιο γράφεται ανάμεσα στα


σύμβολα /* και */. Για παράδειγμα:
/* Exercise 5-2 for Java Methods
Author: Miss Brace
Date: 3/5/2010
Rev. 1.0 */

 Ένα single-line σχόλιο γράφεται μετά από το


σύμβολο // μέχρι το τέλος της γραμμής. Για
παράδειγμα:
wt *= 2.2046; // Convert to kilograms

Σχόλια Τεκμηρίωσης
 Μπορούμε να χρησιμοποιήσουμε το special
utility program javadoc για να παράξουμε
αυτόματα τεκμηρίωση του source code μας σε
HTML format.
 Τέτοιας μορφής σχόλια πρέπει να προηγούνται
των: classes, methods, ή fields
 Μπορούν να χρησιμοποιηθούν special javadoc
tags:
@param – περιγράφει τις παραμέτρους μιας μεθόδου
(method)
@return - περιγράφει την τιμή που επιστρέφονται από μια
μέθοδο (method’s return value)
javadoc Comments (συνέχ.)
/** δείχνει ένα javadoc
comment

/**
* Returns total sales from all vendors;
* sets <code>totalSales</code> Μπορεί να
* to 0. χρησιμοποιεί HTML
* tags
* @return total amount of sales from all vendors
*/

Common
style

Δομή σχολίων μεθόδου


Περιγραφή

Ετικέτες

Προαπαιτούμενα Συνέπειες
Ετικέτες Μεθόδων
 @see
 @since
 @deprecated
 @param
 @return
 @throws / @exception
 {@link}
 {@linkplain}
 {@inheritDoc}
 {@docRoot}

Παράδειγμα
/**
* Sample.java – a class that demonstrates the use of javadoc
* comments.
* @author Ruth Dannenfelser
* @version 2.0
* @see Sample2
*/
public class Sample extends Sample2 {
public String words;
/**
* Retrieve the value of words.
* @return String data type.
*/
public String getWords() /**
* Set the value of words.
{
* @param someWords A variable of type String.
return words; */
} public void setWords(String someWords)
{
words = newWords;
}
}
Δημιουργία τεκμηρίωσης

javadoc –d doc src/package/*.java

37

11. Προχωρημένα θέματα


Προγραμματισμού με αντικείμενα
Java Enterprise Technologies
Εσωτερικές κλάσεις

Εσωτερικά interfaces και κλάσεις


 Μέσα σε ένα interface (σε μία κλάση) μπορούμε να δηλώσουμε ένα
άλλο interface (μια κλάση)
 Χρησιμοποιούνται
 για να ομαδοποιήσουμε σχετικά μεταξύ τους interfaces ή κλάσεις
(λειτουργικότητα), που δε χρησιμοποιούνται σε άλλο περιεχόμενο.
 για να διαχωρίσουμε τη λειτουργικότητα σε μια κλάση από την ίδια την
κλάση
 Παράδειγμα:
 μια κλάση BinarySearchTree μπορεί να έχει εκτός από τις μεθόδους για
προσθήκη και αφαίρεση κόμβων, και την εσωτερική κλάση
BinarySearchTreeNode
 Μέθοδοι που υλοποιούν κάποιο αλγόριθμο ταξινόμησης ή αναζήτησης
κόμβων ομαδοποιούνται σε εσωτερική κλάση της BinarySearchTree.
Για παράδειγμα ένας Iterator για τη διάσχιση του δέντρου.
Εσωτερικές (inner) κλάσεις
 Έχουν πρόσβαση στα μέλη της κλάσης που τις περιέχει
 Η εξωτερική κλάση δεν μπορεί να προσπελάσει private
μέλη της εσωτερικής
 Δεν είναι το ίδιο πράγμα με τη σύνθεση
 Επιτρέπουν την καλύτερη οργάνωση των κλάσεων
 Είναι τεσσάρων τύπων
 Static member classes
 Member classes
 Local classes
 Anonymous classes

Static inner κλάσεις


 Στατικό μέλος μιας κλάσης όπως οι μέθοδοι.
 Έχει πρόσβαση μόνο στα στατικά μέλη της
κλάσης που την περιέχει
 Μπορεί να περιέχει δικά της στατικά μέλη
 Μπορούμε να φτιάξουμε στιγμιότυπα static inner
κλάσεων που όμως δε σχετίζονται με το
εξωτερικό αντικείμενο (ανήκουν στην κλάση)
 Φωλιασμένες κλάσεις χωρίς μεγάλη
χρησιμότητα
class BinarySearchTree {
public static class BSTNode {
BSTNode left;
BSTNode right;
Human value;
public BSTNode(Human value) { this.value = value; }
}
protected BSTNode root;

public BinarySearchTree() { root = null; }


public void insert(Human x) { root = insert(x, root); }
public void remove(Human x) { root = remove(x, root); }
public BSTNode find(Human x) { return find(x, root); }
protected BSTNode insert(Human x, BSTNode t) {
if (t == null) { t = new BSTNode(x); }
else if (x.compareTo(t.value) < 0) {
t.left = insert(x, t.left); } public static void main(String args[]){
Human a1=new Human(1,"joe","black");
else if (x.compareTo(t.value) > 0) { Human a2=new Human(2,"bill","brows");
t.right = insert(x, t.right); } Human a3=new Human(3,"mary","pierce");
BinarySearchTree bst=new BinarySearchTree();
else { System.out.println(x bst.insert(a1);
+ " is already in the tree"); } bst.insert(a2);
return t; bst.insert(a3);
bst.insert(a1);
} }

}

Παράδειγμα
class Parcel{
boolean local;
public static class CostHandler{
private int cost=10;
public int getCost() { return cost; }
public void setCost(int c) {cost=c;}
}
}
 Η μεταγλώττιση παράγει τα αρχεία Parcel και Parcel$CostHandler.class
Parcel.CostHandler p1=new Parcel.CostHandler();
Parcel.CostHandler p2 = new Parcel.CostHandler();
p1.setCost(20);
System.out.println(“p1:"+p1.getCost()+” p2:”+ p2.getCost());
Non-static inner κλάσεις
 Επώνυμες κλάσεις μέλη: Ανήκουν στο κάθε αντικείμενο της κλάσης και
έχουν πρόσβαση σε όλα τα μέλη του
 Τοπικές κλάσεις: Δηλώνονται σε ένα block κώδικα και είναι ορατές μόνο σε
αυτό
 Ανώνυμες κλάσεις: Είναι τοπικές κλάσεις χωρίς όνομα.
 Παράδειγμα: Έστω ότι υπάρχει μια κλάση SearchCriteria με συγκεκριμένη
λειτουργικότητα. Η ακόλουθη μέθοδος search:
myOrder.search( new SearchCriteria () {
public boolean matches(Object o) { ... }
}
);
 Δημιουργεί μια ανώνυμη κλάση που επεκτείνει την SearchCriteria. Έχει
μόνο μια μέθοδο, αλλά μπορούμε να ορίσουμε μεταβλητές και άλλες
μεθόδους αν θέλουμε.

class BinarySearchTree {
public static class BSTNode {
BSTNode left;
BSTNode right;
Human value;
public BSTNode(Human value) { this.value = value; }
}

public class InOrderIterator{


public void iterateInOrder(){ inorder(root); }
public void iteratePreOrder(){ preorder(root); }
public void iteratePostOrder(){ postorder(root); }
private void inorder(BSTNode t){
if (t.left != null ) inorder(t.left);
System.out.println(t.value);
if (t.right != null) inorder(t.right); public static void main(String args[]){
Human a1=new Human(1,"joe","black");
} Human a2=new Human(2,"bill","brows");
… Human a3=new Human(3,"mary","pierce");
} BinarySearchTree bst=new BinarySearchTree();
bst.insert(a3);
bst.insert(a1);
protected BSTNode root; bst.insert(a2);
BinarySearchTree.InOrderIterator it =
… bst.new InOrderIterator();
} it.iterateInOrder();
}
Παράδειγμα
class Parcel{
boolean isLocal; private int cost=10;
public class CostHandler{
public int getCost() {
if (isLocal) cost=2*cost;
return cost;
}}}
 Χρειαζόμαστε πλέον ένα αντικείμενο Parcel
Parcel p=new Parcel();
p.isLocal=true;
Parcel.CostHandler p1 = p.new CostHandler();
System.out.println(“p1:"+p1.getCost());

Πλεονεκτήματα
 Αντικειμενοστραφής κώδικας
 Κάθε αντικείμενο της εσωτερικής κλάσης έχει
πρόσβαση στα μέλη της εξωτερικής κλάσης
 Ταυτόχρονα είναι ένα ξεχωριστό αντικείμενο.
 Ομαδοποίηση της συμπεριφοράς
π.χ. Ένας αλγόριθμος διάσχισης σε ένα ArrayList μπορεί να
διαχωριστεί από τις μεθόδους κατασκευής του ArrayList με
χρήση μιας εσωτερικής κλάσης (iterator).
 Οργάνωση κώδικα
 Ιεραρχίες εσωτερικών κλάσεων
 Κλήσεις στο εξωτερικό αντικείμενο (callback)
Μειονεκτήματα των inner
κλάσεων
 Δύσκολες στην κατανόησή τους. Απαιτούν
εμπειρία.
 Αυξάνει το συνολικό αριθμό κλάσεων στον
κώδικα, άρα και την πολυπλοκότητα
 Τα περισσότερα εργαλεία ανάπτυξης
προσφέρουν περιορισμένη υποστήριξη
 Δεν
έχουν δυνατότητα επισκόπησης των
μελών της εσωτερικής κλάσης

Java applets
Τι είναι το Applet
 Είναι ένα πρόγραμμα Java που τρέχει στο περιβάλλον
μιας εφαρμογής (συνήθως σε ένα φυλλομετρητή –
browser ή στο πρόγραμμα appletviewer του jdk).
 Η εφαρμογή διαθέτει δικό της JVM στο οποίο τρέχει το
applet.
 Το applet προσφέρεται μέσα από ένα HTML έγγραφο.
Στην ετικέτα APPLET προσδιορίζεται το URL του
applet.
 Κάθε applet επεκτείνει την τάξη java.applet.Applet ή
την javax.swing.JApplet που επίσης επεκτείνει την
Applet.
 Για λόγους ασφαλείας τα applets τρέχουν με
περιορισμούς (in a sandbox).

Ιεραρχία τάξεων
 Ένα applet είναι στιγμιότυπο μιας
απογόνου των Applet ή
JApplet.
 Είναι ένα Panel, και συνεπώς ένα
παράθυρο Container.
 Μια τάξη applet πρέπει να είναι
public.
 Κάθε applet κληρονομεί τις
μεθόδους init, start, paint,
stop, και destroy.
Τι κάνουν οι μέθοδοι που
κληρονομεί
 init(): καλείται μόλις φορτώνεται το applet και το
αρχικοποιεί
 start(): καλείται όποτε ο browser έρθει στο προσκήνιο
(focus) και εκτελεί τις λειτουργίες του applet
 stop(): καλείται όταν ο browser ελαχιστοποιείται ή όταν
ο χρήστης φεύγει από μια σελίδα
 destroy(): καλείται όταν κλείσει ο φυλλομετρητής και
κάνει ότι χρειάζεται πριν τερματίσει το applet

Στα applet δεν υπάρχει main (αυτή την παρέχει ο


φυλλομετρητής)

Υπέρβαση μεθόδων
 Αν δεν υπερβούμε τις μεθόδους αυτές το applet δεν κάνει τίποτε
 init(): Καλείται μία φορά. Περιέχει τον κώδικα που
κατασκευάζει ότι χρειαζόμαστε (αρχικοποιεί μεταβλητές, GUI,
ακροατές κλπ).
 start(): Περιέχει το σώμα εντολών του applet που θέλουμε να
ξανατρέχει κάθε φορά που εμφανίζεται το applet.
 stop(): Πρέπει να σταματά την εκτέλεση του applet (π.χ. Ένα
χρονόμετρο). Χρησιμοποιείται σε συνδυασμό με τη start για
να διακόπτει χρονοβόρες διεργασίες όταν το applet είναι στο
φόντο.
 destroy(): Ελευθερώνει πόρους του συστήματος (π.χ. Κλείνει
συνδέσεις σε ΒΔ κλπ.).
Ένα απλό applet
import javax.swing.*;
import java.awt.*;
public class HiWorld extends JApplet {
public void init() {
getContentPane().add(
new JLabel(“Hi World!"));
}
}

Δομή μιας σελίδας HTML Test.html


HTML
<html>
<head>
HEAD BODY
<title> Hi World Applet </title>
</head>
TITLE περιεχόμενο

<body>
<applet code="HiWorld.class”
width=300 height=200>
</applet>
</body>
</html>
Εκτέλεση από command line

 appletviewer c:\java\Test.html
 Στην περίπτωση αυτή το HiWorld.class
βρίσκεται στο c:\java\

Οργάνωση αρχείων
 Αν το applet μας δεν είναι σε κάποιο package αρκεί το
html και το class να είναι στο ίδιο φάκελο
 Διαφορετικά πρέπει η οργάνωση των φακέλων να
ακολουθήσει αυτή των packages
 Αν τα applets βρίσκονται σε άλλο φάκελο από αυτό
του html τότε χρησιμοποιούμε την παράμετρο
codebase.
<applet codebase=“../applets”
code=mypackage/AppletClassName.class
width=100 height=200> </applet>
Κύκλος ζωής ενός Applet
init()
 Μόλις ο browser εντοπίσει μια ετικέτα <APPLET>
 Δεσμεύει το χώρο που καθορίζουν οι παράμετροι
width και height για το applet start()
 Φορτώνει τα bytecode για τη συγκεκριμένη υποτάξη
της Applet
 Δημιουργεί το αντικείμενο applet Κάνει κάτι
 Καλεί τη μέθοδο init για να αρχικοποιήσει το
αντικείμενο (π.χ. Ορίζει χρώμα, γραμματοσειρά κλπ.)
 Καλεί τη μέθοδο start. stop()
 Στη συνέχεια καλείται η paint
 Αν φύγουμε από τη σελίδα καλείται η μέθοδος
destroy()
stop
 Αν ξαναμπούμε στη σελίδα εκτελείται η μέθοδος
start.
 Όποτε κλείσει ο φυλλομετρητής καλείται η μέθοδος
destroy

Μέθοδοι ενός JApplet (ως Container)

 Container getContentPane()
 Επιστρέφει το ContentPane του applet
 void setJMenuBar(JMenuBar menuBar)
 Προσθέτει μενού στο applet
 void setLayout(LayoutManager manager)
 Ορίζει τη διάταξη στο applet
 System.out.println(String s)
 Εμφανίζει το μήνυμα σε μια ξεχωριστή κονσόλα
Design patterns

Τι είναι και γιατί τα χρειαζόμαστε


 Συχνά στα προγράμματά μας υπάρχουν
επαναλαμβανόμενες ανάγκες για τις οποίες πρέπει να
επαναλαμβάνουμε την ίδια λύση με μικρές αλλαγές
 Τα design patterns είναι μια αφηρημένη περιγραφή
(σχεδίαση) της λύσης με χρήση αντικειμένων, κλάσεων
και διεπαφών και εναλλακτικές υλοποιήσεις ανάλογα με
το πρόβλημα.
a common solution to a recurring problem in design

25
Στόχοι
 Codify good design
 Να κάνουμε όσο πιο γενική γίνεται τη σχεδίαση μιας λύσης
 Give design structures explicit names
 Να δημιουργήσουμε ένα κοινό λεξικό
 Να μειώσουμε την πολυπλοκότητα
 Capture and preserve design information
 Να διατηρήσουμε τη δομή του προγράμματος
 Να βελτιώσουμε την τεκμηρίωση
 Facilitate restructuring/refactoring
 Να βελτιώσουμε την ανεξαρτησία των λύσεων
 Να μειώσουμε το χρόνο υλοποίησής τους, χτίζοντας σε
προκαθορισμένα σχέδια

Design Pattern Catalogues


 GoF (“the gang of four”) catalogue
 “Design Patterns: Elements of Reusable
Object-Oriented Software,” Gamma, Helm,
Johnson, Vlissides, Addison-Wesley, 1995
 POSA catalogue
 Pattern-Oriented Software Architecture,
Buschmann, et al.; Wiley, 1996
GoF Design Patterns
Creational Structural Behavioral
Factory Method Adapter Interpreter
Abstract Factory Bridge Template
Builder Composite Method
Prototype Decorator Chain of
Singleton Flyweight Responsibility
Facade Command
Proxy Iterator
Mediator
Memento
Observer
State
Strategy
Visitor

Παραδείγματα
 Observer  MVC
 Singleton

29
Observer (Behavioral)
 Σκοπός
 Μια σχέση εξάρτηση 1:Ν μεταξύ αντικειμένων. Όταν το 1 αλλάξει
ενημερώνει τα υπόλοιπα για να αλλάξουν κι αυτά
 Εφαρμογές
 Όταν το ίδιο αντικείμενο εμφανίζεται μέσα από δύο ή
περισσότερα άλλα αντικείμενα (MVC)
 Όταν μια αλλαγή στο αντικείμενο, επηρεάζει άλλα, αλλά δεν
ξέρουμε ποια τη στιγμή της αλλαγής
 Όταν ένα αντικείμενο πρέπει να ενημερώσει άλλα αντικείμενα
χωρίς να ελέγξει ποια είναι αυτά

Observer (Cont'd)
 Structure
Subject
-observers Observer

+attach(in o : Observer)
+detach(in o : Observer) 1 * +update()
+notify()
{for all o in observers
{ o.update() } }

ConcreteSubject -subject ConcreteObserver


-subjectState -observerState
+getState() 1 * +update()

{return subjectState } {observerState =


subject.getState() }
Schematic Observer Example
Observers

Subject

Observable - Sample Code


import java.util.Observable;
public class ObservableValue extends
Observable
{
private int n = 0;
public ObservableValue(int n)
{
this.n = n;
}
public void setValue(int n)
{ Marks this Observable object as having
this.n = n; been changed; the hasChanged method
setChanged(); will now return true.
notifyObservers();
}
public int getValue() If this object has changed, as indicated by
{ the hasChanged method, then notify all of its
return n; observers and then call
} the clearChanged method to indicate that this
} object has no longer changed.
Observer - Sample Code
import java.util.Observer;
import java.util.Observable;
public class TextObserver implements
Observer
{
private ObservableValue ov = null;
public class Main
public TextObserver(ObservableValue ov) {
{ public Main()
this.ov = ov; {
} ObservableValue ov = new ObservableValue(0);
TextObserver to = new TextObserver(ov);
public void update(Observable obs, Object ov.addObserver(to);
obj) }
{ public static void main(String [] args)
if (obs == ov) {
{ Main m = new Main();
}
System.out.println(ov.getValue()); }
}
}
}

Observer – Sample Code


public class Main
{
public Main()
{
ObservableValue ov = new ObservableValue(0);
TextObserver to = new TextObserver(ov);
ov.addObserver(to);
}
public static void main(String [] args)
{
Main m = new Main();
}
}
Abstract Factory (Creational)
 Σκοπός
 Να δημιουργεί οικογένειες σχετικών
αντικειμένων χωρίς να δίνει το όνομα της
κλάσης
 Εφαρμογή
 Όταν δεν μπορούμε από πριν να
προβλέψουμε το αντικείμενο που θέλουμε να
δημιουργήσουμε κατά τη χρήση

Abstract Factory
AbstractFactory
 Structure Client

+createProductA()
* AbstractProductA * *
+createProductB()

*
*

ProductA1 ProductA2
«instantiate»

ConcreteFactory1 ConcreteFactory2

+createProductA() +createProductA() AbstractProductB *


+createProductB() +createProductB() «instantiate»

«instantiate» «instantiate»
ProductB1 ProductB2
Abstract Factory - Example
public class MazeFactory { public class MazeGame {
public MazeFactory() {...} // ...
public Maze makeMaze(){ public Maze createMaze (MazeFactory factory) {
return new Maze(); Maze aMaze = factory.makeMaze();
} Room r1 = factory.makeRoom(1);
public Room makeRoom(int n) { Room r2 = factory.makeRoom(2);
return new Room(n); Door theDoor = factory.makeDoor(r1, r2);
} aMaze.addRoom(r1);
public Wall makeWall() { aMaze.addRoom(r2);
return new Wall(); r1.setSide(MapSite.NORTH, factory.makeWall());
} r1.setSide(MapSite.EAST, theDoor);
public Door makeDoor(Room r1, Room r1.setSide(MapSite.SOUTH, factory.makeWall());
r2) { r1.setSide(MapSite.WEST, factory.makeWall());
return new Door(r1, r2); r2.setSide(MapSite.NORTH, factory.makeWall());
} r2.setSide(MapSite.EAST, factory.makeWall());
}; r2.setSide(MapSite.SOUTH, factory.makeWall();
r2.setSide(MapSite.WEST, theDoor); return aMaze;
}
}

Abstract Factory - Example


public class EnchantedMazeFactory extends MazeFactory {
public EnchantedMazeFactory() {...}
public Room makeRoom(int n) {
return new EnchantedRoom(n, new Spell());
}
public Door makeDoor(Room r1, Room r2) {
return new DoorNeedingSpell(r1, r2);
}
}

public class BombedMazeFactory extends MazeFactory {


public BombedMazeFactory() {...}
public Wall makeWall(){
return new BombedWall();
}
public Room makeRoom(int n){
return new RoomWithABomb(n);
}
}
Abstract Factory - Client
MazeGame game; // The instance of a game.
……….
Maze aMaze; // A reference to a maze.
switch(choice) {
case ENCHANTED: {
EnchantedMazeFactory factory = new EnchantedMazeFactory();
aMaze = game.createMaze(factory);
break;
}
case BOMBED: {
BombedMazeFactory factory = new BombedMazeFactory();
aMaze = game.createMaze(factory);
break;
}
}

Abstract Factory
 Πλεονεκτήματα/Μειονεκτήματα
+ Flexibility: αφαιρεί τα type dependencies κατά τη
χρήση
+ Abstraction: κρύβει τη σύνθεση των αντικειμένων
 Δύσκολο να επεκταθεί το factory interface ώστε να
φτιάχνει νέα προϊόντα
Iterator (Behavioral)
 Σκοπός
Η διάσχιση στοιχείων σειριακά, χωρίς να μας
ενδιαφέρει η δομή στην οποία αποθηκεύονται
 Εφαρμογές
 Αλγόριθμοι διάσχισης
 Ενιαίος τρόπος διάσχισης σε συλλογές

Iterator
 Structure
Iterator
Aggregate (Glyph) Client
+first()
+next()
+createIterator() * * * *
+isDone()
+currentItem()

ConcreteAgregate ConcreteIterator

+createIterator() 1 *

{ return ConcreteIterator(this); }
Singleton (Creational)
 Σκοπός
 Να βεβαιωθούμε ότι έχουμε ένα μόνο αντικείμενο από
μια κλάση σε όλο το πρόγραμμα και καθολική
πρόσβαση από παντού.
 Εφαρμογές
 Όταν χρειαζόμαστε ακριβώς ένα αντικείμενο από μια
κλάση
 Όταν το μοναδικό αντικείμενο πρέπει να είναι
επεκτάσιμο (με κληρονομικότητα) και κατά τη χρήση
δεν θέλουμε να τροποποιείται ο κώδικας

Singleton (cont'd)
 Structure

Singleton
-uniqueInstance : Singleton
-singletonData
{ return uniqueInstance; }
+instance()
+singletonOperation()
+getSingletonData()
Singleton - Example

public class ClassicSingleton {


private static ClassicSingleton instance = null;
protected ClassicSingleton() {
lazy instantiation
// Exists only to defeat instantiation.
}
public static ClassicSingleton getInstance() {
if(instance == null) {
instance = new ClassicSingleton();
}
return instance; public class SingletonInstantiator {
} public SingletonInstantiator() {
ClassicSingleton instance = ClassicSingleton.getInstance();
}
ClassicSingleton anotherInstance =
new ClassicSingleton();
...
}
}

Java Enterprise
Technologies
H aρχιτεκτονική του Web
 Αρχιτεκτονική client/server

 Αιτήσεις του client - απαντήσεις του server

Μορφές αρχιτεκτονικής client-server

 Αρχιτεκτονική δύο επιπέδων (2-tier).


 Στον client τρέχει μια εφαρμογή που διαβάζει τα περιεχόμενα
της ΒΔ στον server.
 Αρχιτεκτονική τριών επιπέδων (3-tier)
 Η εφαρμογή τρέχει στο server και συνδέει το interface του
client με τη ΒΔ.
 Αρχιτεκτονική πολλών επιπέδων (multi-tier)
 Η εφαρμογή τρέχει διαμοιρασμένη σε περισσότερους servers
που επικοινωνούν μεταξύ τους.
Αρχιτεκτονική δύο επιπέδων (Fat client)

Database
Server

Εφαρμογή
στον Client Database
Server
Driver Driver

Αρχιτεκτονική τριών επιπέδων(thin client)

Database
Driver Server
Εφαρμογή
Εφαρμογή
στον Client
στο Server Database
Server
Driver
Απαιτήσεις αρχιτεκτονικής 3-tier
 Ανάπτυξη της διεπαφής με το χρήστη
(user-interface)
 Ανάπτυξη της εφαρμογής που θα συνδέει
το user-interface με τη βάση δεδομένων
(application logic)
 Ανάπτυξη της βάσης δεδομένων
(database schema)

Java EE

Java Enterprise Edition


Enterprise Computing
Προκλήσεις Τεχνολογίες Προϊόντα
Portability J2SE™ App Servers
Diverse J2EE™ Web Servers
Environments
JMS Components
Time-to-market
Servlet Databases
Core Competence
JSP Object to DB
Assembly tools
Integration Connector
XML
Data
Binding
XSLT

Τι είναι το Java EE?


 Μια ανοικτή πρότυπη πλατφόρμα για
 Ανάπτυξη, εκτέλεση και διαχείριση
 n-tier, Web-enabled, server-centric, και
component-based εφαρμογών
The Java™ Platform

Java Technology Java Technology Workgroup High-End


Enabled Devices Enabled Desktop Server Server

Umesh Bellur

The JavaTM Platform

Optional
Packages

Optional
Packages

Personal Personal
Java 2 Java 2 Basis Profile Profile
Enterprise Standard
Edition Edition Foundation Profile MIDP
(J2EE) (J2SE)
Java
CDC CLDC Card
APIs

JVM KVM CardVM

* Under development in JCP


Java EE APIs

J2EE APIs και τεχνολογίες


 Servlets
 JSP
 EJB 3.0
 JavaSever Faces
 Java Persistence (JPA), Hibernate
 Spring Framework
Java Servlets

Server Side Java - Servlets


 Απαιτούν την εγκατάσταση του Java Web Server (παρέχεται
από τη Sun). Άρα μπορούν να μεταφερθούν σε οποιαδήποτε
πλατφόρμα διαθέτει Java Virtual Machine
 Η εγκατάσταση του JWS ξεκινά κάποιο service που δέχεται
κλήσεις σε συγκεκριμένη θύρα του server.
 Τα Servlets είναι classes που μπορεί να δημιουργούν HTML
κώδικα, βασισμένα σε κάποιες παραμέτρους.
 Ο browser καλεί τα servlets με κάποιες παραμέτρους και
παίρνει σαν απάντηση μια δημιουργημένη HTML σελίδα.
Servlet vs. CGI
Request
RequestCGI1
CGI1 Child
Childfor
forCGI1
CGI1
CGI
CGI
Request
RequestCGI2
CGI2 •Καλύτερη
Based
Based Child
Childfor
forCGI2
CGI2
Webserver διαχείριση μνήμης
Request Webserver •Ταχύτερη
RequestCGI1
CGI1 Child
Childfor
forCGI1
CGI1 απόκριση
Request
RequestServlet1
Servlet1 Servlet
Servlet Based
BasedWebserver
Webserver
Request Servlet1
RequestServlet2
Servlet2 Servlet1
JVM
JVM
Request Servlet1 Servlet2
Servlet2

Στο CGI κάθε HTTP request δημιουργεί ένα νέο process.


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

Servlets
 Είναι java εφαρμογές που εκτελούνται από ένα web server, σε
αντίθεση με τα applets που εκτελούνται στον client.
 Τα servlets πολλές φορές χρησιμοποιούνται για να φτιάξουν δυναμικές
HTML σελίδες.

www.home.com

form.html reply.class
1. Δίνει τα στοιχεία του π.χ. Ηρακλής, 4. Η σελίδα παράγεται
Βαρλάμης δυναμικά και στέλνεται
2. Πατάει submit στον client
3. Καλείται η διεύθυνση
http://www.home.com/reply.class?name=‘
Ηρακλής’,surname=‘Βαρλάμης’
HelloWorld Servlet
public class HelloWorldServlet extends HttpServlet {
public void doGet (HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
PrintWriter out;
res.setContentType("text/html");
out = res.getWriter();
out.println("<html>");
out.println("<head><title>Hello
World</title></head>");
out.println("<body>");
out.println("<h1>Hello World</h1>");
out.println("</body></html>"); }
}
Όταν στο browser δώσουμε διεύθυνση:
www.server.com:4444/HelloWorld.class
μας επιστρέφεται μια HTML σελίδα.

JSP

Java Server Pages


JSP – Java Server Pages
 Είναι HTML σελίδες που περιέχουν κώδικα Java. Ο
κώδικας αυτός εκτελείται στο server πριν η σελίδα
σταλεί στο χρήστη.
 Είναι πιο εύκολα στη χρήση από τα servlets.
 Και στις δύο περιπτώσεις ο web server πρέπει να
υποστηρίζει Java δυνατότητες.
 π.χ. Πάνω από τον IIS, μπορούμε να βάλουμε τον
Tomcat της Apache που είναι java web server

What is JSP Technology?


 Διαχωρίζουν το business logic από την
παρουσίαση
Η παρουσίαση γίνεται με HTML (XML/XSLT)
 Το business logic υλοποιείται με παραμετροποίηση
έτοιμων Java Beans ή με custom tags
 Καλύτερη διαχείριση κώδικα, επαναχρησιμοποίηση
example.jsp
<html> <head> <title> JSP Example</title>
<%@ page import = "java.io.*" %>
</head>
<body>
<%
String sn1; String sn2; int n1,n2;
sn1 = request.getParameter("n1");
sn2 = request.getParameter("n2");
n1 = Integer.parseInt(sn1);
n2 = Integer.parseInt(sn2);
out.println("The numbers were " + sn1 + " and " + sn2);
out.println("<br>");
out.println("The sum is " + (n1+n2));
%>
</body>
</html>

To jsp θα κληθεί ως εξής http://www...../example.jsp?n1=1&n2=1

Java Beans

69
Java Beans
 Επαναχρησιμοποιήσιμα προγράμματα.
 Αποτελούν την απάντηση της Java στα ActiveX
components.
 Είναι σύνθετα αντικείμενα (π.χ. κουμπιά, μπάρες
κύλισης, ημερολόγια, επεξεργαστές κειμένου,
λογιστικά φύλλα κλπ.) η συμπεριφορά των οποίων
μπορεί να καθοριστεί.
 Τα Java Beans μπορούν να αγοραστούν και να
χρησιμοποιηθούν μέσα από ένα γραφικό
περιβάλλον ανάπτυξης εφαρμογών, χωρίς ειδικές
γνώσεις προγραμματισμού.

Παράδειγμα (Barchart bean)


HTML+Java Beans
 Tα JSPs επιτρέπουν την ανάμειξη του HTML και του
κώδικα της Java σ’ έναν ενοποιημένο πηγαίο κώδικα
 Από τεχνική άποψη, μπορούμε να κάνουμε σ’
ένα JSP όλη τη δουλειά ενός JavaBean
 Αλλά στην πραγματικότητα τα JSPs σχεδιάσθηκαν για
να χρησιμοποιηθούν στο επίπεδο παρουσίασης
 Ο πολύ μεγάλος φόρτος υπολογισμών που συμβαίνει
στο παρασκήνιο θα πρέπει να χειρισθεί από κάποιον
μηχανισμό που να είναι αφοσιωμένος σ’ αυτή τη
δουλειά, όπως είναι τα JavaBeans

72

Παράδειγμα
package MyBeans;
public class Circle {
double radius;
double area;
public void setRadius(double r) {radius = r;}
public double getRadius() {return radius;}
public void setArea(double a) {area = a;}
public double getArea() {return area;}
}

73
<jsp:useBean name="circle1" class=“MyBeans.Circle">
<html>
<head>
<title> Ένα Απλό Παράδειγμα JavaBean </title>
</head>
<body>
<jsp:setProperty name="circle1" property="radius" value="2">
Εμβαδόν = <jsp:getProperty name="circle1" property="area">
</body>
</html>

74

EJB

Enterprise Java Beans


Τι είναι τα EJB
 Μια τεχνολογία που χρησιμοποιεί ολοκληρωμένες
εφαρμογές (παραμετρικές) στο server (server-side
component) για να λύσει συνηθισμένα προβλήματα
 Προσφέρουν εύκολη/γρήγορη ανάπτυξη εφαρμογών:
Transactional, distributed, multi-tier, portable, scalable,
secure, …
 Διαχωρίζει το business logic από το application logic
(από το που και πως τρέχουν οι εφαρμογές)

EJB Architecture
Enterprise JavaBeans
Enterprise JavaBeans

Synchronous communication Asynchronous communication


Session Bean Entity Bean Message-Driven Bean

Stateless Stateful

Bean managed Container managed


Persistence Persistence
(BMP) (CMP)

Συνολικά

79
Ενδεικτική αρχιτεκτονική μιας
Java EE εφαρμογής
Web Server EJB Server

DB & EIS
Resources

Browser Web Server EJB Server

Stand-alone

N -tier J2EE Architecture

Web Tier EJB Tier


J2EE Application Anatomies
● 4-tier J2EE applications
– HTML client, JSP/Servlets, EJB, JDBC/Connector
● 3-tier J2EE applications
– HTML client, JSP/Servlets, JDBC
● 3-tier J2EE applications
– EJB standalone applications, EJB, JDBC/Connector
● B2B Enterprise applications
– J2EE platform to J2EE platform through the
exchange of JMS or XML-based messages

Προγραμματισμός ΙΙ
(Java)
Επανάληψη
1ο μάθημα
 Κλάσεις
 Δήλωση κλάσης,
 Δήλωση χαρακτηριστικών, μεθόδων
 Αντικείμενα
 Δημιουργία αντικειμένου
 Κλήση μεθόδων, χαρακτηριστικών
 Έλεγχος πρόσβασης (ενθυλάκωση)

Ορισμός κλάσης Στόχο έχουν να


class Human { χειρίζονται τα
boolean alive; δεδομένα, να τα
int age; Δεδομένα τροποποιούν ή να
String name; επιστρέφουν τις τιμές
void born()
αυτών, σε όποιον τις
{ ζητήσει
alive = true;
}
void speak() Λειτουργίες
{

}
System.out.println(“Hi!”); Μέθοδοι
void incr_age()
{
age = age +1;
}
}
Κλήση μεθόδου = Αποστολή Μηνύματος
5
Κλήση μεθόδων
 Μια μέθοδος καλείται από κάποιο αντικείμενο (συνήθως)
π.χ.
Human John= new Human();
John.born();
John.speak();
John.setAge(10);
 Μπορούμε να αναφερθούμε απευθείας στα δεδομένα
του αντικειμένου.
John.age=15;
int z=John.getAge();

Τα όρια μιας κλάσης


 Υπάρχουν τρεις τύποι πρόσβασης στα μέρη μιας κλάσης: public,
private, και protected.
 Δημόσια (public), τα μέρη είναι διαθέσιμα σε όλους
 Ιδιωτική (private), τα μέρη είναι διαθέσιμα μόνο στην ίδια την κλάση
και τις λειτουργίες της
 Προστατευμένη (protected), τα μέρη είναι διαθέσιμα στην κλάση και
σε όσες κλάσεις την κληρονομούν.
 Δεδομένη (default) πρόσβαση, όταν δεν δηλώνεται κάποια από τις
προηγούμενες, τα μέρη είναι διαθέσιμα στην κλάση και σε όλες τις
υπόλοιπες κλάσεις της ίδιας εφαρμογής (του ίδιου package)

7
Νέος ορισμός κλάσης
class Human { void speak()
private boolean alive; {
private int age; System.out.println(“Hi!”);
void Human() }
{
void incr_age()
alive = true;
{
age = 0
age = age +1;
}
public int getAge()
}
{ }
return age;
}
public void setAge(int a)
{
age=a;
}
8

Συμπερασματικά
 Σε ένα πρόβλημα:
 Προσπαθώ να δω: ποια αντικείμενα εμπλέκονται, τι δεδομένα
έχει το καθένα από αυτά και ποιες λειτουργίες επιτελεί και στη
συνέχεια ορίζω τις αντίστοιχες κλάσεις
 Σε μια κλάση
 Ορίζω χαρακτηριστικά: name, surname, age
 Ορίζω μεθόδους πρόσβασης: getName(), setName() ..
 Ορίζω άλλες βοηθητικές μεθόδους
 Στο τέλος
 Ορίζω μια κλάση με μια μέθοδο main()
 Η κλάση αυτή εκτελεί το πρόγραμμά μου. Μόνο που δεν περιέχει
όλη τη λύση. Κάποια πράγματα τα αναλαμβάνουν τα αντικείμενα

9
2ο μάθημα
 Static και Final
 Μέθοδοι
 Πέρασμα αντικειμένου σε μέθοδο
 Υπερφόρτωση μεθόδων
 Μέθοδοι κατασκευαστές
 Υπερφόρτωση κατασκευαστών
 Πακέτα
 Βοηθητικά πακέτα της Java
 Σύνθεση και κληρονομικότητα
10

Τελεστής ανάθεσης
 Δημιουργώντας ένα αντικείμενο, public class Complex {
ουσιαστικά δεσμεύουμε μνήμη και private double x,y;
δημιουργούμε μια αναφορά σε αυτή.
public double real() { return x; }
Complex c1 = new Complex();
Complex c2 = new Complex(); public double imag() { return y; }
c1.setReal(9); public void setReal(double u) {x=u; }
c1.setImag(47); public void setImag(double v) {y=v; }
c2=c1;
}
 Όταν αναθέσουμε ένα αντικείμενο (c1)
σε ένα άλλο (c2), ουσιαστικά έχουμε
δύο αναφορές στην ίδια θέση μνήμης
c2
(αυτή που δεσμεύτηκε για το c1)
c2 = c1; c1
 To φαινόμενο αυτό ονομάζεται aliasing x=9.0, y=47.0
(συνωνυμία) public double real()
public double imag()
public void setReal(double u)
public void setImag(double v)

11
H equals στις κλάσεις χρήστη
 Ορίζοντας τη μέθοδο equals καθορίζουμε τον
τρόπο με τον οποίο θα συγκρίνονται τα
αντικείμενα της κλάσης μας
public class Complex {
private double x,y;

public boolean equals(Complex c) {
if (x==c.x && y==c.y)
return true;
else return false;
}
}

12

static γνωρίσματα- μέθοδοι

 Αν ένα γνώρισμα είναι κοινό για όλα τα αντικείμενα μιας κλάσης τότε
δεσμεύουμε μια φορά χώρο για όλα τα αντικείμενα.
 Κατά τη δήλωση της κλάσης, τη δηλώνουμε static. Το γνώρισμα αυτό θα
δημιουργηθεί μία φορά μόλις δηλωθεί το πρώτο αντικείμενο αυτής της
κλάσης και θα μπορεί να χρησιμοποιείται από κάθε αντικείμενο της ίδιας
κλάσης.
π.χ. static float bonus;
 Αν θέλουμε να αναφερθούμε στο γνώρισμα αυτό, μπορούμε απ’ ευθείας
μέσω της κλάσης:
π.χ. Human.bonus=100,00;
 Παρόμοια ισχύουν και για τις μεθόδους.
π.χ. static setBonus(float b)
Human.setBonus(200,00);
 Τα static μέλη μπορούμε να τα καλούμε είτε απ’ευθείας μέσω της κλάσης
είτε μέσω των αντικειμένων που δημιουργούμε. Οι static μέθοδοι έχουν
πρόσβαση στα static μέλη της κλάσης.

13
Final γνωρίσματα
 Πρακτικά: final = μόνο για ανάγνωση
 Αν ένα γνώρισμα δηλωθεί final, τότε λειτουργεί ως σταθερά που
 πρέπει να αρχικοποιηθεί
 και δεν αλλάζει τιμή
 Αν η παράμετρος εισόδου μιας μεθόδου δηλωθεί final τότε δεν
μπορεί να αλλάξει τιμή στο σώμα της μεθόδου.
 public void setHour(final int hrs)
 Αν ένα αντικείμενο δηλωθεί final τότε το όνομα του αντικειμένου θα
αναφέρεται πάντα στο ίδιο αντικείμενο.
 Αν μια κλάση δηλωθεί final τότε δεν μπορεί να κληρονομηθεί από
άλλη κλάση.

14

Τελικοί (Final) μέθοδοι


 Οι “final” μεταβλητές γίνονται σταθερές
 Ανατίθεται ακριβώς μία φορά και δε μπορεί να
αλλάξει
 Οι “final” μέθοδοι δεν είναι overridable
Η κλάση γονέα τις ορίζει μία φορά και δεν ορίζονται
ξανά στις υπο-κλάσεις
 Όλες οι private μέθοδοι είναι έμμεσα τελικές
(implicitly final)
 Οι μέθοδοι δεν μπορούν να είναι μαζί abstract και
final - γιατί;
 Εξασφαλίζουμε ότι η συμπεριφορά διατηρείται και
δεν μπορεί να τις αλλάξει κανείς στις υπο-κλάσεις
15
Final κλάσεις
 Οι “final” κλάσεις δεν κληρονομούνται
 Ολοι οι μέθοδοι της γίνονται έμμεσα τελικές
 Οταν θέλουμε να είμαστε σίγουροι ότι κανείς δεν θα
τις κληρονομήσει

public final class String{ …..}

 Οι final μέθοδοι και κλάσεις δεν


χρησιμοποιούνται συχνά

16

Δομή μεθόδου
πρόσβαση τύποςΕπιστροφής όνομαΜεθόδου (τυπος1 παράμετρος1, …)
{

}

public double addDouble (double num1, double num2)


{
return num1+num2;
}

17
attribute

Μέθοδοι Input parameters

method
return type

class Human { System.in System.out


boolean alive;
int age; name
String name;
phrase void
void speak(String phrase)
{ speak
System.out.println(“Hi!”); name,
System.out.println(“My name is ”+name); phrase
System.out.print(“You asked me to say:”);
System.out.println(phrase); age
}
int getAgeAfter(int months){ months return type
int years=months/12; getAgeAfter
int ageafter=age+years;
return ageafter;
}
age
void setAge(){
Scanner keyboard=new Scanner(System.in); void
System.out.println(“How old are you?”);
age=keyboard.nextInt(); setAge
} System.in System.out
}
18

Υπερφόρτωση μεθόδων
 Σε μια τάξη μπορούμε να ξαναχρησιμοποιήσουμε το ίδιο
όνομα για μεθόδους που έχουν ελαφρώς διαφορετική
συμπεριφορά
 Διαφορετικούς τύπους ορισμάτων
 Διαφορετικό πλήθος ορισμάτων

void speak (String phrase);


void speak ();
void speak (int times, String phrase);

19
Μέθοδος κατασκευαστής
 Βασικός ή κενός κατασκευαστής:
 Μια public μέθοδος με όνομα ίδιο με αυτό της τάξης,
χωρίς παραμέτρους και τύπο επιστροφής.
 public Human(){ } – Δεσμεύει μνήμη για το
αντικείμενο και κάνει τις αρχικοποιήσεις
 Αν τον ορίσουμε στην τάξη, μπορούμε να ορίσουμε
τις αρχικοποιήσεις που θα κάνει
 Μπορούμε να ορίσουμε άλλους κατασκευαστές.
Οπότε αναιρείται ο βασικός. Αν θέλουμε και το βασικό
κατασκευαστή πρέπει υποχρεωτικά να τον ορίσουμε.

20

Παράδειγμα (1)
 Ορισμός ενός καλύτερου κατασκευαστή για τη Human
public Human (String tempName, String tempSurname,
int tempAge)
{
name=tempName;
surname=tempSurname;
age=tempAge;
}
 Αν ορίσουμε μόνο αυτόν τον κατασκευαστή τότε στη
demo θα μπορούμε να χρησιμοποιούμε μόνο αυτόν.
Human h1=new Human(); // βγάζει λάθος
21
Παράδειγμα (2)
 Ορισμός του βασικού κατασκευαστή στη Human
public Human(){
name=“”;
surname=“”;
age=0;
}
 Διαφορετικά τα name και surname σε κάθε νέο Human
είναι null.
Human h1=new Human();
System.out.println(h1.name); //τυπώνει null
22

Η λέξη this
 Χρησιμοποιείται μέσα σε μια μέθοδο για να αναφερθούμε στο
αντικείμενο για το οποίο καλείται η μέθοδος.
 Το this είναι μια αναφορά στο αντικείμενο στο οποίο βρισκόμαστε.
 Αν για παράδειγμα μια μέθοδος της τάξης Human έπρεπε να
επιστρέφει το ίδιο το αντικείμενο:
Human increaseAge(){
age++;
return this;
}
 Human h1=new Human(“Nikos”, “Nikolaou”,20);
 int x=h1.increaseAge().increaseAge().getAge();

23
Επαναχρησιμοποίηση
(σύνθεση+κληρονομικότητα)
public class Employee extends Human{ //κληρονομικότητα
String position;
Address residence; //σύνθεση
void setPosition(String temp){position=temp;}
String getPosition () {return position;}
void setAddress(Address tempad){residence=tempad;}
Address getAddress() {return residence;}
}
… main(..){ Name
Surname Human
Employee e1=new Employee(); Age
Address a1=new Address();
street
a1.street=“Patision”; … number
e1.setAddress(a1); state residence Employee
} postcode
position
24

3ο Μάθημα
 Δυναμικές δομές
 ArrayList
 Πολυμορφισμός - Polymorphism
 Αφηρημένες κλάσεις – Abstract Classes
 Διεπαφές - Interfaces

25
Η κλάση ArrayList
 Ίδιες ιδιότητες με τη Vector
 Προτείνεται από τους δημιουργούς της Java
 ArrayList list = new ArrayList();
 add(Object searchkey), get(int position)

Iterator it = list.iterator();
StringBuffer buf = new StringBuffer();
while (it.hasNext())
buf.append( it.next()) .append( " " );
System.out.println(buf.toString());

26

Άλλες μέθοδοι της ArrayList


void clear(); //αδειάζει τη λίστα
Object clone(); //δημιουργεί αντίγραφο
boolean addAll(Collection c);//προσθέτει όλα τα
//αντικείμενα της c στη λίστα
boolean contains(Object elem); // αναζητά το elem
int indexOf(Object elem); //βρίσκει την θέση 1ης
//εμφάνισης
Object remove(int index); //διαγράφει στοιχείο
Object[] toArray();// επιστρέφει τα στοιχεία της
//λίστας σε πίνακα αντικειμένων

27
H κλάση Arrays της java.util
 Γέμισμα πίνακα με μια τιμή
 int[] a6=new int[5];
 Arrays.fill(a6, 23);
 αντιγραφή
 int[] i = new int[25];
 int[] j = new int[25];
 Arrays.fill(i, 47);
 Arrays.fill(j, 99);
 System.arraycopy(i, 0, j, 0, i.length); //static μέθοδος της Java
 Σύγκριση τιμών
 Arrays.equals(i,j); //ελέγχει ισότητα στα περιεχόμενα των πινάκων
 Ταξινόμηση
 Arrays.sort(a6);

28

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


 Σε ένα array με αντικείμενα Human μπορούμε να βάλουμε και
αντικείμενα Employee (upcasting)
Human[] group=new Human[];
group[0]=new Human();
group[1]=new Employee();
 Στα αντικείμενα αυτά μπορούμε χωρίς κίνδυνο να καλέσουμε
χαρακτηριστικά και μεθόδους της Human.
 Για να καλέσουμε χαρακτηριστικά και μεθόδους της Employee από
κάποιο αντικείμενο πρέπει πρώτα να το μετατρέψουμε σε
Employee (downcasting)
(Employee)group[1].getPosition();
(Employee)group[0].getPosition(); //Class Cast Exception

29
Η λύση - RTTI
 Για τη μέθοδο toString που υπάρχει και στις δύο τάξεις,
το πρόβλημα λύνεται αυτόματα.
 Χωρίς να κάνουμε downcasting.
group[1].toString();
group[0].toString();
 Αν βρει αντικείμενο της τάξης Human καλεί την toString
της Human. Αν βρει αντικείμενο της τάξης Employee
καλεί αυτόματα την αντίστοιχη toString.
 Run Time Type Identification – Καθορισμός τύπου την
ώρα εκτέλεσης

30

Δομές αντικειμένων
 Σε ArrayList και Vector αποθηκεύουμε αντικείμενα
διαφόρων τάξεων που όλες κληρονομούν από την ίδια
βασική τάξη.
 Η βασική τάξη έχει μεθόδους και οι παράγωγες τάξεις τις
υπερβαίνουν
 Όταν ανακτούμε ένα αντικείμενο από τη δομή το
μετατρέπουμε στη βασική τάξη και καλούμε τις μεθόδους
του.
 Ανάλογα με τον τύπο του αντικειμένου παίρνουμε και
άλλη συμπεριφορά - Πολυμορφισμός

31
Αφηρημένες τάξεις – abstract
classes
 Μια abstract τάξη βρίσκεται στην κορυφή μιας
ιεραρχίας τάξεων και συγκεντρώνει λειτουργίες.
 Οι υπόλοιπες τάξεις της ιεραρχίας υλοποιούν τις
λειτουργίες αυτές με το δικό τους τρόπο
 Δεν μπορούμε να φτιάξουμε αντικείμενα abstract
τάξεων μπορούμε όμως να έχουμε αναφορές σε
abstract τάξεις.

32

Interface
 To interface είναι μια συλλογή από “υπογραφές“
μεθόδων (δεν υπάρχουν στιγμιότυπα, ούτε υλοποιήσεις
των μεθόδων)
 Περιγράφει πρωτόκολλο/συμπεριφορά αλλά όχι
υλοποίηση
 Όλες οι μέθοδοι του είναι public και abstract (ποτέ static)
 Όλες οι μεταβλητές είναι static και final
 Μια κλάση υλοποιεί (implements) ένα interface

33
Κληρονομικότητα - Παράδειγμα

34

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


Employee (abstract)
- private
-residence : Address
-position : String # protected
#bonus : double + public
+(abstract) getSalary() : double
+getResidence() : Address
+setResidence(in getResidence : Address) : void
+getPosition() : String
+setPosition(in position : String) : void
+worksFor(in manager : Manager) : void

Manager PieceWorker HourlyWorker


-weeklySalary : double -wagePerPiece : double -wage : double
+Manager() -quantity : int -hours : int
+getSalary() : double +PieceWorker() +HourlyWorker()
+getSalary() : double +getSalary() : double
35
4ο Μάθημα
 Ρεύματα
 Προκαθορισμένα ρεύματα εισόδου/εξόδου
 Η τάξη File - Οργάνωση αρχείων
 Ρεύματα bytes, χαρακτήρων
 Αρχεία κειμένου
 Ρεύματα εισόδου αρχείων
 Ρεύματα εξόδου αρχείων
 Διαχείριση λαθών – Εξαιρέσεις
 Δημιουργία
 Ανίχνευση
 Διαχείριση
 Βασικοί τύποι εξαιρέσεων
 Δημιουργία τύπων εξαίρεσης

36

H κλάση File
 Είναι η βασική κλάση για αρχεία και φακέλους
 Μέθοδοι της File
 exists: ελέγχει αν υπάρχει το αρχείο
 canRead: ελέγχει αν μπορούμε να διαβάσουμε από το αρχείο
 canWrite: ελέγχει αν μπορούμε να γράψουμε στο αρχείο
 delete: διαγράφει το αρχείο και επιστρέφει true (αν πετύχει)
 length: επιστρέφει το μέγεθος του αρχείου σε bytes
 getName: επιστρέφει το όνομα του αρχείου (μόνο)
 getPath: επιστρέφει το πλήρες μονοπάτι του αρχείου

File numFile = new File(“numbers.txt”);


if (numFile.exists())
System.out.println(numfile.length());

37
Σχετικές κλάσεις
 Η FileInputStream και η FileOutputStream
έχουν κατασκευαστές που παίρνουν ως όρισμα ένα
αντικείμενο File ή το όνομα του αρχείου ως String
PrintWriter smileyOutStream = new
PrintWriter(new
FileOutputStream(“smiley.txt”));
File smileyFile = new File(“smiley.txt”);
if (smileyFile.canWrite())
PrintWriter smileyOutStream = new
PrintWriter(new
FileOutputStream(smileyFile));

38

Συνδυασμός ρευμάτων bytes


float, String, κλπ.

DataInputStream
bytes

FilterInputStream ή
BufferedInputStream

bytes

FileInputStream
InputStream

bytes
Αρχείο
39
Διάβασμα από αρχεία
 Η τάξη File (στο πακέτο java.io.*) αντιπροσωπεύει:
 Ένα αρχείο:
File arxeio = new File("c:\\1.txt");
 Ένα κατάλογο:
File katalogos = new File(".");
String path=katalogos.getAbsolutePath();
File[] files=katalogos.listFiles();
 Η τάξη FileReader (FileWriter) δημιουργεί ένα ρεύμα
εισόδου (εξόδου) από αρχείο:
 FileReader arxeio = new FileReader("c:\\1.txt"));

40

Ανάγνωση - Εγγραφή
 Ανάγνωση: Όπως και με το πληκτρολόγιο συνδέουμε το
πρόγραμμά μας με το αρχείο με έναν BufferedReader
BufferedReader eisodos = new BufferedReader(new
FileReader("c:\\1.txt"));
 Εγγραφή: Συνδέουμε το πρόγραμμά μας με το αρχείο με
ένα BufferedWriter
PrintWriter exodos =new PrintWriter(new BufferedWriter(new
FileWriter(“c:\\copy.txt")));
String s;
while((s = eisodos.readLine()) != null )
exodos.println(lineCount++ + ": " + s);
exodos.close();

41
Αντιμετώπιση λαθών
 Υπάρχουν λάθη χρόνου εκτέλεσης (run time errors) τα
οποία δεν ανιχνεύονται στη μεταγλώττιση.
 Αναζήτηση στοιχείου έξω από τα όρια ενός πίνακα
 Άνοιγμα αρχείου που δεν υπάρχει
 Κλήση αναφοράς σε null
 Θα πρέπει να αντιμετωπίζονται όταν το πρόγραμμα
εκτελείται
 Ο κώδικας που δημιουργεί κάποιο λάθος μεταδίδει
πληροφορία στον κώδικα που καλείται να το
αντιμετωπίσει. Αυτό γίνεται με τις Εξαιρέσεις –
Exceptions
 Σηματοδοτούν εμφάνιση συνθηκών ιδιαίτερης
μεταχείρισης και διακόπτουν τη συνήθη ροή του κώδικα
42

Αναλυτικά με τις εξαιρέσεις


 Όταν εμφανίζεται μία εξαίρεση σταματά η εκτέλεση της μεθόδου
 Δεν υπάρχει η απαραίτητη πληροφορία στο scope της μεθόδου
 Ανεβαίνουμε και αντιμετωπίζουμε το πρόβλημα σε κάποιο
«υψηλότερο» scope. «Ρίχνουμε» μια εξαίρεση (throw)
 Ένα αντικείμενο εξαίρεσης (Exception object) δημιουργείται στον σωρο
(heap) με χρήση του τελεστή new όπως κάθε άλλο Java object
 Διακόπτεται η εκτέλεση της μεθόδου και κρατιέται μια αναφορά στο
Exception object σε κάποια περιοχή της μνήμης
 Αναλαμβάνει ο μηχανισμός διαχείρισης της εξαίρεσης (Exception
handling mechanism) που πρέπει να βρει το κατάλληλο μέρος για να
συνεχίσει να εκτελεί κώδικα

43
Αντικείμενα εξαιρέσεων
 To keyword throw προκαλεί τα ακόλουθα γεγονότα:
 εκτελεί την έκφραση new και δημιουργεί ένα αντικείμενο που δεν
θα υπήρχε κανονικά
 Το αντικείμενο αυτό επιστρέφεται στην ουσία από την μέθοδο ή
το block μέσα στο οποίο δημιουργήθηκε μολονότι η μέθοδος δεν
έχει δηλωθεί να επιστρέφει παραμέτρους αυτού του τύπου και τα
blocks δεν έχουν φυσικά παραμέτρους που να επιστρέφουν
 Το πρόγραμμα βγαίνει από τη μέθοδο ή το block.
 Τα αντικείμενα exception που «ρίχνονται» μπορεί να
είναι διάφορων τύπων, ανάλογα το είδος της εξαίρεσης
 Κάθε αντικείμενο κωδικοποιεί στα πεδία του όλη την
πληροφορία που αφορά την εξαίρεση, ώστε ο
μηχανισμός διαχείρισης εξαιρέσεων στα ψηλότερα
επίπεδα να μπορεί να πάρει τις κατάλληλες αποφάσεις
44

Σύλληψη εξαίρεσης
 Όταν ρίχνουμε μία εξαίρεση πρέπει στα υψηλότερα
επίπεδα κάποιο μπλοκ κώδικα να την ανιχνεύσει και να
την διαχειριστεί.
 Προστατευόμενη περιοχή είναι ένα κομμάτι κώδικα
που μπορεί να ρίξει εξαιρέσεις και που ακολουθείται από
κώδικα που διαχειρίζεται αυτές τις εξαιρέσεις.
 Μια προστατευόμενη περιοχή μπορεί να ανιχνεύσει ένα
ή περισσότερους τύπους εξαιρέσεων και
 να τους διαχειριστεί ή
 να τους ρίξει ακόμη πιο πάνω (με νέο throw)

45
Προστατευόμενη περιοχή - try
 Ένα τέτοιο μπλοκ ονομάζεται try block αφού εκεί
δοκιμάζουμε να κάνουμε κλήσεις σε διάφορες
«επικίνδυνες μεθόδους»
 Το try block είναι ένα κανονικό scoper που περικλείεται
από την κωδική λέξη try
try {
// κώδικας που παράγει εξαιρέσεις
}
 Προστασία από εξαιρέσεις: Bάζουμε όλον τον
«επικίνδυνο» κώδικα σε ένα try block και πιάνουμε όλες
τις εξαιρέσεις στο ίδιο μέρος.

46

Διαχειριστές εξαιρέσεων - catch


 Κάθε εξαίρεση που ανιχνεύεται μέσα στο try καταλήγει στον
αντίστοιχο κώδικα (catch block) που θα την εξυπηρετήσει. Τα catch
ελέγχονται διαδοχικά.
 Παράδειγμα:
try {
// κώδικας που παράγει εξαιρέσεις
} catch (type1 id1) {
// χειρισμός εξαιρέσεων τύπου 1
} catch (type2 id2) {
// χειρισμός εξαιρέσεων τύπου 2
} catch (type3 id3) {
// χειρισμός εξαιρέσεων τύπου 3
}
 Αν πολλές μέθοδοι στο try ρίχνουν τον ίδιο τύπο εξαίρεσης, τότε
χρειαζόμαστε μόνο έναν exception handler για αυτόν τον τύπο.

47
Παράδειγμα – έλεγχος εισόδου (2)
 Μπορούμε να χρησιμοποιήσουμε δική μας εξαίρεση;
 Στο αρχείο MySpecialException.java
public class MySpecialException extends Exception{

}
 Οπότε
public double readDouble() throws MySpecialException{
Scanner in =new Scanner(System.in);
if(in.hasNextDouble()){
return in.nextDouble();
}
else throw new MySpecialException();
}

48

Παράδειγμα
 Μη διαχείριση σφάλματος εισόδου
public double sumNumbers() throws MySpecialException{
double sum=0;
sum+=readDouble();
return sum;
}
public static void main(String[] args) throws MySpecialException{
Main m=new Main();
double z=m.sumNumbers();
System.out.println("Sum is:"+z);
}

 Έτσι αποφεύγουμε να χειριστούμε την εξαίρεση

49
Παράδειγμα
 Διαχείριση σφάλματος εισόδου
public double sumNumbers(){
double sum=0;
try{
sum+=readDouble();
}
catch(MySpecialException ex){ //θα συμβεί αν ο χρήστης δεν δώσει αριθμό
System.err.println(ex.toString()); //τυπώνει το όνομα της κλάσης εξαίρεσης
}
catch(Exception ex){ //θα συμβεί σε οποιαδήποτε άλλη περίπτωση λάθους
System.err.println(ex.getMessage()); //τυπώνει το μήνυμα της εξαίρεσης
}
return sum;
}
 Η MySpecialException είναι ειδικότερη από την Exception

50

Κατασκευαστές
public Human(){
name=“Unknown”; surname=“Unknown”; age=0;
System.out.println(“A new Human has been created”);
}
public Address(){
street=“Unknown”; number=0; city=“Unknown”;
System.out.println(“A blank Address has been created”);
}
public Employee(){
residence=new Address();
position=“Unemployed”;
System.out.println(“A new Employee has been created”);
}
 Με ποια σειρά καλούνται οι κατασκευαστές;
51
Δημιουργία αντικειμένων
Address ad1=new Address();
A blank Address has been created
Human h1=new Human();
A new Human has been created
Employee e1= new Employee();
A new Human has been created
A blank Address has been created
A new Employee has been created
 Καλείται αυτόματα ο βασικός κατασκευαστής της
Human

52

Αν η Human δεν έχει βασικό κατασκευαστή;


public Human(String name,String surname, int age){
this.name=name; this.surname=surname; this.age=age;
System.out.println(name+” “+surname+“ has been created”);
}
 Πρέπει να δηλώσουμε στον κατασκευαστή της Employee
ποιο συγκεκριμένο κατασκευαστή της Human θα καλέσει
 Αυτό γίνεται με τη λέξη super.
public Employee(){
super(“Unknown”,”Unknown”,0);
residence=new Address();
position=“Unemployed”;
System.out.println(“A new Employee has been created”);
}
53
Υπέρβαση μεθόδων
 Η getCompleteData της Human
String getCompleteData(){
String data=new String();
data=name+“ “+surname+” “+age+” years old”;
return data;
}
 Λόγω κληρονομικότητας μπορούμε να την
καλέσουμε για έναν Employee, αλλά δε θα
έχουμε όλες τις πληροφορίες γι’αυτόν.
54

Υπέρβαση μεθόδων
 Υπερβαίνουμε τη μέθοδο, δηλώνοντάς την ΚΑΙ στην
Employee με το ίδιο όνομα
 Καλούμε στο σώμα της τη μέθοδο της employee με τη
δήλωση super
class Employee{
...
String getCompleteData(){
String data=new String();
data=super.getCompleteData() + " "+
residence.getCompleteAddress()+" position:"+
position;
return data;
}
}
55
7ο Μάθημα
 Γραφικά περιβάλλοντα (GUI)
 Abstract Windowing Toolkit (AWT)
 Containers
 Components
 Layout managers
 (Listeners)
 Swing
 Αρχιτεκτονική Model-View-Controller
 Διάφορα στοιχεία του Swing
 Παράθυρα και μενού
 Περιγράμματα
 Τοποθέτηση στοιχείων στο παράθυρο
 Διαχειριστές τοποθέτησης
 Βασικά interfaces
 Τάξεις

Τα μέρη ενός γραφικού περιβάλλοντος


GUI Σύνθεση τάξεων

JFrame JFrame
JPanel containers

JPanel
JButton

JButton JLabel
JLabel

components
Με ποια σειρά φτιάχνουμε το
GUI Listener
 Δημιουργούμε
 Το JFrame
 Το JPanel JLabel JButton
 Τα Components (JButton, JLabel)
 To Listener για το JButton
 Προσθέτουμε (μέθοδος add) JPanel
 Τον Listener στo JButton
 Τα components στο Jpanel
 To JPanel στο JFrame
 Εμφανίζουμε
 Το JFrame (μέθοδος show) JFrame

8ο Μάθημα
 Στοιχεία
 Περιοχές κειμένου
 Κουμπιά
 Λίστες επιλογών
 Παράθυρα διαλόγου
 Παράθυρα επιβεβαίωσης
 Παράθυρο επιλογής αρχείου
 Παράθυρο επιλογής χρώματος
Στοιχεία του Swing

Λίστες επιλογών
 JComboBox: Περιέχει ένα πίνακα από επιλογές, εμφανίζει στο
χρήστη μόνο μία και επιτρέπει μονές ή πολλαπλές επιλογές.
String [] items = { "uno", "due", "tre", "quattro", "cinque", "sei", "sette",
"otto", "nove", "deici", "undici" };
JComboBox comboBox = new JComboBox(items);
comboBox.addItem("dodici");
comboBox.getSelectedItem() //επιστρέφει Object
comboBox.getSelectedObjects() //επιστρέφει Object[]
 JList: Περιέχει ένα πίνακα από επιλογές, εμφανίζει στο χρήστη
ορισμένες από αυτές (ανάλογα με το ύψος της) και επιτρέπει μονές
ή πολλαπλές επιλογές.
JList list = new JList(comboBox.getModel( ));
list.getSelectedValues() //επιστρέφει Object[]
 Mοιράζονται το ίδιο μοντέλο δεδομένων
Μοντέλα Δεδομένων για Λίστες
dlm = new DefaultListModel();
dlm.addElement(new Human("George", "Brown", 22, "6th Avenue"));
dlm.addElement(new Human("Mary", "Jones", 18, "5th Avenue"));
dlm.addElement(new Human("Bill", "Murray", 19, "Madison Avenue"));
students = new JList(dlm);
this.getContentPane().add(students);
this.getContentPane().add(clearButton);
this.getContentPane().add(copyButton);

- Φαίνεται ότι επιστρέφει η toString()


- Επιστρέφει όλο το Object
Object[] selected=students.getSelectedValues();
for (int i=0;i<selected.length;i++)
Human h=(Human)selected[i];

Το παράθυρο JDialog
 Συμπεριφέρεται όπως και το JFrame
JDialog dialog = new JDialog(myFrame, "Dialog Frame");
JLabel label = new JLabel("This is a message“);
dialog.getContentPane().add(label);
dialog.setVisible(true);

 Μπορεί να μπλοκάρει τη συνέχιση του


προγράμματος (modal) ή όχι (non-modal)
JDialog dialog1 = new JDialog(myFrame, "This is modal", true);
JDialog dialog2 = new JDialog(myFrame, "This is non modal", false);
9ο Μάθημα
 Συλλογές και ενέργειες
 ArrayList
 Αναζήτηση συγκεκριμένου στοιχείου
 Αναζήτηση ελαχίστου/μεγίστου
 Συνάθροιση

 Πίνακας
 Εισαγωγή
 Εισαγωγή με έλεγχο διπλοτύπων
64

Σύγκριση: Η μέθοδος equals


 Για να δουλέψουν οι προηγούμενοι μέθοδοι για λίστες με αντικείμενα
δικών μας κλάσεων πρέπει στις κλάσεις μας να έχουμε μια μέθοδο
equals π.χ.
public boolean equals(Object o){
Department d=(Department)o; // πιθανό να παράγει
//ClassCastException
if (this.id==d.getId() && this.name.equals(d.getName()) &&
this.numStudents==d.getNumStudents())
return true;
else
return false;
}
65
Ταξινόμηση
 Με ποιο τρόπο μπορώ να ταξινομήσω τα στοιχεία ενός πίνακα ή μιας
λίστας; BubbleSort:
public void bubbleSort(int[] unsortedArray, int length) {
int temp, counter, index;
for(counter=0; counter<length-1; counter++) {
for(index=0; index<length-1-counter; index++) {
if(unsortedArray[index] > unsortedArray[index+1]) {
temp = unsortedArray[index];
unsortedArray[index] = unsortedArray[index+1];
unsortedArray[index+1] = temp;
}
}
}
}
66

Διάταξη
 Η διάταξη στους ακεραίους είναι δεδομένη
 Τι γίνεται όμως με τις δικές μας κλάσεις;
 Πώς μπορούμε να ορίσουμε διάταξη στα αντικείμενά
τους;

Comparable
public interface Comparable
{
int compareTo(Object o);
}
Department

67
public class Department implements Comparator{

public int compareTo(Object o){
Department d=(Department)o; // πιθανό να παράγει
//ClassCastException
if (this.numStudents>d.getNumStudents())
return 1;
else if (this.numStudents<d.getNumStudents())
return -1;
else
return 0;
}
}
68

Ταξινόμηση

Collections.sort(allDeps);

Ταξινομεί τα τμήματα με βάση τον αριθμό


σπουδαστών που έχουν
Χρησιμοποιεί την QuickSort

69
Διεπαφές – υλοποιήσεις και παρελθόν
Διεπαφή Υλοποιήσεις Παλιότερες
υλοποιήσεις
Set HashSet TreeSet

List ArrayList LinkedList Vector


Stack

Map HashMap TreeMap HashTable


Properties

Μια τάξη υλοποίησης μπορεί να μην υλοποιεί μια συγκεκριμένη μέθοδο


του interface (κάποιες μέθοδοι είναι προεραιτικές)
Στην περίπτωση αυτή παράγει UnsupportedOperationException

Υλοποιήσεις
Υλοποιήσεις

 WeakHashMap
είναι μια
υλοποίηση του
Map που καλεί
τον garbage
collector όταν
ένα κλειδί δε
χρησιμοπείται
πλέον

11ο Μάθημα
 Πολυνηματικές εφαρμογές
 Ορισμοί
 Έλεγχος νήματος
 Συγχρονισμός νημάτων
Threads - Νήματα
 Τα threads επιτρέπουν εργασίες να τρέχουν παράλληλα
με την κύρια εφαρμογή
 Είναι διεργασίες που τρέχουν στον ίδιο χώρο
διευθύνσεων: μοιράζονται τις μεταβλητές στιγμιοτύπων,
αλλά διατηρούν και τοπικές μεταβλητές
 Χρησιμοποιούνται από το JVM σε συγκεκριμένες
περιπτώσεις
 Όταν φορτώνουμε μια εικόνα ή ένα ήχο μέσα από ένα applet.
 Όταν καλούμε την update του αντικειμένου graphics
 Μπορούμε να δηλώσουμε και να χρησιμοποιήσουμε
δικά μας νήματα.

Τρόποι δήλωσης (1/2)


 Επέκταση της Thread
public class HelloThread extends Thread {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new HelloThread()).start();
}
}
Τρόποι δήλωσης (2/2)
 Υλοποίηση της Runnable
public class HelloRunnable implements
Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}

Μέθοδοι
 run(): το βασικό σύνολο εντολών του νήματος.
Ενεργοποιείται με το start()
 static void sleep(milliseconds): σταματά
προσωρινά την εκτέλεση του νήματος
 void interrupt(): διακόπτει το νήμα
 boolean interrupted(): ελέγχει αν το νήμα
εξακολουθεί να είναι σταματημένο ή
ξαναξεκίνησε
 final void otherThread.join(): διακόπτει το τρέχον
νήμα μέχρι να τελειώσει το otherThread
12ο μάθημα
 Επικοινωνία με δικτυακές πηγές
 Ανάγνωση από πηγή

BufferedReader in = new BufferedReader( new


InputStreamReader( target.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();

Σύνδεση με πηγή
try {
URL hua = new URL("http://www.hua.gr/");
URLConnection huaConnection = hua.openConnection();
huaConnection.connect();
BufferedReader in = new BufferedReader( new InputStreamReader(
huaConnection.getInputStream()));

}
catch (MalformedURLException e) {
// new URL() failed . . .
}
catch (IOException e) {
// openConnection() failed . . .
}
Γράφοντας σε μια διεύθυνση
 Δημιουργία του URL
URL url = new URL("http://www.hua.gr");
 Ανάκτηση του URLConnection
URLConnection connection = url.openConnection();
 Ενεργοποίηση εξόδου
connection.setDoOutput(true);
 Δημιουργία ρεύματος εξόδου
OutputStreamWriter out = new OutputStreamWriter(
connection.getOutputStream());
 Πέρασμα παραμέτρων
out.write("id=25");
 Κλείσιμο του ρεύματος
out.close();

You might also like