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

Στατικές τάξεις και εσωτερικές τάξεις στην Ιάβα

Ένθετα μαθήματα είναι τάξεις που δηλώνονται ως μέλη άλλων τάξεων ή πεδίων. Τα μαθήματα ένθεσης είναι ένας τρόπος για να οργανώσετε καλύτερα τον κώδικά σας. Για παράδειγμα, ας υποθέσουμε ότι έχετε μια μη ένθετη τάξη (επίσης γνωστή ως υψηλού επιπέδου τάξη) που αποθηκεύει αντικείμενα σε έναν πίνακα με δυνατότητα αλλαγής μεγέθους, ακολουθούμενο από μια κλάση επαναληπτών που επιστρέφει κάθε αντικείμενο. Αντί να ρυπαίνετε το χώρο ονομάτων της κλάσης ανώτατου επιπέδου, θα μπορούσατε να δηλώσετε την κλάση επαναληπτικών ως μέλος της κλάσης συλλογής πίνακα με δυνατότητα αλλαγής μεγέθους Αυτό λειτουργεί επειδή τα δύο είναι στενά συνδεδεμένα.

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

Αποφύγετε διαρροές μνήμης σε ένθετες τάξεις

Δείτε επίσης τη συμβουλή Java που σχετίζεται με αυτό το σεμινάριο, όπου θα μάθετε γιατί οι ένθετες τάξεις είναι ευάλωτες σε διαρροές μνήμης.

Στατικές τάξεις σε Java

