Professional Documents
Culture Documents
Προγραμματισμός ΙΙ (Java) Ιωάννης Βιόλος Χαροκόπειο Πανεπιστήμιο
Προγραμματισμός ΙΙ (Java) Ιωάννης Βιόλος Χαροκόπειο Πανεπιστήμιο
(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
}
System.out.println(“Hi!”); Μέθοδοι
void incr_age()
{
age = age +1;
}
}
Κλήση μεθόδου = Αποστολή Μηνύματος
15
Γνωρίσματα - Δεδομένα
Τα δεδομένα μπορεί να είναι απλού
τύπου: int, boolean, double, float, long
κλπ.
Μπορεί να είναι σύνθετου τύπου. Δηλαδή
αντικείμενα μιας άλλης κλάσης: String,
Date, Human
Λειτουργίες - Μέθοδοι
Οι μέθοδοι περιγράφουν τις λειτουργίες της κλάσης πάνω στα
δεδομένα. Είναι ο τρόπος με τον οποίο επικοινωνούν τα αντικείμενα
διαφόρων κλάσεων μεταξύ τους.
Μία μέθοδος στη Java έχει:
Όνομα
Τύπο επιστροφής
Λίστα ορισμάτων
Το σώμα της μεθόδου πρέπει στο τέλος να επιστρέφει τιμή με
χρήση της εντολής return
Αν ο τύπος επιστροφής είναι void δεν χρειάζεται return.
returnType methodName( /* λίστα ορισμάτων */ ) {
/* σώμα μεθόδου */
return …;
}
17
Δημιουργία κλάσης Human
Τα πάντα στην Java είναι αντικείμενα κάποιας κλάσης.
Για το λόγο αυτό σε κάθε μας πρόγραμμα χρειάζεται να
ορίσουμε τουλάχιστον μία κλάση. Η κλάση αυτή θα έχει
το ίδιο όνομα με το αρχείο που θα την αποθηκεύσουμε.
π.χ. Η κλάση Human θα πρέπει να αποθηκευθεί στο
αρχείο Human.java
Kλήση του Java compiler
javacHuman.java
παράγει ένα αρχείο Human.class
18
19
Αντικείμενο = Χαρακτηριστικά + Μέθοδοι
Για να χρησιμοποιήσουμε ένα
αντικείμενο πρέπει πρώτα να Human john = new Human();
το δημιουργήσουμε // Δημιουργείται ένας human
Για να στείλουμε μήνυμα σε
ένα αντικείμενο, δίνουμε το john.speak();
όνομα του αντικειμένου μία
john.age=0;
τελεία και το όνομα της
διαθέσιμης λειτουργίας Human
Παρόμοια δίνουμε τιμή στα age
χαρακτηριστικά ενός alive
αντικειμένου born()
To σύνολο των διαθέσιμων speak()
λειτουργιών ενός αντικειμένου incr_age()
αποτελεί τη διεπαφή του με τα
υπόλοιπα αντικείμενα
20
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
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
30
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
33
Εμβέλεια μεταβλητών/αντικειμένων
Κάθε μεταβλητή έχει ισχύ εντός του μπλοκ στο οποίο ορίζεται και σε κάθε
μπλοκ που υπάρχει μέσα σε αυτό. {
{
int x = 12;
int x = 12;
/* μόνο το x υπάρχει */ {
{ int x = 96; /* Δεν επιτρέπεται
int q = 96;
/* υπάρχουν τα x & q */ γιατί έχει ήδη οριστεί το x*/
} }
q=150 /* δεν επιτρέπεται }
γιατί μόνο το x υπάρχει */
/* εκτός της εμβέλειας του q */
}
34
attribute
method
return type
36
37
Θεμελιώδεις περικλείουσες κλάσεις
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, …)
{
…
}
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;
} 63
2. Μέθοδοι
Περιεχόμενα
Μέθοδοι
Πέρασμα αντικειμένου σε μέθοδο
Υπερφόρτωση μεθόδων
Μέθοδοι κατασκευαστές
Υπερφόρτωση κατασκευαστών
Επαναχρησιμοποίηση κώδικα
Σύνθεση και κληρονομικότητα
Πολυμορφισμός
Αφηρημένες κλάσεις
Διεπαφές
2
Μέθοδοι
Δομή μεθόδου
πρόσβαση τύποςΕπιστροφής όνομαΜεθόδου (τυπος1 παράμετρος1, …)
{
…
}
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
15
16
Υπερφόρτωση μεθόδου
Υπερφόρτωση μεθόδων
Σε μια τάξη μπορούμε να ξαναχρησιμοποιήσουμε το ίδιο
όνομα για μεθόδους που έχουν ελαφρώς διαφορετική
συμπεριφορά
Διαφορετικούς τύπους ορισμάτων
Διαφορετικό πλήθος ορισμάτων
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;}
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
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;
}
34
Final κλάσεις
Οι “final” κλάσεις δεν κληρονομούνται
Ολοι οι μέθοδοι της γίνονται έμμεσα τελικές
Οταν θέλουμε να είμαστε σίγουροι ότι κανείς δεν θα
τις κληρονομήσει
35
Παράδειγμα (1)
Employee (abstract)
-residence : Address
-position : String
+getSalary (abstract)()
Διαχείριση
αντικειμένων
Κατασκευαστές
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();
}
}
class Employee{…
protected void finalize(){
super.finalize();
System.out.println("The employee has been cleared");
}…}
Κληρονομικότητα - Παράδειγμα
Δομές και κληρονομικότητα
Σε ένα 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 αποθηκεύουμε αντικείμενα
διαφόρων τάξεων που όλες κληρονομούν από την ίδια
βασική τάξη.
Η βασική τάξη έχει μεθόδους και οι παράγωγες τάξεις τις
υπερβαίνουν
Όταν ανακτούμε ένα αντικείμενο από τη δομή το
μετατρέπουμε στη βασική τάξη και καλούμε τις μεθόδους
του.
Ανάλογα με τον τύπο του αντικειμένου παίρνουμε και
άλλη συμπεριφορά - Πολυμορφισμός
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
61
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
Πίνακες
Προκαθορισμένο μέγεθος
Συνεχείς θέσεις
Πίνακες τιμών
Αρχικοποιούνται σε 0 ή false
int[] a=new int[10];
boolean[] b=new boolean[10];
Πίνακες αντικειμένων
Αρχικοποιούνται σε null
String[] c= new String[10]
2
Περιορισμοί των πινάκων
Οι εισαγωγές και οι διαγραφές σε κάποια θέση «κοστίζουν»
Πρέπει να μετακινηθούν όλα τα υπόλοιπα στοιχεία για να καλύψουν το
κενό ή να δημιουργήσουν χώρο.
Αν γεμίσουν οι θέσεις θα πρέπει να αντιγράψουμε όλα τα στοιχεία σε
νέο, μεγαλύτερο πίνακα.
Η λογική διαδοχή των θέσεων του πίνακα ταυτίζεται με την
πραγματική (ο πίνακας αποθηκεύεται σε συνεχόμενες θέσεις
μνήμης)
Θέλουμε να αποσυνδέσουμε τη λογική από την πραγματική
διαδοχή θέσεων.
Έτσι θα έχουμε διαγραφές και εισαγωγές χωρίς μετακίνηση
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
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
Collections.sort(allDeps);
15
17
18
Προσθήκη package στο Netbeans
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
• 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
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
}
Οπότε
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
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
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
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;}}
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));
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
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 smileyFile = new File(“smiley.txt”);
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()
Παράδειγμα
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() //επιστρέφει τη θέση του δείκτη
30
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
37
Ο τελεστής <>
diamond operator
Αντί για
HashMap<String, Stack<String>> map =
new HashMap<String, Stack<String>>();
Μπορώ να γράψω:
HashMap<String, Stack<String>> map =
new HashMap<>;
38
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. Διαχείριση δεδομένων
Java και ΒΔ
Για να επικοινωνήσει η εφαρμογή μας με μια βάση
δεδομένων θα πρέπει:
Να συνδεθούμε με το ΣΔΒΔ (όπως θα ανοίγαμε ένα ρεύμα
εισόδου/εξόδου προς ένα αρχείο)
Να συνδεθούμε με τη συγκεκριμένη ΒΔ (αν το σύστημα διατηρεί
ταυτόχρονα πολλές ΒΔ).
Να υποβάλλουμε ερωτήσεις SQL και
Να διαχειριστούμε τη λίστα των εγγραφών που παίρνουμε ως
απάντηση
ερωτήσεις SQL
Java Application Σύνδεση ΒΔ
λίστα εγγραφών
Java Database Connectivity
Το JDBC επιτρέπει στις εφαρμογές Java να
συνδεθούν και να "ρωτήσουν" μια ΒΔ.
Οι ερωτήσεις υποβάλλονται σε μια κοινή μορφή
και μεταφράζονται στη μορφή που υποστηρίζει
κάθε ΣΔΒΔ.
Δεν υποστηρίζει ειδικές λειτουργίες του κάθε
ΣΔΒΔ
Το πακέτο java.sql περιέχει τις τάξεις για το JDBC 1.0
Το πακέτο javax.sql υποστηρίζει τα JDBC 2.0 και 3.0
ODBC process
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 οδηγού με τη βάση.
• Πολύ γρήγορη πρόσβαση
network
JDBC Driver Native
JDBC API JDBC Driver Server Driver
Intermediate data
access server:
Gateway for multiple
database server
network
JDBC API JDBC Driver
O διαχειριστής των οδηγών
Μια εφαρμογή μιλά ταυτόχρονα
σε πολλές ΒΔ
Με διαφορετικό τύπο οδηγού
στην κάθε μια
Για το λόγο αυτό υπάρχει ο
JDBC Driver Manager
O DriverManager είναι μια τάξη
που περιέχεται στο βασικό
πακέτο java.sql
Έχει τη μέθοδο getConnection
για να δημιουργούμε μια
σύνδεση σε μια ΒΔ
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
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
jdbc:oracle:thin:@//10.100.51.123:1521:orcl
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());
//...
Τι προσφέρουν
− Διαφανή υποστήριξη «παραμενόντων
αντικειμένων» (transparent persistence)
− Caching
− Διαχείριση δοσοληψιών (Transaction
management)
Που θα βρω πληροφορίες
− https://docs.oracle.com/javaee/7/tutorial/partp
ersist.htm#BNBPY
@Id
@GeneratedValue
private Integer id;
private String title;
private String subtitle;
@ManyToMany
private Set<Author> authors = new HashSet<Author>();
public Book() {
}
Η κλάση 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();
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));
3
Διαγραφή μέσω αναζήτησης (ArrayList)
Εισαγωγή σε πίνακα
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 της
λίστας και μας το επιστρέφει
Διάταξη
Η διάταξη στους ακεραίους είναι δεδομένη
Τι γίνεται όμως με τις δικές μας κλάσεις;
Πώς μπορούμε να ορίσουμε διάταξη στα αντικείμενά
τους;
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);
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
Collections Framework
Πλαίσιο γενικότερα
Ως πλαίσιο ορίζεται το σύνολο των τάξεων που καθορίζει
το σχεδιασμό λύσης για μια οικογένεια προβλημάτων
Περιλαμβάνει κάποιες βασικές τάξεις αλλά μπορεί να
επεκταθεί
Καθορίζει την αρχιτεκτονική μιας εφαρμογής: τις τάξεις,
τα αντικείμενα, τις μεταξύ τους συνεργασίες και τον
έλεγχο των νηματικών διεργασιών
Ταυτόχρονα προσφέρει και έτοιμες υλοποιήσεις που
μπορούμε να χρησιμοποιήσουμε
Πλαίσιο διαχείρισης συλλογών
Το πρόβλημα είναι η διαχείριση συλλογών
αντικειμένων
Το πλαίσιο καθορίζει τις τάξεις για τους
διάφορους τύπους συλλογών και τις μεθόδους
που απαιτεί η διαχείριση μιας συλλογής
Γενικότερα μια συλλογή (collection) είναι ένα
αντικείμενο που περιλαμβάνει περισσότερα
αντικείμενα
Σε μια συλλογή θέλουμε να αποθηκεύουμε, να
ανακτούμε και να διαχειριζόμαστε αντικείμενα.
Συγκεκριμένα
Να προσθέτουμε ένα αντικείμενο
Να βγάζουμε ένα αντικείμενο
Να εντοπίζουμε ένα αντικείμενο
Αν υπάρχει συλλογή
Πόσες φορές
Αν κάποιο ισοδύναμό του υπάρχει στη συλλογή
Να δίνουμε κάποια τιμή κλειδί και να ανακτούμε
το αντικείμενο
Να διασχίζουμε όλη τη συλλογή
Πώς υλοποιούνται όλα αυτά;
Java Collections Framework
Το πλαίσιο συλλογών της Java περιλαμβάνει
βασικές συλλογές αντικειμένων (object
containers)
Διεπαφές: αφηρημένοι τύποι που αντιστοιχούν σε
τύπους συλλογών (interfaces και abstract classes)
Υλοποιήσεις: των προηγούμενων διεπαφών
Αλγορίθμους: μεθόδους που κάνουν συγκεκριμένες
λειτουργίες όπως αναζήτηση, ταξινόμηση κλπ σε
αντικείμενα της συλλογής
Συλλογές με ευρετήρια
Το Map επιτρέπει την εισαγωγή στοιχείων με
ταυτόχρονη εισαγωγή ενός κλειδιού.
Το ζεύγος key-value συνδέει το σύνολο των κλειδιών
με τη συλλογή των τιμών.
Αυτό σημαίνει ότι τα κλειδιά δεν επιτρέπουν
διπλοεγγραφές ενώ οι τιμές επιτρέπουν
Η διάσχιση του map γίνεται με διάσχιση του key-set
και ανάκτηση κάθε value.
Βασικές υλοποιήσεις
Μια 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
Διεπαφή 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
Υλοποιήσεις
Υλοποιήσεις
WeakHashMap
είναι μια
υλοποίηση του
Map που καλεί
τον garbage
collector όταν
ένα κλειδί δε
χρησιμοπείται
πλέον
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]);}
}
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
Τάξεις
Περιεχόμενα
Στοιχεία
Περιοχές κειμένου
Κουμπιά
Λίστες επιλογών
Παράθυρα διαλόγου
Παράθυρα επιβεβαίωσης
Παράθυρο επιλογής αρχείου
Παράθυρο επιλογής χρώματος
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
Button
Checkbox CheckboxGroup
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);
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);
Ενδεικτικά layouts
FlowLayout GridLayout BorderLayout
n
CardLayout GridBagLayout
Εσωτερικά παράθυρα
Η τάξη 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: JPanelFlowLayout
contentPane: JPanel
BorderLayout
CENTER t: JTextArea
Συνδυασμός
JFrame f = new JFrame(“Frame1”);
BUTTONS
MENUS
Άλλα COMPONENTS
JComboBox JColorChooser
ImageIcon
JInternalFrame
JDialog
JFileChooser
Άλλα COMPONENTS
JScrollBar
JLabel JList
JSplitPane
JTabbedPane
Άλλα COMPONENTS
JTable
JTextArea
JTextField
JToolBar
JToolTip
JTree
JComponent
Κάθε JComponent είναι αντικείμενο μιας τάξης.
Συνεπώς:
Έχει κατάσταση (ιδιότητες)
(π.χ. ενεργό, ορατό, επιλεγμένο, JButton
θέση,κείμενο, εικόνα κλπ.)
Έχει μεθόδους
(π.χ. Όρισε κείμενο/εικόνα, φόντο)
Ανταποκρίνεται σε γεγονότα
(π.χ. mouseClicked, mouseEntered, keyTyped, componentMoved)
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);
Παράδειγμα
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);
Πίνακες - 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);
Μελέτη Περίπτωσης
Μελέτη Περίπτωσης
Παράθυρα διαλόγου
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);
Περιεχόμενα
Διαχείριση γεγονότων
Δημιουργία γεγονότος
Ακρόαση (ανίχνευση) γεγονότος
Δημιουργία ακροατή – Κατηγορίες ακροατών
Σύνδεση ακροατή με στοιχείο
Πρακτικές χρήσης ακροατών
Διαχείριση γεγονότων
Το στοιχείο του 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);
}
}
Παράδειγμα - 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
Υλοποίηση με 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();
}}
Παράδειγμα
Στο κατάστημα με τους υπολογιστές θέλουμε να
δημιουργήσουμε μια φόρμα που θα κάνει τα
ακόλουθα
Θα διαβάζει από αρχείο όλους τους υπολογιστές και
θα τους εμφανίζει σε μια λίστα, τυπώνοντας μόνο το
μοντέλο του υπολογιστή
Θα επιτρέπει να επιλέξουμε ένα μόνο υπολογιστή και
Αν πατήσουμε το κουμπί Details θα μας δείχνει σε
ξεχωριστό παράθυρο τις λεπτομέρειες του
υπολογιστή.
Πόσες φόρμες χρειαζόμαστε
MainFrame OrderFrame ProductFrame
createOrder addProduct
setVisible(true) setVisible(true)
Τι
δημιουργεί Order o = new Order() Product p = new Product()
κάθε
φόρμα;
Περιεχόμενα
Στοιχεία
Περιοχές κειμένου
Κουμπιά
Λίστες επιλογών
Παράθυρα διαλόγου
Παράθυρα επιβεβαίωσης
Παράθυρο επιλογής αρχείου
Παράθυρο επιλογής χρώματος
Τα μέρη ενός γραφικού περιβάλλοντος
GUI Σύνθεση τάξεων
JFrame JFrame
JPanel containers
JPanel
JButton
JButton JLabel
JLabel
components
Component (Canvas)
Components (Buttons)
Components (TextFields)
Components (Labels)
Παράδειγμα - Components
Checkbox
Label Button
Choice Scrollbar
Button
Checkbox
CheckboxGroup
Παράδειγμα - Layout Managers
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)
Αντικείμενα - Τάξεις
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;
Περιγράμματα - Borders
Οι αντίστοιχες τάξεις βρίσκονται στο πακέτο javax.swing.border
BevelBorder (υπερυψωμένο ή βυθισμένο), CompoundBorder
(διπλό) EmptyBorder (διάφανο), TitledBorder κ.ά.
Panel p=new Panel();
BevelBorder bb = new BevelBorder (BevelBorder.RAISED);
p.setBorder(bb);
Τοποθέτηση components στο JPanel
Ορισμός Layouts
Κάθε παράθυρο (container) έχει ένα
προκαθορισμένο τρόπο τοποθέτησης στοιχείων
(components)
Τα JPanel έχουν προκαθορισμένα FlowLayout
Για κάθε παράθυρο ορίζουμε ένα layout με τη
μέθοδο setLayout
myPanel.setLayout(new BorderLayout());
ή
this.getContentPane().setLayout(new
GridLayout(2,2));
Ενδεικτικά layouts
FlowLayout GridLayout BorderLayout
n
CardLayout GridBagLayout
NORTH
p1: JPanelFlowLayout
contentPane: JPanel
BorderLayout
CENTER t: JTextArea
Συνδυασμός
JFrame f = new JFrame(“Frame1”);
MENUS
Άλλα COMPONENTS
JComboBox JColorChooser
ImageIcon
JInternalFrame
JDialog
JFileChooser
Άλλα COMPONENTS
JScrollBar
JLabel JList
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);
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);
}
Λίστες επιλογών
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;
}
}
Μενού επιλογών
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);
Διαχείριση γεγονότων
Περιεχόμενα
Διαχείριση γεγονότων
Δημιουργία γεγονότος
Ακρόαση (ανίχνευση) γεγονότος
Δημιουργία ακροατή – Κατηγορίες ακροατών
Σύνδεση ακροατή με στοιχείο
Πρακτικές χρήσης ακροατών
Διαχείριση γεγονότων
Το στοιχείο του 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);
}
}
Β) Ανίχνευση γεγονότων
Για να μπορεί ένα στοιχείο να ανιχνεύει γεγονότα θα
πρέπει να του προσθέσουμε τον αντίστοιχο ακροατή
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
createOrder addProduct
setVisible(true) setVisible(true)
Τι
δημιουργεί 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
Μπορούμε να δηλώσουμε και να χρησιμοποιήσουμε
δικά μας νήματα.
4
Πότε χρειάζομαι threads
Όταν η εφαρμογή μου έχει GUI
Τα νήματα που αφορούν το GUI διαχειρίζονται τις ενέργειες του χρήστη
και αναθέτουν τις εργασίες σε άλλα νήματα
Το GUI συνεχίζει να αποκρίνεται στις ενέργειες του χρήστη ακόμη κι αν
τρέχουν άλλα νήματα
Όταν η εφαρμογή μου πρέπει να αποκρίνεται ασύγχρονα (π.χ.
Network based applications)
Τα δεδομένα που έρχονται από το δίκτυο μπορεί να έρχονται χωρίς
ομαλή ροή
Ένα νήμα μπορεί να ελέγχει την πόρτα εισόδου δεδομένων
Όποτε έρθουν δεδομένα το νήμα ολοκληρώνει τη διαχείρισή τους ή την
αναθέτει σε άλλο νήμα
Η εφαρμογή μας τρέχει σε άλλο νήμα
6
Καταστάσεις ενός thread
yield(), or Running
time out run() returns
Thread created start()
New Ready run() join() Finished
interrupt() sleep()
Target wait()
finished
Thread Object
run()
8
Ένα Thread για κάθε Task
Ένα Thread μπορεί να είναι αντικείμενο της κλάσης
Thread ή δικών μας κλάσεων που κληρονομούν τη
Thread
Συχνά οι δικές μας κλάσεις μπορεί να έχουν δική τους
κληρονομικότητα, και ταυτόχρονα να θέλουμε να είναι
threads
Τότε χρησιμοποιούμε το Runnable interface
Ένα interface με μοναδική μέθοδο την run()
Χρειαζόμαστε και κάποιον (ένα dummy Thread 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)
13
Κοινή χρήση;
Υπάρχουν θέματα συγχρονισμού (ταυτόχρονης
πρόσβασης στον κοινόχρηστο χώρο) που πρέπει να
ληφθούν υπόψη.
Για να αντιληφθούμε καλύτερα τα νήματα θεωρούμε δύο
μόνο αντικείμενα που μοιράζονται τον κοινό χώρο: Το
αντικείμενο Thread της Java που ελέγχει το χώρο
(ελεγκτής) και ένα αντικείμενο που περιέχει τη μέθοδο
που θα εκτελέσουμε παράλληλα (νήμα).
Το αντικείμενο νήμα έχει μια μέθοδο run η οποία:
πρέπει να είναι public, να μην παίρνει ορίσματα, να μην
επιστρέφει τιμές και να μην παράγει εξαιρέσεις.
Το αντικείμενο ελεγκτής φτιάχνει το νήμα, το ξεκινά
(καλώντας τη run) και το καταστρέφει μόλις τελειώσει.
Δήλωση μιας τάξης νήματος
Μια τάξη νήμα υλοποιεί τη διεπαφή Runnable (ορίζει μια
μέθοδο run).
Περιέχει μια σημαία (flag) επιτυχούς ολοκλήρωσης της
διεργασίας.
Μέσα στη run υλοποιεί την παράλληλη διεργασία και στο
τέλος της ενημερώνει τη σημαία.
class Animation implements Runnable {
boolean finished;
public void run( ) {
...
finished=true;
}
}
}
}
Παράδειγμα
Δημιουργήστε ένα GUI με 3 buttons και
ένα text field
Με το start: θα ξεκινά ένα thread που θα
τυπώνει την τρέχουσα ώρα και
ημερομηνία στο text field κάθε 1 sec.
Με το stop: το thread θα σταματά
Με το reset: θα καθαρίζει το text field
20
Συγχρονισμός νημάτων
Έστω ένας τραπεζικός λογαριασμός με ένα αρχικό ποσό, ένα νήμα
που κάνει κατάθεση και δύο νήματα που κάνουν ανάληψη
Παράδειγμα
Ο 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)
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
28
Τεκμηρίωση κώδικα
javadoc
29
Σχόλια (Comments)
Σχόλια είναι σημειώσεις σε φυσική γλώσσα
και όχι source code.
Τα Comments χρησιμοποιούνται για να:
Τεκμηριώνουμε: τον σκοπό και τους στόχους του
προγράμματος, τον author, ιστορικά στοιχεία για
τις αναθεωρημένες εκδώσεις του code (revision
history), copyright notices, κτλ.
Περιγράφουμε: fields, constructors, και methods
Την επεξήγηση μη καθαρών σημείων του code
Προσωρινός σχολιασμός μέρους του code, σαν
υπενθύμιση για μελλοντική χρήση
Μορφές Σχολίων
Σχόλια Τεκμηρίωσης
Μπορούμε να χρησιμοποιήσουμε το 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;
}
}
Δημιουργία τεκμηρίωσης
37
Παράδειγμα
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; }
}
Πλεονεκτήματα
Αντικειμενοστραφής κώδικας
Κάθε αντικείμενο της εσωτερικής κλάσης έχει
πρόσβαση στα μέλη της εξωτερικής κλάσης
Ταυτόχρονα είναι ένα ξεχωριστό αντικείμενο.
Ομαδοποίηση της συμπεριφοράς
π.χ. Ένας αλγόριθμος διάσχισης σε ένα 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 δεν κάνει τίποτε
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!"));
}
}
<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
Container getContentPane()
Επιστρέφει το ContentPane του applet
void setJMenuBar(JMenuBar menuBar)
Προσθέτει μενού στο applet
void setLayout(LayoutManager manager)
Ορίζει τη διάταξη στο applet
System.out.println(String s)
Εμφανίζει το μήνυμα σε μια ξεχωριστή κονσόλα
Design patterns
25
Στόχοι
Codify good design
Να κάνουμε όσο πιο γενική γίνεται τη σχεδίαση μιας λύσης
Give design structures explicit names
Να δημιουργήσουμε ένα κοινό λεξικό
Να μειώσουμε την πολυπλοκότητα
Capture and preserve design information
Να διατηρήσουμε τη δομή του προγράμματος
Να βελτιώσουμε την τεκμηρίωση
Facilitate restructuring/refactoring
Να βελτιώσουμε την ανεξαρτησία των λύσεων
Να μειώσουμε το χρόνο υλοποίησής τους, χτίζοντας σε
προκαθορισμένα σχέδια
Παραδείγματα
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() } }
Subject
Abstract Factory
AbstractFactory
Structure Client
+createProductA()
* AbstractProductA * *
+createProductB()
*
*
ProductA1 ProductA2
«instantiate»
ConcreteFactory1 ConcreteFactory2
«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
Πλεονεκτήματα/Μειονεκτήματα
+ 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
Java Enterprise
Technologies
H aρχιτεκτονική του Web
Αρχιτεκτονική client/server
Database
Server
Εφαρμογή
στον Client Database
Server
Driver Driver
Database
Driver Server
Εφαρμογή
Εφαρμογή
στον Client
στο Server Database
Server
Driver
Απαιτήσεις αρχιτεκτονικής 3-tier
Ανάπτυξη της διεπαφής με το χρήστη
(user-interface)
Ανάπτυξη της εφαρμογής που θα συνδέει
το user-interface με τη βάση δεδομένων
(application logic)
Ανάπτυξη της βάσης δεδομένων
(database schema)
Java EE
Umesh Bellur
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
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 Beans
69
Java Beans
Επαναχρησιμοποιήσιμα προγράμματα.
Αποτελούν την απάντηση της Java στα ActiveX
components.
Είναι σύνθετα αντικείμενα (π.χ. κουμπιά, μπάρες
κύλισης, ημερολόγια, επεξεργαστές κειμένου,
λογιστικά φύλλα κλπ.) η συμπεριφορά των οποίων
μπορεί να καθοριστεί.
Τα Java Beans μπορούν να αγοραστούν και να
χρησιμοποιηθούν μέσα από ένα γραφικό
περιβάλλον ανάπτυξης εφαρμογών, χωρίς ειδικές
γνώσεις προγραμματισμού.
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
EJB Architecture
Enterprise JavaBeans
Enterprise JavaBeans
Stateless Stateful
Συνολικά
79
Ενδεικτική αρχιτεκτονική μιας
Java EE εφαρμογής
Web Server EJB Server
DB & EIS
Resources
Stand-alone
Προγραμματισμός ΙΙ
(Java)
Επανάληψη
1ο μάθημα
Κλάσεις
Δήλωση κλάσης,
Δήλωση χαρακτηριστικών, μεθόδων
Αντικείμενα
Δημιουργία αντικειμένου
Κλήση μεθόδων, χαρακτηριστικών
Έλεγχος πρόσβασης (ενθυλάκωση)
}
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();
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 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
16
Δομή μεθόδου
πρόσβαση τύποςΕπιστροφής όνομαΜεθόδου (τυπος1 παράμετρος1, …)
{
…
}
17
attribute
method
return type
Υπερφόρτωση μεθόδων
Σε μια τάξη μπορούμε να ξαναχρησιμοποιήσουμε το ίδιο
όνομα για μεθόδους που έχουν ελαφρώς διαφορετική
συμπεριφορά
Διαφορετικούς τύπους ορισμάτων
Διαφορετικό πλήθος ορισμάτων
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
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
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
36
H κλάση File
Είναι η βασική κλάση για αρχεία και φακέλους
Μέθοδοι της File
exists: ελέγχει αν υπάρχει το αρχείο
canRead: ελέγχει αν μπορούμε να διαβάσουμε από το αρχείο
canWrite: ελέγχει αν μπορούμε να γράψουμε στο αρχείο
delete: διαγράφει το αρχείο και επιστρέφει true (αν πετύχει)
length: επιστρέφει το μέγεθος του αρχείου σε bytes
getName: επιστρέφει το όνομα του αρχείου (μόνο)
getPath: επιστρέφει το πλήρες μονοπάτι του αρχείου
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
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
43
Αντικείμενα εξαιρέσεων
To keyword throw προκαλεί τα ακόλουθα γεγονότα:
εκτελεί την έκφραση new και δημιουργεί ένα αντικείμενο που δεν
θα υπήρχε κανονικά
Το αντικείμενο αυτό επιστρέφεται στην ουσία από την μέθοδο ή
το block μέσα στο οποίο δημιουργήθηκε μολονότι η μέθοδος δεν
έχει δηλωθεί να επιστρέφει παραμέτρους αυτού του τύπου και τα
blocks δεν έχουν φυσικά παραμέτρους που να επιστρέφουν
Το πρόγραμμα βγαίνει από τη μέθοδο ή το block.
Τα αντικείμενα exception που «ρίχνονται» μπορεί να
είναι διάφορων τύπων, ανάλογα το είδος της εξαίρεσης
Κάθε αντικείμενο κωδικοποιεί στα πεδία του όλη την
πληροφορία που αφορά την εξαίρεση, ώστε ο
μηχανισμός διαχείρισης εξαιρέσεων στα ψηλότερα
επίπεδα να μπορεί να πάρει τις κατάλληλες αποφάσεις
44
Σύλληψη εξαίρεσης
Όταν ρίχνουμε μία εξαίρεση πρέπει στα υψηλότερα
επίπεδα κάποιο μπλοκ κώδικα να την ανιχνεύσει και να
την διαχειριστεί.
Προστατευόμενη περιοχή είναι ένα κομμάτι κώδικα
που μπορεί να ρίξει εξαιρέσεις και που ακολουθείται από
κώδικα που διαχειρίζεται αυτές τις εξαιρέσεις.
Μια προστατευόμενη περιοχή μπορεί να ανιχνεύσει ένα
ή περισσότερους τύπους εξαιρέσεων και
να τους διαχειριστεί ή
να τους ρίξει ακόμη πιο πάνω (με νέο throw)
45
Προστατευόμενη περιοχή - try
Ένα τέτοιο μπλοκ ονομάζεται try block αφού εκεί
δοκιμάζουμε να κάνουμε κλήσεις σε διάφορες
«επικίνδυνες μεθόδους»
Το try block είναι ένα κανονικό scoper που περικλείεται
από την κωδική λέξη try
try {
// κώδικας που παράγει εξαιρέσεις
}
Προστασία από εξαιρέσεις: Bάζουμε όλον τον
«επικίνδυνο» κώδικα σε ένα try block και πιάνουμε όλες
τις εξαιρέσεις στο ίδιο μέρος.
46
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
Υπέρβαση μεθόδων
Υπερβαίνουμε τη μέθοδο, δηλώνοντάς την ΚΑΙ στην
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
Τάξεις
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);
Το παράθυρο JDialog
Συμπεριφέρεται όπως και το JFrame
JDialog dialog = new JDialog(myFrame, "Dialog Frame");
JLabel label = new JLabel("This is a message“);
dialog.getContentPane().add(label);
dialog.setVisible(true);
Πίνακας
Εισαγωγή
Εισαγωγή με έλεγχο διπλοτύπων
64
Διάταξη
Η διάταξη στους ακεραίους είναι δεδομένη
Τι γίνεται όμως με τις δικές μας κλάσεις;
Πώς μπορούμε να ορίσουμε διάταξη στα αντικείμενά
τους;
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);
69
Διεπαφές – υλοποιήσεις και παρελθόν
Διεπαφή Υλοποιήσεις Παλιότερες
υλοποιήσεις
Set HashSet TreeSet
Υλοποιήσεις
Υλοποιήσεις
WeakHashMap
είναι μια
υλοποίηση του
Map που καλεί
τον garbage
collector όταν
ένα κλειδί δε
χρησιμοπείται
πλέον
11ο Μάθημα
Πολυνηματικές εφαρμογές
Ορισμοί
Έλεγχος νήματος
Συγχρονισμός νημάτων
Threads - Νήματα
Τα threads επιτρέπουν εργασίες να τρέχουν παράλληλα
με την κύρια εφαρμογή
Είναι διεργασίες που τρέχουν στον ίδιο χώρο
διευθύνσεων: μοιράζονται τις μεταβλητές στιγμιοτύπων,
αλλά διατηρούν και τοπικές μεταβλητές
Χρησιμοποιούνται από το JVM σε συγκεκριμένες
περιπτώσεις
Όταν φορτώνουμε μια εικόνα ή ένα ήχο μέσα από ένα applet.
Όταν καλούμε την update του αντικειμένου graphics
Μπορούμε να δηλώσουμε και να χρησιμοποιήσουμε
δικά μας νήματα.
Μέθοδοι
run(): το βασικό σύνολο εντολών του νήματος.
Ενεργοποιείται με το start()
static void sleep(milliseconds): σταματά
προσωρινά την εκτέλεση του νήματος
void interrupt(): διακόπτει το νήμα
boolean interrupted(): ελέγχει αν το νήμα
εξακολουθεί να είναι σταματημένο ή
ξαναξεκίνησε
final void otherThread.join(): διακόπτει το τρέχον
νήμα μέχρι να τελειώσει το otherThread
12ο μάθημα
Επικοινωνία με δικτυακές πηγές
Ανάγνωση από πηγή
Σύνδεση με πηγή
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();