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

Java 101: Η βασική γλώσσα Java περιλαμβάνει περιοδεία, Μέρος 5

Προηγούμενη 1 2 Σελίδα 2 Σελίδα 2 από 2

Τύπος συμπερασμάτων και γενικοί κατασκευαστές για γενικές και μη γενικές τάξεις

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

 δημόσια τάξη Box {public Box (T t) {// ...}} 

Αυτή η δήλωση καθορίζει γενική κλάση Κουτί με τυπική παράμετρο τύπου μι. Καθορίζει επίσης έναν γενικό κατασκευαστή με τυπική παράμετρο τύπου Τ. Θα μπορούσατε να δημιουργήσετε μια γενική τάξη και να επικαλεστείτε τον κατασκευαστή της ως εξής:

 νέο κουτί ("Aggies") 

Αυτή η έκφραση δημιουργεί μια παρουσία του Κουτί, πέρασμα Μάρμαρο προς την μι. Επίσης, ο μεταγλωττιστής μπαίνει Σειρά όπως και ΤΤο πραγματικό όρισμα τύπου επειδή το επιχείρημα του κατασκευαστή είναι ένα Σειρά αντικείμενο.

Οι μεταγλωττιστές Pre-Java 7 συνάγουν τα επιχειρήματα ενός πραγματικού τύπου κατασκευαστή παρόμοια με αυτά μιας γενικής μεθόδου. Ωστόσο, ο μεταγλωττιστής της Java 7 μπορεί να συμπεράνει τα πραγματικά επιχειρήματα τύπου της γενικής κλάσης που δημιουργούνται σε περιβάλλον χειριστή διαμαντιών. Εξετάστε το ακόλουθο παράδειγμα:

 Box box = νέο κουτί ("Aggies"); 

Όπως επίσης και το συμπέρασμα του τύπου Μάρμαρο για τυπική παράμετρο τύπου μι γενικής τάξης Κουτί, ο τύπος μεταγλωττιστή infers Σειρά για τυπική παράμετρο τύπου Τ του κατασκευαστή αυτής της γενικής τάξης.

Project Coin small change # 8: Επίκληση απλοποιημένης μεθόδου varargs

Πριν από την Java 7, κάθε προσπάθεια επίκλησης varargs (μεταβλητά ορίσματα, επίσης γνωστά ως μεταβλητή αρτηρία) Η μέθοδος με μη επαναπροσδιορίσιμο τύπο varargs προκάλεσε τον μεταγλωττιστή να εμφανίζει προειδοποίηση "μη ασφαλούς λειτουργίας". Για να εξαλειφθεί η πιθανότητα πολλών παρόμοιων μηνυμάτων προειδοποίησης (ένα ανά ιστότοπο κλήσεων), η Java 7 μετέφερε την προειδοποίηση από την τοποθεσία κλήσης στη δήλωση μεθόδου.

Επαναπροσδιόριστοι και μη επαναβεβαιώσιμοι τύποι

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

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

Η καταχώριση 13 καταδεικνύει τη ρύπανση από σωρούς σε ένα περιβάλλον χωρίς varargs.

Λίστα 13. Επίδειξη της ρύπανσης από σωρούς σε ένα περιβάλλον χωρίς varargs

 εισαγωγή java.util.Iterator; εισαγωγή java.util.Set; εισαγωγή java.util.TreeSet; δημόσια τάξη HeapPollutionDemo {public static void main (String [] args) {Set s = new TreeSet (); Ορισμός ss = s; // μη ελεγμένη προειδοποίηση s.add (new Integer (42)) // μια άλλη μη ελεγμένη προειδοποίηση Iterator iter = ss.iterator (); ενώ (iter.hasNext ()) {String str = iter.next (); // ClassCastException ρίξτε System.out.println (str); }}} 

Μεταβλητός δδ έχει παραμετροποιημένο τύπο Σειρά. Οταν ο java.util.Set που αναφέρεται από μικρό έχει ανατεθεί σε δδ, ο μεταγλωττιστής δημιουργεί μια μη ελεγμένη προειδοποίηση. Αυτό συμβαίνει επειδή ο μεταγλωττιστής δεν μπορεί να το προσδιορίσει αυτό μικρό αναφέρεται σε ένα Σειρά πληκτρολογήστε (όχι). Το αποτέλεσμα είναι η ρύπανση από σωρούς. (Ο μεταγλωττιστής επιτρέπει σε αυτήν την ανάθεση να διατηρήσει τη συμβατότητα προς τα πίσω με παλαιότερες εκδόσεις Java που δεν υποστηρίζουν γενικά. Επιπλέον, μετασχηματισμός τύπου διαγραφής Σειρά σε Σειρά, που οδηγεί σε ένα Σειρά ανατίθεται σε άλλο Σειρά.)

Ο μεταγλωττιστής δημιουργεί μια δεύτερη μη ελεγμένη προειδοποίηση στη γραμμή που επικαλείται Σειρά'μικρό Προσθήκη() μέθοδος. Αυτό το κάνει επειδή δεν μπορεί να προσδιορίσει εάν μεταβλητή μικρό αναφέρεται σε ένα Σειρά ή Σειρά τύπος. Αυτή είναι μια άλλη κατάσταση ρύπανσης σωρού. (Ο μεταγλωττιστής επιτρέπει αυτήν την κλήση μεθόδου επειδή η διαγραφή μεταμορφώνεται Σειρά'μικρό boolean add (E ε) μέθοδος για boolean προσθήκη (αντικείμενο o), το οποίο μπορεί να προσθέσει οποιοδήποτε είδος αντικειμένου στο σύνολο, συμπεριλαμβανομένου του java.lang.Integer υποτύπος του java.lang.Object.)

Η ρύπανση του σωρού μπορεί εύκολα να συμβεί σε ένα περιβάλλον varargs. Για παράδειγμα, σκεφτείτε την καταχώριση 14.

Λίστα 14. Επίδειξη ρύπανσης από σωρούς σε ένα πλαίσιο varargs

 εισαγωγή java.util.Arrays; εισαγωγή java.util.List; δημόσια τάξη UnsafeVarargsDemo {public static void main (String [] args) {unsafe (Arrays.asList ("A", "B", "C"), Arrays.asList ("D", "E", "F") ); } στατικό κενό μη ασφαλές (Λίστα ... l) {Object [] oArray = l; oArray [0] = Arrays.asList (νέο διπλό (3.5)); Συμβολοσειρά s = l [0] .get (0); }} 

ο Αντικείμενο [] oArray = l; ανάθεση εισάγει την πιθανότητα ρύπανσης από σωρούς. Μια τιμή που δεν ταιριάζει με τον παραμετροποιημένο τύπο της παραμέτρου varargs μεγάλο μπορεί να αντιστοιχιστεί σε μεταβλητή o Σειρά. Ωστόσο, ο μεταγλωττιστής δεν δημιουργεί μια μη ελεγμένη προειδοποίηση επειδή το έχει ήδη κάνει κατά τη μετάφραση Λίστα ... l προς την Λίστα [] l. Αυτή η ανάθεση είναι έγκυρη επειδή μεταβλητή μεγάλο έχει τον τύπο Λίστα[], ποιοι υπότυποι Αντικείμενο[].

Επίσης, ο μεταγλωττιστής δεν εκδίδει προειδοποίηση ή σφάλμα κατά την εκχώρηση α Λίστα αντικείμενο οποιουδήποτε τύπου σε οποιοδήποτε o Σειράτα συστατικά του πίνακα? για παράδειγμα, oArray [0] = Arrays.asList (νέο διπλό (3.5));. Αυτή η ανάθεση αντιστοιχεί στο πρώτο συστατικό πίνακα του o Σειρά ένα Λίστα αντικείμενο που περιέχει ένα μόνο java.lang. Διπλό αντικείμενο.

ο Συμβολοσειρά s = l [0] .get (0); η ανάθεση είναι προβληματική. Το αντικείμενο που είναι αποθηκευμένο στο στοιχείο πρώτου πίνακα της μεταβλητής μεγάλο έχει τον τύπο Λίστα, αλλά αυτή η ανάθεση αναμένει ένα αντικείμενο τύπου Λίστα. Ως αποτέλεσμα, το JVM ρίχνει java.lang.ClassCastException.

Συντάξτε αυτόν τον πηγαίο κώδικα (javac -Xlint: μη επιλεγμένο UnsafeVarargsDemo.java). Θα πρέπει να παρατηρήσετε την ακόλουθη έξοδο (ελαφρώς αναδιαμορφωμένη για αναγνωσιμότητα) κατά τη μεταγλώττιση στο Java SE 7 ενημέρωση 6:

 UnsafeVarargsDemo.java:8: προειδοποίηση: [unchecked] unchecked generic array create for varargs parameter of type List [] unsafe (Arrays.asList ("A", "B", "C"), ^ UnsafeVarargsDemo.java:12: προειδοποίηση : [μη ελεγμένο] Πιθανή ρύπανση από σωρούς από παραμετροποιημένο τύπο vararg Λίστα στατικών κενού μη ασφαλούς (Λίστα ... l) ^ 2 προειδοποιήσεις 

Στην εισαγωγή μου Java 101 στα γενικά, δήλωσα ότι δεν μπορείτε να χρησιμοποιήσετε παραμέτρους τύπου σε εκφράσεις δημιουργίας πίνακα. Για παράδειγμα, δεν μπορείτε να καθορίσετε στοιχεία = νέο E [μέγεθος];. Ο μεταγλωττιστής αναφέρει ένα μήνυμα "γενικό σφάλμα δημιουργίας πίνακα" όταν προσπαθείτε να το κάνετε. Ωστόσο, εξακολουθεί να είναι δυνατό να δημιουργηθεί ένας γενικός πίνακας, αλλά μόνο σε ένα πλαίσιο varargs, και αυτό είναι που αναφέρεται το πρώτο προειδοποιητικό μήνυμα. Πίσω από τα παρασκήνια, ο μεταγλωττιστής μεταμορφώνεται Λίστα ... l προς την Λίστα [] l και μετά να Λίστα [] l.

Παρατηρήστε ότι η προειδοποίηση για τη ρύπανση σωρού δημιουργείται στο επισφαλής() ιστότοπος δήλωσης της μεθόδου. Αυτό το μήνυμα δεν δημιουργείται στον ιστότοπο κλήσεων αυτής της μεθόδου, όπως συμβαίνει με τους μεταγλωττιστές Java 5 και 6.

Δεν συμβάλλουν όλες οι μέθοδοι varargs στη ρύπανση του σωρού. Ωστόσο, ένα προειδοποιητικό μήνυμα θα εκδοθεί στον ιστότοπο δήλωσης της μεθόδου. Εάν γνωρίζετε ότι η μέθοδος σας δεν συμβάλλει στη σωστή ρύπανση, μπορείτε να καταργήσετε αυτήν την προειδοποίηση δηλώνοντάς την με το @SafeVarargs σχολιασμός - Η Java 7 εισήγαγε το java.lang.SafeVarargs τύπος σχολιασμού. Για παράδειγμα, επειδή δεν υπάρχει τρόπος για το Πίνακες της τάξης asList () μέθοδος για τη συμβολή στη ρύπανση του σωρού, η δήλωση αυτής της μεθόδου έχει επισημανθεί με @SafeVarargs, ως εξής:

 @SafeVarargs δημόσια στατική Λίστα asList (T ... a) 

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

Συμπερασματικά

Το Java 7 βελτίωσε την παραγωγικότητα του προγραμματιστή εισάγοντας την αυτόματη διαχείριση πόρων μέσω της δήλωσης δοκιμής με πόρους μαζί με μια νέα Αυτόματο κλείσιμο διεπαφή, διακόπτης σε σειρά, multi-catch, final rethrow, binary literals, υπογράμμιση σε αριθμητικά γράμματα, αλλαγές στον αλγόριθμο συμπερασμάτων τύπου του μεταγλωττιστή που εισήγαγε τον λεγόμενο τελεστή διαμαντιών και απλοποιημένη επίκληση μεθόδου varargs. Στη συνέχεια στο Java 101: Η επόμενη γενιά Η σειρά είναι μια ματιά στα χαρακτηριστικά λάμδα Java και λειτουργικής γλώσσας διεπαφής.

Αυτή η ιστορία, "Java 101: Η βασική γλώσσα Java διαθέτει περιοδεία, Μέρος 5" δημοσιεύθηκε αρχικά από το JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found