Σε μου Java 101 tutorial Μαθήματα και αντικείμενα στην Java, μάθατε πώς να δηλώνετε στατικά πεδία και στατικές μεθόδους ως μέλη μιας τάξης. Στην αρχικοποίηση κλάσης και αντικειμένων στην Java, μάθατε πώς να δηλώνετε στατικούς αρχικοποιητές ως μέλη μιας τάξης. Τώρα θα μάθετε πώς να δηλώνετε στατικές τάξεις. Επίσημα γνωστή ως τάξεις στατικών μελών, αυτές είναι ένθετες τάξεις που δηλώνετε στο ίδιο επίπεδο με αυτές τις άλλες στατικές οντότητες, χρησιμοποιώντας το στατικός λέξη-κλειδί. Ακολουθεί ένα παράδειγμα δήλωσης στατικής τάξης μέλους:

 τάξη C {static int f; στατικό κενό m () {} στατικό {f = 2; } στατική τάξη D {// member}} 

Αυτό το παράδειγμα εισάγει κατηγορία ανώτατου επιπέδου ντο με στατικό πεδίο φά, στατική μέθοδος Μ(), ένα στατικό αρχικοποιητή και μια κατηγορία στατικών μελών ρε. Σημειώσε ότι ρε είναι μέλος του ντο. Το στατικό πεδίο φά, στατική μέθοδος Μ(), και ο στατικός αρχικοποιητής είναι επίσης μέλη του ντο. Δεδομένου ότι όλα αυτά τα στοιχεία ανήκουν στην τάξη ντο, είναι γνωστό ως κλειστή τάξη. Τάξη ρε είναι γνωστό ως το κλειστή τάξη.

Κανόνες περίφραξης και πρόσβασης

Παρόλο που είναι κλειστό, μια τάξη στατικού μέλους δεν μπορεί να έχει πρόσβαση στα πεδία παρουσίας της κλειστής τάξης και να επικαλεστεί τις μεθόδους εμφάνισης της. Ωστόσο, μπορεί να έχει πρόσβαση στα στατικά πεδία της κλειστής τάξης και να επικαλεστεί τις στατικές μεθόδους της, ακόμη και εκείνα τα μέλη που έχουν δηλωθεί ιδιωτικός. Για επίδειξη, η Λίστα 1 δηλώνει ένα EnclosingClass με ένθετο SMClass.

Λίστα 1. Δήλωση στατικής τάξης μέλους (EnclosingClass.java, έκδοση 1)

 τάξη EnclosingClass {private static String s; ιδιωτικό στατικό κενό m1 () {System.out.println (s); } στατικό κενό m2 () {SMClass.accessEnclosingClass (); } στατική κλάση SMClass {static void accessEnclosingClass () {s = "Κλήθηκε από τη μέθοδο πρόσβασης SMClass's AccessEnclosingClass ()"; m1 (); } άκυρη πρόσβασηEnclosingClass2 () {m2 (); }}} 

Η Λίστα 1 δηλώνει μια κατηγορία ανώτατου επιπέδου που ονομάζεται EnclosingClass με πεδίο κλάσης μικρό, μέθοδοι τάξης m1 () και m2 (), και στατική τάξη μέλους SMClass. SMClass δηλώνει τη μέθοδο κλάσης accessEnclosingClass () και μέθοδο εμφάνισης accessEnclosingClass2 (). Σημειώστε τα εξής:

  • m2 ()Επίκληση της SMClass'μικρό accessEnclosingClass () η μέθοδος απαιτεί το SMClass. πρόθεμα επειδή accessEnclosingClass () δηλώνεται στατικός.
  • accessEnclosingClass () έχει πρόσβαση EnclosingClass'μικρό μικρό πεδίο και καλέστε το m1 () μέθοδος, παρόλο που και οι δύο έχουν δηλωθεί ιδιωτικός.

Η λίστα 2 παρουσιάζει τον πηγαίο κώδικα σε ένα SMCDemo κλάση εφαρμογών που δείχνει πώς να καλέσετε SMClass'μικρό accessEnclosingClass () μέθοδος. Δείχνει επίσης τον τρόπο δημιουργίας SMClass και επικαλέστε το accessEnclosingClass2 () μέθοδος παρουσίας.

Λίστα 2. Επίκληση μεθόδων στατικής τάξης μέλους (SMCDemo.java)

 δημόσια τάξη SMCDemo {public static void main (String [] args) {EnclosingClass.SMClass.accessEnclosingClass (); EnclosingClass.SMClass smc = νέο EnclosingClass.SMClass (); smc.accessEnclosingClass2 (); }} 

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

Συγκεντρώστε τις λίστες 1 και 2 ως εξής:

 javac * .java 

Όταν συντάσσετε μια κλάση εγκλεισμού που περιέχει μια κλάση στατικού μέλους, ο μεταγλωττιστής δημιουργεί ένα αρχείο κλάσης για την κλάση στατικού μέλους του οποίου το όνομα αποτελείται από το όνομα της κλάσης που περικλείει, έναν χαρακτήρα δολαρίου και το όνομα της τάξης στατικού μέλους. Σε αυτήν την περίπτωση, η συλλογή αποτελεσμάτων σε EnclosingClass $ SMCClass.class και EnclosingClass.class.

Εκτελέστε την εφαρμογή ως εξής:

 java SMCDemo 

Πρέπει να παρατηρήσετε την ακόλουθη έξοδο:

 Κλήθηκε από τη μέθοδο AccessEnclosingClass () SMClass Κλήθηκε από τη μέθοδο AccessEnclosingClass () SMClass 

Παράδειγμα: Στατικές τάξεις και Java 2D

Java τυπική βιβλιοθήκη τάξης είναι μια βιβλιοθήκη χρόνου εκτέλεσης αρχείων τάξεων, η οποία αποθηκεύει συγκεντρωμένες τάξεις και άλλους τύπους αναφοράς. Η βιβλιοθήκη περιλαμβάνει πολλά παραδείγματα τάξεων στατικών μελών, μερικά από τα οποία βρίσκονται στις τάξεις γεωμετρικού σχήματος Java 2D που βρίσκονται στο java.awt.geom πακέτο. (Θα μάθετε για τα πακέτα στο επόμενο Java 101 φροντιστήριο.)

ο Ellipse2D τάξη βρέθηκε στο java.awt.geom περιγράφει μια έλλειψη, η οποία ορίζεται από ένα ορθογώνιο πλαισίου με όρους (x, y) πάνω-αριστερή γωνία μαζί με πλάτος και ύψος. Το ακόλουθο τμήμα κώδικα δείχνει ότι βασίζεται η αρχιτεκτονική αυτής της κλάσης Φλοτέρ και Διπλό τάξεις στατικών μελών, τις οποίες και οι δύο υποκατηγορίες Ellipse2D:

 δημόσια αφηρημένη κλάση Ellipse2D επεκτείνει το RectangularShape {δημόσια στατική κλάση Float επεκτείνει το Ellipse2D υλοποιεί σειριακά {δημόσια float x, y, πλάτος, ύψος; public Float () {} public Float (float x, float y, float w, float h) {setFrame (x, y, w, h); } δημόσιο διπλό getX () {return (double) x; } // πρόσθετες μέθοδοι εμφάνισης} δημόσια στατική κλάση Διπλή επέκταση Το Ellipse2D υλοποιεί σειριακές δυνατότητες {δημόσιο διπλό x, y, πλάτος, ύψος; δημόσιο διπλό () {} δημόσιο διπλό (διπλό x, διπλό, διπλό, διπλό h) {setFrame (x, y, w, h); } δημόσιο διπλό getX () {return x; } // πρόσθετες μέθοδοι παρουσίας} δημόσια boolean περιέχει (διπλά x, διπλά y) {// ...} // πρόσθετες μεθόδους παρουσίας που μοιράζονται οι Float, Double και άλλες // Ellipse2D υποκατηγορίες} 

ο Φλοτέρ και Διπλό μαθήματα επεκτείνονται Ellipse2D, παρέχοντας floating-point και double-precision floating-point Ellipse2D υλοποιήσεις. Οι προγραμματιστές χρησιμοποιούν Φλοτέρ για να μειώσετε την κατανάλωση μνήμης, ειδικά επειδή ίσως χρειαστείτε χιλιάδες ή περισσότερα από αυτά τα αντικείμενα για να δημιουργήσετε μια μονή 2D σκηνή. Χρησιμοποιούμε Διπλό όταν απαιτείται μεγαλύτερη ακρίβεια.

Δεν μπορείτε να υποδείξετε την περίληψη Ellipse2D τάξη, αλλά μπορείτε είτε να δημιουργήσετε ένα παράδειγμα Φλοτέρ ή Διπλό. Μπορείτε επίσης να επεκτείνετε Ellipse2D για να περιγράψετε ένα προσαρμοσμένο σχήμα που βασίζεται σε έλλειψη.

Για παράδειγμα, ας υποθέσουμε ότι θέλετε να εισαγάγετε ένα Κύκλος2D τάξη, η οποία δεν υπάρχει στο java.awt.geom πακέτο. Το παρακάτω τμήμα κώδικα δείχνει πώς θα δημιουργήσετε ένα Ellipse2D αντικείμενο με εφαρμογή κινητής υποδιαστολής:

 Ellipse2D e2d = νέο Ellipse2D.Float (10.0f, 10.0f, 20.0f, 30.0f); 

Το επόμενο τμήμα κώδικα δείχνει πώς θα δημιουργήσετε ένα Ellipse2D αντικείμενο με εφαρμογή κυμαινόμενου σημείου διπλής ακρίβειας:

 Ellipse2D e2d = νέο Ellipse2D. Διπλό (10.0, 10.0, 20.0, 30.0); 

Τώρα μπορείτε να καλέσετε οποιαδήποτε από τις μεθόδους που δηλώνονται στο Φλοτέρ ή Διπλό επικαλούμενος τη μέθοδο που επιστράφηκε Ellipse2D αναφορά (π.χ., e2d.getX ()). Με τον ίδιο τρόπο, μπορείτε να επικαλεστείτε οποιαδήποτε από τις κοινές μεθόδους Φλοτέρ και Διπλό, και τα οποία δηλώνονται στο Ellipse2D. Ένα παράδειγμα είναι:

 Περιεχόμενα e2d. (2.0, 3.0) 

Αυτό ολοκληρώνει την εισαγωγή στις κατηγορίες στατικών μελών. Στη συνέχεια θα εξετάσουμε εσωτερικές τάξεις, οι οποίες είναι μη στατικές τάξεις μελών, τοπικές τάξεις ή ανώνυμες τάξεις. Θα μάθετε πώς να εργάζεστε και με τους τρεις τύπους εσωτερικής τάξης.

λήψη Λήψη του κώδικα Λήψη του πηγαίου κώδικα για παραδείγματα σε αυτό το σεμινάριο. Δημιουργήθηκε από τον Jeff Friesen για το JavaWorld.

Εσωτερικές τάξεις, τύπος 1: Κατηγορίες μη στατικών μελών

Έχετε μάθει στο παρελθόν στο Java 101 σειρά για τον τρόπο δήλωσης μη στατικών πεδίων, μεθόδων και κατασκευαστών ως μελών μιας τάξης. Μπορείτε επίσης να δηλώσετε μη στατικές τάξεις μελών, οι οποίες είναι ένθετες μη στατικές τάξεις που δηλώνετε στο ίδιο επίπεδο με πεδία παρουσίας, μεθόδους και κατασκευαστές. Εξετάστε αυτό το παράδειγμα:

 τάξη C {int f; κενό m () {} C () {f = 2; } τάξη Δ {// μέλη}} 

Εδώ, παρουσιάζουμε κορυφαία τάξη ντο με πεδίο παρουσίας φά, μέθοδος παρουσίας Μ(), κατασκευαστής και μη στατική τάξη μέλους ρε. Όλες αυτές οι οντότητες είναι μέλη της τάξης ντο, που τους περικλείει. Ωστόσο, σε αντίθεση με το προηγούμενο παράδειγμα, αυτές οι οντότητες παρουσίας σχετίζονται με περιπτώσεις τουντο και όχι με το ντο η ίδια η τάξη.

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

Λίστα 3. Δηλώστε μια κλάση που περικλείει μια ένθετη μη στατική τάξη μέλους (EnclosingClass.java, έκδοση 2)

 τάξη EnclosingClass {private String s; ιδιωτικό κενό m () {System.out.println (s); } κλάση NSMClass {void accessEnclosingClass () {s = "Κλήθηκε από τη μέθοδο AccessEnclosingClass () του NSMClass"; Μ(); }}} 

Η λίστα 3 δηλώνει μια κατηγορία ανώτατου επιπέδου που ονομάζεται EnclosingClass με πεδίο παρουσίας μικρό, μέθοδος παρουσίας Μ()και μη στατική τάξη μέλους NSMClass. Επί πλέον, NSMClass δηλώνει τη μέθοδο εμφάνισης accessEnclosingClass ().

Επειδή accessEnclosingClass () είναι μη στατικό, NSMClass πρέπει να δημιουργηθεί πριν από την κλήση αυτής της μεθόδου. Αυτή η παρουσία πρέπει να πραγματοποιηθεί μέσω μιας παρουσίας του EnclosingClass, όπως φαίνεται στην καταχώριση 4.

Λίστα 4. NSMCDemo.java

 δημόσια τάξη NSMCDemo {public static void main (String [] args) {EnclosingClass ec = new EnclosingClass (); ec.new NSMClass (). accessEnclosingClass (); }} 

Λίστα 4's κύριος() πρώτη μέθοδος EnclosingClass και αποθηκεύει την αναφορά του στην τοπική μεταβλητή εκ. ο κύριος() Στη συνέχεια η μέθοδος χρησιμοποιεί το EnclosingClass αναφορά ως πρόθεμα του νέος χειριστή, προκειμένου να δημιουργηθεί NSMClass. ο NSMClass Στη συνέχεια χρησιμοποιείται αναφορά για κλήση accessEnclosingClass ().

Πρέπει να χρησιμοποιήσω το «νέο» με αναφορά στην κλάση που περικλείει;

Πρόθεμα νέος με αναφορά στην κλάση που είναι κλειστή είναι σπάνια. Αντ 'αυτού, συνήθως θα καλέσετε έναν κατασκευαστή μιας κλειστής κλάσης μέσα από έναν κατασκευαστή ή μια μέθοδο παρουσίας της κλάσης που περικλείει.

Συγκεντρώστε τις λίστες 3 και 4 ως εξής:

 javac * .java 

Όταν συντάσσετε μια κλάση εγκλεισμού που περιέχει μια μη στατική τάξη μέλους, ο μεταγλωττιστής δημιουργεί ένα αρχείο κλάσης για την μη στατική τάξη μέλους του οποίου το όνομα αποτελείται από το όνομα της κλάσης που περικλείει, έναν χαρακτήρα δολαρίου και τη μη στατική τάξη μέλους όνομα. Σε αυτήν την περίπτωση, η συλλογή αποτελεσμάτων σε EnclosingClass $ NSMCClass.class και EnclosingClass.class.

Εκτελέστε την εφαρμογή ως εξής:

 java NSMCDemo 

Πρέπει να παρατηρήσετε την ακόλουθη έξοδο:

 Κλήθηκε από τη μέθοδο AccessEnclosingClass () του NSMClass 

Πότε (και πώς) να προκριθείτε "αυτό"

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

Παράδειγμα: Κατηγορίες μη στατικών μελών στο HashMap

Η τυπική βιβλιοθήκη κατηγορίας περιλαμβάνει τάξεις μη στατικών μελών καθώς και τάξεις στατικών μελών. Για αυτό το παράδειγμα, θα δούμε το HashMap class, το οποίο είναι μέρος του Java Συλλογές Framework στο java.util πακέτο. HashMap, η οποία περιγράφει μια εφαρμογή χαρτών που βασίζεται σε κατακερματισμό, περιλαμβάνει πολλές μη στατικές τάξεις μελών.

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

 Το δημόσιο μάθημα HashMap επεκτείνει το AbstractMap υλοποιεί το Map, Cloneable, Serializable {// διάφορα μέλη final class KeySet επεκτείνει το AbstractSet {// διάφορα μέλη} // διάφορα μέλη} 

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

HashMap παρέχει ένα keySet () μέθοδος που δημιουργεί Σύνολο κλειδιών όταν είναι απαραίτητο και επιστρέφει αυτήν την παρουσία ή μια προσωρινή μνήμη. Εδώ είναι η πλήρης μέθοδος: