java:generics
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
java:generics [2017/02/07 14:37] – [Interfaces ως παραμετρικοί τύποι δεδομένων] gthanos | java:generics [2020/03/10 09:44] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== Παραμετρικοί τύποι δεδομένων (Generics) ====== | ====== Παραμετρικοί τύποι δεδομένων (Generics) ====== | ||
- | Ένας | + | Ένας |
- | Δείτε το παρακάτω παράδειγμα της κλάσης Box, η οποία θέλουμε να μπορεί να αποθηκεύσει οποιονδήποτε τύπο δεδομένων. | + | Η υιοθέτηση γενικών κλάσεων έχει το πλεονέκτημα ότι μπορεί να αποθηκεύσει αντικείμενα οποιασδήποτε κλάσης, |
+ | |||
+ | ===== Παράδειγμα γενικής κλάσης για την αποθήκευση δεδομένων ===== | ||
+ | |||
+ | Δείτε το παρακάτω παράδειγμα της κλάσης | ||
<code java Box.java> | <code java Box.java> | ||
Line 14: | Line 18: | ||
</ | </ | ||
- | Στο παραπάνω παράδειγμα | + | Ας υποθέσουμε ότι έχετε |
<code java BoxUsage.java> | <code java BoxUsage.java> | ||
Line 22: | Line 26: | ||
| | ||
| | ||
- | String | + | Integer |
} | } | ||
} | } | ||
</ | </ | ||
- | Ο παραπάνω | + | Στο |
- | <code> | + | * να περάσετε |
- | Exception in thread " | + | * να αναθέσετε την επιστρεφόμενη τιμή της μεθόδου //get// σε οποιοδήποτε τύπο δεδομένων. |
- | | + | |
+ | Παρατηρήστε ότι στην τελευταία γραμμή είμαστε υποχρεωμένοι να κάνουμε typecast την | ||
+ | |||
+ | Δείτε τώρα το παρακάτω παράδειγμα κώδικα | ||
+ | |||
+ | <code java BoxUsage.java> | ||
+ | public class BoxUsage | ||
+ | | ||
+ | Box b = new Box(); | ||
+ | | ||
+ | b.set(n); | ||
+ | | ||
+ | } | ||
+ | } | ||
</ | </ | ||
- | Παρατηρήστε επίσης, ότι | + | Η μετατροπή τύπου στην τελευταία γραμμή είναι προφανώς λάθος, διότι επιχειρούμε να αναθέσουμε |
+ | |||
+ | ===== Παράδειγμα παραμετρικής κλάσης ===== | ||
+ | |||
+ | Προκειμένου να αποφύγουμε τα παραπάνω προβλήματα και να είμαστε σίγουροι ότι ο κώδικας που γράφουμε δεν περιέχει λάθη στη χρήση τύπων δεδομένων η Java εισάγει τους παραμετρικούς τύπους δεδομένων, | ||
<code java Box.java> | <code java Box.java> | ||
Line 50: | Line 71: | ||
Η παραπάνω δήλωση της κλάσης //Box// σημαίνει ότι κατά τον ορισμό αντικειμένων της κλάσης αυτά θα πρέπει να προσδιορίζεται ανάμεσα στους χαρακτήρες '<', | Η παραπάνω δήλωση της κλάσης //Box// σημαίνει ότι κατά τον ορισμό αντικειμένων της κλάσης αυτά θα πρέπει να προσδιορίζεται ανάμεσα στους χαρακτήρες '<', | ||
+ | |||
<code java> | <code java> | ||
Box< | Box< | ||
Line 55: | Line 77: | ||
Box< | Box< | ||
</ | </ | ||
+ | |||
Ο τύπος δεδομένων που χρησιμοποιούμε ανάμεσα στους χαρακτήρες '<', | Ο τύπος δεδομένων που χρησιμοποιούμε ανάμεσα στους χαρακτήρες '<', | ||
- | ===== Ονοματολογία παραμέτρων ===== | + | ===== Συνήθης ονοματολογία παραμέτρων ===== |
* E - Element (χρησιμοποείται στο Java Collections Framework) | * E - Element (χρησιμοποείται στο Java Collections Framework) | ||
Line 89: | Line 112: | ||
Note: Recompile with -Xlint: | Note: Recompile with -Xlint: | ||
</ | </ | ||
- | |||
- | ===== Interfaces ως παραμετρικοί τύποι δεδομένων ===== | ||
- | |||
- | Εκτός από κλάσεις μπορούμε να ορίσουμε και διεπαφές ως παραμετρικούς τύπους. Το interface Stack που ορίζεται παρακάτω είναι ένα παράδειγμα παραμετρικού interface το οποίο προδιαγράφει τη λειτουργία της στοίβας. | ||
- | |||
- | <code java Stack.java> | ||
- | interface Stack <T> { | ||
- | public int size(); | ||
- | public boolean isEmpty(); | ||
- | public void push(T obj); | ||
- | public T pop(); | ||
- | public T top(); | ||
- | } | ||
- | </ | ||
- | |||
- | Το interface δηλώνει ότι η στοίβα λαμβάνει ως όρισμα ένα τύπο δεδομένων που αντιστοιχεί στα αντικείμενα που αποθηκεύονται σε αυτή. | ||
- | |||
- | Άλλο παράδειγμα παραμετρικού interface είναι το [[https:// | ||
- | |||
- | <code java> | ||
- | interface Comparable< | ||
- | int compareTo(T o) | ||
- | } | ||
- | </ | ||
- | |||
- | |||
- | ===== Παραμετρικοί τύποι δεδομένων με πολλές παραμέτρους ===== | ||
- | |||
- | Δείτε το παρακάτω παράδειγμα, | ||
- | |||
- | <code java Pair.java> | ||
- | public interface Pair<K, V> { | ||
- | public K getKey(); | ||
- | public V getValue(); | ||
- | public void setKey(K key); | ||
- | public void setValue(V value); | ||
- | } | ||
- | </ | ||
- | <code java OrderedPair.java> | ||
- | public class OrderedPair< | ||
- | |||
- | private K key; | ||
- | private V value; | ||
- | |||
- | public OrderedPair(K key, V value) { | ||
- | this.key = key; | ||
- | this.value = value; | ||
- | } | ||
- | |||
- | public void setKey(K key) { this.key = key; } | ||
- | public void setValue(V value) { this.value = value; } | ||
- | public K getKey() | ||
- | public V getValue() { return value; } | ||
- | } | ||
- | </ | ||
- | |||
- | Με βάση τον παραπάνω κώδικα μπορείτε να δημιουργήσετε αντικείμενα επιμέρους τύπων ως εξής: | ||
- | <code java OrderedPairUsage.java> | ||
- | public class OrderedPairUsage { | ||
- | public static void main(String args[]) { | ||
- | Pair< | ||
- | Pair< | ||
- | OrderedPair< | ||
- | // the following is not allowed | ||
- | Pair< | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | ===== Απλοί παραμετρικοί τύποι δεδομένων (Raw Generic Types) ===== | ||
- | |||
- | Αντικείμενα της κλάσης Box ορίζονται συνήθως σε συνδυασμό με ένα reference τύπο δεδομένων, | ||
- | <code java> | ||
- | Box b = new Box() | ||
- | </ | ||
- | |||
- | Σε αυτή την περίπτωση καταλήγουμε να έχουμε έναν μη-παραμετρικό τύπο δεδομένων. Ο compiler δεν είναι σε θέση να γνωρίζει τον τύπο δεδομένων που θα τοποθετήσετε στο συγκεκριμένο αντικείμενο. Ουσιαστικά η παραπάνω δήλωση ισοδυναμεί με μία δήλωση της μορφής | ||
- | <code java> | ||
- | Box< | ||
- | </ | ||
- | |||
- | Η προσπάθεια μεταγλώττισης του παρακάτω κώδικα καταδεικνύει το παραπάνω | ||
- | <code java BoxUsage.java> | ||
- | public class BoxUsage { | ||
- | | ||
- | Box b = new Box(5); | ||
- | | ||
- | | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | Αν αλλάξετε την γραμμή '' | ||
- | |||
- | Η μη χρήση των παραμετρικών τύπων δεδομένων δυσκολεύει τον compiler να αποφασίσει για την ασφαλή ή μη ασφαλή χρήση των δεδομένων που θα αποθηκευτούν στην κλάση. Δείτε τα παρακάτω παραδείγματα κώδικα | ||
- | |||
- | <code java> | ||
- | Box< | ||
- | Box rawBox = stringBox; | ||
- | </ | ||
- | |||
- | <code java> | ||
- | Box rawBox = new Box(); | ||
- | Box< | ||
- | </ | ||
- | |||
- | <code java> | ||
- | Box< | ||
- | Box rawBox = stringBox; | ||
- | rawBox.set(8); | ||
- | </ | ||
- | |||
- | |||
- | ==== Unchecked Error Messages ==== | ||
- | |||
- | Όπως είπαμε προηγούμενα η μίξη generics με raw types μπορεί να δημιουργήσει warnings κατά την μεταγλώττιση της μορφής | ||
- | < | ||
- | Note: Example.java uses unchecked or unsafe operations. | ||
- | Note: Recompile with -Xlint: | ||
- | </ | ||
- | όπως παρακάτω | ||
- | <code java WarningDemo.java> | ||
- | public class WarningDemo { | ||
- | public static void main(String[] args){ | ||
- | Box< | ||
- | bi = createBox(); | ||
- | } | ||
- | |||
- | static Box createBox(){ | ||
- | return new Box(); | ||
- | } | ||
- | } | ||
- | </ | ||
- | Μεταγλωττίζοντας με το flag '' | ||
- | < | ||
- | WarningDemo.java: | ||
- | found : Box | ||
- | required: Box< | ||
- | bi = createBox(); | ||
- | ^ | ||
- | 1 warning | ||
- | </ | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
+ | | Προηγούμενο: | ||
java/generics.1486478233.txt.gz · Last modified: 2017/02/07 14:37 (external edit)